This commit is contained in:
millmanorama 2017-08-20 18:30:07 -04:00
parent 0961f64892
commit 55dd19b39c
5 changed files with 50 additions and 38 deletions

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.util.Comparator; import java.util.Comparator;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -26,10 +27,10 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Stores the fact that file or an artifact associated with a file had a keyword * Represents the fact that a file or an artifact associated with a file had a
* hit. All instances make both the document id of the Solr document where the * keyword hit. All instances make both the document id of the Solr document
* keyword was found and the object Id available to clients. Artifact keyword * where the keyword was found and the object Id of the file available to
* hits also make the artifact available to clients. * clients. Artifact keyword hits also make the artifact available to clients.
*/ */
class KeywordHit implements Comparable<KeywordHit> { class KeywordHit implements Comparable<KeywordHit> {
@ -38,7 +39,7 @@ class KeywordHit implements Comparable<KeywordHit> {
private final int chunkId; private final int chunkId;
private final String snippet; private final String snippet;
private final long contentID; private final long contentID;
private final BlackboardArtifact artifact; private final boolean hitOnArtifact;
private final String hit; private final String hit;
public String getHit() { public String getHit() {
@ -67,18 +68,18 @@ class KeywordHit implements Comparable<KeywordHit> {
this.solrObjectId = Long.parseLong(solrDocumentId); this.solrObjectId = Long.parseLong(solrDocumentId);
this.chunkId = 0; this.chunkId = 0;
} }
hitOnArtifact = this.solrObjectId < 0;
/* /*
* If the high order bit of the object id is set (ie, it is negative), * If the high order bit of the object id is set (ie, it is negative),
* the hit was in an artifact, look up the artifact. * the hit was in an artifact, look up the artifact.
*/ */
if (this.solrObjectId < 0) { if (hitOnArtifact) {
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase(); SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
this.artifact = caseDb.getBlackboardArtifact(this.solrObjectId); BlackboardArtifact artifact = caseDb.getBlackboardArtifact(this.solrObjectId);
contentID = artifact.getObjectID(); contentID = artifact.getObjectID();
} else { } else {
//else the object id is for content. //else the object id is for content.
this.artifact = null;
contentID = this.solrObjectId; contentID = this.solrObjectId;
} }
} }
@ -113,17 +114,20 @@ class KeywordHit implements Comparable<KeywordHit> {
* @return * @return
*/ */
boolean isArtifactHit() { boolean isArtifactHit() {
return (null != this.artifact); return hitOnArtifact;
} }
/** /**
* If this hit is in the indexed text of an artifact, get that artifact. * If this hit is in the indexed text of an artifact, get that artifact.
* *
* @return The artifact whose indexed text this hit is in, or null if it is * @return The artifact whose indexed text this hit is in.
* not an artifacts hit.
*/ */
BlackboardArtifact getArtifact() { Optional<Long> getArtifactID() {
return this.artifact; if (hitOnArtifact) {
return Optional.of(solrObjectId);
} else {
return Optional.empty();
}
} }
@Override @Override

View File

@ -140,7 +140,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
queryResults = queryRequest.performQuery(); queryResults = queryRequest.performQuery();
} catch (KeywordSearchModuleException | NoOpenCoreException ex) { } catch (KeywordSearchModuleException | NoOpenCoreException ex) {
logger.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS logger.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage()); MessageNotifyUtil.Notify.error(org.sleuthkit.autopsy.keywordsearch.Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage());
return false; return false;
} }
SleuthkitCase tskCase = null; SleuthkitCase tskCase = null;
@ -186,12 +186,16 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
properties.put(TSK_KEYWORD_PREVIEW.getDisplayName(), hit.getSnippet()); properties.put(TSK_KEYWORD_PREVIEW.getDisplayName(), hit.getSnippet());
} }
try {
String hitName = hit.isArtifactHit() String hitName = hit.isArtifactHit()
? hit.getArtifact().getDisplayName() + " Artifact" //NON-NLS ? tskCase.getBlackboardArtifact(hit.getArtifactID().get()).getDisplayName() + " Artifact" //NON-NLS
: contentName; : contentName;
hitNumber++; hitNumber++;
tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), content, queryRequest, queryResults)); tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), content, queryRequest, queryResults));
} catch (TskCoreException ex) {
Exceptions.printStackTrace(ex);
return false;
}
} }
// Add all the nodes to toPopulate at once. Minimizes node creation // Add all the nodes to toPopulate at once. Minimizes node creation

