diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchUtil.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchUtil.java new file mode 100644 index 0000000000..b53dedbf02 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchUtil.java @@ -0,0 +1,35 @@ +package org.sleuthkit.autopsy.keywordsearch; + +import java.util.logging.Level; +import java.util.logging.Logger; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.FsContent; +import org.sleuthkit.datamodel.TskException; + +public class KeywordSearchUtil { + + private static final Logger logger = Logger.getLogger(KeywordSearchUtil.class.getName()); + + public static String buildDirName(FsContent f) { + + String dirName = null; + StringBuilder dirNameB = new StringBuilder(); + try { + + Directory pd = f.getParentDirectory(); + + while (pd != null && pd.isRoot() == false) { + dirNameB.insert(0, "/"); + dirNameB.insert(0, pd.getName()); + pd = pd.getParentDirectory(); + } + dirNameB.insert(0, "/"); + + } catch (TskException ex) { + logger.log(Level.WARNING, "Error getting path for fscontent id: " + Long.toString(f.getId()), ex); + } finally { + dirName = dirNameB.toString(); + } + return dirName; + } +} diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java index 9773c537ee..87c3cf7be8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java @@ -22,6 +22,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.response.QueryResponse; @@ -31,19 +33,27 @@ import org.openide.nodes.Node; import org.openide.windows.TopComponent; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; +import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.datamodel.FsContent; import org.sleuthkit.datamodel.SleuthkitCase; public class LuceneQuery implements KeywordSearchQuery { + private static final Logger logger = Logger.getLogger(LuceneQuery.class.getName()); + private String query; public LuceneQuery(String query) { this.query = query; } - - @Override - public void execute() { + + /** + * Just perform the query and return result without updating the GUI + * This utility is used in this class, can be potentially reused by other classes + * @param query + * @return matches List + */ + public List doQuery() throws RuntimeException { List matches = new ArrayList(); boolean allMatchesFetched = false; @@ -80,18 +90,26 @@ public class LuceneQuery implements KeywordSearchQuery { } } catch (SolrServerException ex) { + logger.log(Level.WARNING, "Error executing Lucene Solr Query: " + query, ex); throw new RuntimeException(ex); // TODO: handle bad query strings, among other issues } catch (SQLException ex) { - // TODO: handle error getting files from database + logger.log(Level.WARNING, "Error interpreting results from Lucene Solr Query: " + query, ex); } } + return matches; + } + @Override + public void execute() { + List matches = doQuery(); + String pathText = "Lucene query: " + query; Node rootNode = new KeywordSearchNode(matches, query); + Node filteredRootNode = new TableFilterNode(rootNode, true); - TopComponent searchResultWin = DataResultTopComponent.createInstance("Keyword search", pathText, rootNode, matches.size()); + TopComponent searchResultWin = DataResultTopComponent.createInstance("Keyword search", pathText, filteredRootNode, matches.size()); searchResultWin.requestActive(); // make it the active top component } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java index 5368eb7767..05e444d8d5 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java @@ -20,10 +20,13 @@ package org.sleuthkit.autopsy.keywordsearch; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; @@ -44,12 +47,13 @@ import org.openide.windows.TopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.datamodel.KeyValueNode; import org.sleuthkit.autopsy.datamodel.KeyValueThing; +import org.sleuthkit.datamodel.FsContent; public class RegexQuery implements KeywordSearchQuery { private static final int TERMS_UNLIMITED = -1; //corresponds to field in Solr schema, analyzed with white-space tokenizer only - private static final String TERMS_SEARCH_FIELD = "text_ws"; + private static final String TERMS_SEARCH_FIELD = "content_ws"; private static final String TERMS_HANDLER = "/terms"; private static final int TERMS_TIMEOUT = 90 * 1000; //in ms private String query; @@ -148,22 +152,49 @@ public class RegexQuery implements KeywordSearchQuery { return new KeyValueNode(thing, Children.create(new RegexResultDetailsChildFactory(thing), true)); } - class RegexResultDetailsChildFactory extends ChildFactory { - + private KeyValueThing thing; + RegexResultDetailsChildFactory(KeyValueThing thing) { this.thing = thing; } @Override protected boolean createKeys(List toPopulate) { - //query - Map map = new LinkedHashMap(); - map.put("#hits", -1); - KeyValueThing t = new KeyValueThing("TEST", map, 1); - //return toPopulate.addAll(things); - toPopulate.add(t); + //use Lucene query to get files with regular expression match result + final String keywordQuery = thing.getName(); + LuceneQuery filesQuery = new LuceneQuery(keywordQuery); + List matches = filesQuery.doQuery(); + + //get unique match result files + Set uniqueMatches = new TreeSet(new Comparator() { + + @Override + public int compare(FsContent fsc1, FsContent fsc2) { + return (int) (fsc1.getId() - fsc2.getId()); + + } + }); + uniqueMatches.addAll(matches); + + int resID = 0; + for (FsContent f : uniqueMatches) { + Map resMap = new LinkedHashMap(); + //final String name = f.getName(); + final long id = f.getId(); + + //build dir name + String dirName = KeywordSearchUtil.buildDirName(f); + + resMap.put("dir", dirName); + resMap.put("id", Long.toString(id)); + final String name = dirName + f.getName(); + resMap.put("name", name); + toPopulate.add(new KeyValueThing(name, resMap, ++resID)); + } + //TODO fix showing of child attributes in the GUI (DataResultViewerTable issue?) + return true; } @@ -172,10 +203,10 @@ public class RegexQuery implements KeywordSearchQuery { return new KeyValueNode(thing, Children.LEAF); } - + @Override protected Node[] createNodesForKey(KeyValueThing thing) { - Node [] nodes = new Node[1]; + Node[] nodes = new Node[1]; nodes[0] = new KeyValueNode(thing, Children.LEAF); return nodes;