further cleanup and simplify ad hoc search related searches.

This commit is contained in:
millmanorama 2017-02-09 16:49:57 +01:00
parent ab6d8b0b9d
commit 82cd7e6dd9
3 changed files with 62 additions and 46 deletions

View File

@ -123,10 +123,21 @@ class KeywordHit implements Comparable<KeywordHit> {
return this.content; return this.content;
} }
/**
* Is this hit in the indexed text of an artifact.
*
* @return
*/
boolean isArtifactHit() { boolean isArtifactHit() {
return (null != this.artifact); return (null != this.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
* not an artifacts hit.
*/
BlackboardArtifact getArtifact() { BlackboardArtifact getArtifact() {
return this.artifact; return this.artifact;
} }

View File

@ -41,6 +41,7 @@ import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType.LOCATION;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
import org.sleuthkit.autopsy.datamodel.KeyValue; import org.sleuthkit.autopsy.datamodel.KeyValue;
import org.sleuthkit.autopsy.datamodel.KeyValueNode; import org.sleuthkit.autopsy.datamodel.KeyValueNode;
@ -48,6 +49,9 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.KeyValueQu
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
/** /**
@ -64,9 +68,10 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
//common properties (superset of all Node properties) to be displayed as columns //common properties (superset of all Node properties) to be displayed as columns
static final List<String> COMMON_PROPERTIES static final List<String> COMMON_PROPERTIES
= Stream.concat( = Stream.concat(
Stream.of(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, Stream.of(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP, TSK_KEYWORD,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW) TSK_KEYWORD_REGEXP,
TSK_KEYWORD_PREVIEW)
.map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName), .map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName),
Arrays.stream(AbstractAbstractFileNode.AbstractFilePropertyType.values()) Arrays.stream(AbstractAbstractFileNode.AbstractFilePropertyType.values())
.map(Object::toString)) .map(Object::toString))
@ -89,6 +94,15 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
protected boolean createKeys(List<KeyValueQueryContent> toPopulate) { protected boolean createKeys(List<KeyValueQueryContent> toPopulate) {
for (QueryRequest queryRequest : queryRequests) { for (QueryRequest queryRequest : queryRequests) {
/**
* Check the validity of the requested query.
*/
if (!queryRequest.getQuery().validate()) {
//TODO mark the particular query node RED
break;
}
//JMTODO: It looks like this map is not actually used for anything...
Map<String, Object> map = queryRequest.getProperties(); Map<String, Object> map = queryRequest.getProperties();
/* /*
* make sure all common properties are displayed as columns (since * make sure all common properties are displayed as columns (since
@ -97,11 +111,10 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
*/ */
COMMON_PROPERTIES.stream() COMMON_PROPERTIES.stream()
.forEach((propertyType) -> map.put(propertyType, "")); .forEach((propertyType) -> map.put(propertyType, ""));
map.put(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getDisplayName(), map.put(TSK_KEYWORD.getDisplayName(), queryRequest.getQueryString());
queryRequest.getQueryString()); map.put(TSK_KEYWORD_REGEXP.getDisplayName(), !queryRequest.getQuery().isLiteral());
map.put(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getDisplayName(),
!queryRequest.getQuery().isLiteral()); createFlatKeys(queryRequest.getQuery(), toPopulate);
createFlatKeys(queryRequest, toPopulate);
} }
return true; return true;
@ -115,29 +128,21 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
* @return * @return
*/ */
@NbBundle.Messages({"KeywordSearchResultFactory.query.exception.msg=Could not perform the query "}) @NbBundle.Messages({"KeywordSearchResultFactory.query.exception.msg=Could not perform the query "})
private boolean createFlatKeys(QueryRequest queryRequest, List<KeyValueQueryContent> toPopulate) { private boolean createFlatKeys(KeywordSearchQuery queryRequest, List<KeyValueQueryContent> toPopulate) {
/**
* Check the validity of the requested query.
*/
final KeywordSearchQuery keywordSearchQuery = queryRequest.getQuery();
if (!keywordSearchQuery.validate()) {
//TODO mark the particular query node RED
return false;
}
/** /**
* Execute the requested query. * Execute the requested query.
*/ */
QueryResults queryResults; QueryResults queryResults;
try { try {
queryResults = keywordSearchQuery.performQuery(); queryResults = queryRequest.performQuery();
} catch (KeywordSearchModuleException | NoOpenCoreException ex) { } catch (KeywordSearchModuleException | NoOpenCoreException ex) {
logger.log(Level.SEVERE, "Could not perform the query " + keywordSearchQuery.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() + keywordSearchQuery.getQueryString(), ex.getCause().getMessage()); MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage());
return false; return false;
} }
int id = 0; int hitNumber = 0;
List<KeyValueQueryContent> tempList = new ArrayList<>(); List<KeyValueQueryContent> tempList = new ArrayList<>();
for (KeywordHit hit : getOneHitPerObject(queryResults)) { for (KeywordHit hit : getOneHitPerObject(queryResults)) {
/** /**
@ -145,31 +150,33 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
*/ */
Map<String, Object> properties = new LinkedHashMap<>(); Map<String, Object> properties = new LinkedHashMap<>();
Content content = hit.getContent(); Content content = hit.getContent();
String contentName = content.getName();
if (content instanceof AbstractFile) { if (content instanceof AbstractFile) {
AbstractFsContentNode.fillPropertyMap(properties, (AbstractFile) content); AbstractFsContentNode.fillPropertyMap(properties, (AbstractFile) content);
} else { } else {
properties.put(AbstractAbstractFileNode.AbstractFilePropertyType.LOCATION.toString(), content.getName()); properties.put(LOCATION.toString(), contentName);
} }
/** /**
* Add a snippet property, if available. * Add a snippet property, if available.
*/ */
if (hit.hasSnippet()) { if (hit.hasSnippet()) {
properties.put(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getDisplayName(), hit.getSnippet()); properties.put(TSK_KEYWORD_PREVIEW.getDisplayName(), hit.getSnippet());
} }
//JMTODO: I don't understand this comment or the below code...
//@@@ USE ConentHit in UniqueFileMap instead of the below search //@@@ USE ConentHit in UniqueFileMap instead of the below search
//get unique match result files //get unique match result files
// BC: @@@ THis is really ineffecient. We should keep track of this when // BC: @@@ THis is really ineffecient. We should keep track of this when
// we flattened the list of files to the unique files. // we flattened the list of files to the unique files.
final String highlightQueryEscaped = getHighlightQuery(keywordSearchQuery, keywordSearchQuery.isLiteral(), queryResults, content); final String highlightQueryEscaped = getHighlightQuery(queryRequest, queryRequest.isLiteral(), queryResults, content);
String name = content.getName(); String hitName = hit.isArtifactHit()
if (hit.isArtifactHit()) { ? hit.getArtifact().getDisplayName() + " Artifact" //NON-NLS
name = hit.getArtifact().getDisplayName() + " Artifact"; // NON-NLS : contentName;
}
++id; hitNumber++;
tempList.add(new KeyValueQueryContent(name, properties, id, hit.getSolrObjectId(), content, highlightQueryEscaped, keywordSearchQuery, queryResults)); tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), content, highlightQueryEscaped, queryRequest, queryResults));
} }
// Add all the nodes to toPopulate at once. Minimizes node creation // Add all the nodes to toPopulate at once. Minimizes node creation
@ -180,7 +187,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
//cannot reuse snippet in BlackboardResultWriter //cannot reuse snippet in BlackboardResultWriter
//because for regex searches in UI we compress results by showing a content per regex once (even if multiple term hits) //because for regex searches in UI we compress results by showing a content per regex once (even if multiple term hits)
//whereas in bb we write every hit per content separately //whereas in bb we write every hit per content separately
new BlackboardResultWriter(queryResults, queryRequest.getQuery().getKeywordList().getName()).execute(); new BlackboardResultWriter(queryResults, queryRequest.getKeywordList().getName()).execute();
return true; return true;
} }
@ -310,9 +317,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
* @param content File that had the hit. * @param content File that had the hit.
* @param queryStr Query used in search * @param queryStr Query used in search
* @param query Query used in search * @param query Query used in search
* @param hits Full set of search results (for all files! * @param hits Full set of search results (for all files! @@@)
*
* @@@)
*/ */
public KeyValueQueryContent(String name, Map<String, Object> map, int id, long solrObjectId, Content content, String queryStr, KeywordSearchQuery query, QueryResults hits) { public KeyValueQueryContent(String name, Map<String, Object> map, int id, long solrObjectId, Content content, String queryStr, KeywordSearchQuery query, QueryResults hits) {
super(name, map, id); super(name, map, id);

View File

@ -19,19 +19,16 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger;
/** /**
* Stores data about a search before it is done. * Stores data about a search before it is done.
*/ */
class QueryRequest { final class QueryRequest {
private KeywordSearchQuery query; private final KeywordSearchQuery query;
private String queryString; private final String queryString;
private Map<String, Object> map; private final Map<String, Object> queryProperties;
KeywordSearchQuery getQuery() {
return query;
}
/** /**
* NOTE: The below descriptions are based on how it is used in teh code. * NOTE: The below descriptions are based on how it is used in teh code.
@ -40,18 +37,21 @@ class QueryRequest {
* @param id ID that callers simply increment from 0 * @param id ID that callers simply increment from 0
* @param query Query that will be performed. * @param query Query that will be performed.
*/ */
public QueryRequest(Map<String, Object> map, int id, KeywordSearchQuery query) { QueryRequest(Map<String, Object> map, int id, KeywordSearchQuery query) {
this.queryString = query.getEscapedQueryString(); this.queryString = query.getEscapedQueryString();
this.map = map; this.queryProperties = map;
this.query = query; this.query = query;
} }
KeywordSearchQuery getQuery() {
return query;
}
public String getQueryString() { public String getQueryString() {
return queryString; return queryString;
} }
public Map<String, Object> getProperties() { public Map<String, Object> getProperties() {
return map; return queryProperties;
} }
} }