View File

@ -225,9 +225,11 @@ class LuceneQuery implements KeywordSearchQuery {
} }
} }
if (hit.isArtifactHit()) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, hit.getArtifact().getArtifactID())); hit.getArtifactID().ifPresent(artifactID
} -> attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, artifactID))
);
try { try {
bba.addAttributes(attributes); //write out to bb bba.addAttributes(attributes); //write out to bb

View File

@ -417,7 +417,7 @@ final class RegexQuery implements KeywordSearchQuery {
final BlackboardAttribute ccnAttribute = parsedTrackAttributeMap.get(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER)); final BlackboardAttribute ccnAttribute = parsedTrackAttributeMap.get(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
if (ccnAttribute == null || StringUtils.isBlank(ccnAttribute.getValueString())) { if (ccnAttribute == null || StringUtils.isBlank(ccnAttribute.getValueString())) {
if (hit.isArtifactHit()) { if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getArtifact().getArtifactID())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS
} else { } else {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getContentID())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getContentID())); //NON-NLS
} }
@ -480,9 +480,10 @@ final class RegexQuery implements KeywordSearchQuery {
if (snippet != null) { if (snippet != null) {
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet)); attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet));
} }
if (hit.isArtifactHit()) {
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, hit.getArtifact().getArtifactID())); hit.getArtifactID().ifPresent(artifactID
} -> attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, artifactID))
);
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.REGEX.ordinal())); attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.REGEX.ordinal()));

View File

@ -359,7 +359,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
final BlackboardAttribute ccnAttribute = parsedTrackAttributeMap.get(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)); final BlackboardAttribute ccnAttribute = parsedTrackAttributeMap.get(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
if (ccnAttribute == null || StringUtils.isBlank(ccnAttribute.getValueString())) { if (ccnAttribute == null || StringUtils.isBlank(ccnAttribute.getValueString())) {
if (hit.isArtifactHit()) { if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", searchTerm, hit.getSnippet(), hit.getArtifact().getArtifactID())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", searchTerm, hit.getSnippet(), hit.getArtifactID().get())); //NON-NLS
} else { } else {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getContentID())); //NON-NLS LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getContentID())); //NON-NLS
} }
@ -422,9 +422,10 @@ final class TermsComponentQuery implements KeywordSearchQuery {
if (snippet != null) { if (snippet != null) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet)); attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet));
} }
if (hit.isArtifactHit()) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, hit.getArtifact().getArtifactID())); hit.getArtifactID().ifPresent(
} artifactID -> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, artifactID))
);
// TermsComponentQuery is now being used exclusively for substring searches. // TermsComponentQuery is now being used exclusively for substring searches.
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.SUBSTRING.ordinal())); attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.SUBSTRING.ordinal()));
@ -472,7 +473,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
* Creates an attribute of the the given type to the given artifact with a * Creates an attribute of the the given type to the given artifact with a
* value parsed from the snippet for a credit account number hit. * value parsed from the snippet for a credit account number hit.
* *
* @param attributesMap A map of artifact attribute objects, used to avoid * @param attributeMap A map of artifact attribute objects, used to avoid
* creating duplicate attributes. * creating duplicate attributes.
* @param attrType The type of attribute to create. * @param attrType The type of attribute to create.
* @param groupName The group name of the regular expression that was * @param groupName The group name of the regular expression that was