mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
- regex search: show file hits as child nodes under the term matches
- further refactor Lucene query to reuse that query for regex detail view
This commit is contained in:
parent
2557aed21c
commit
3ea53996be
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,8 @@ import java.sql.ResultSet;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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.SolrQuery;
|
||||||
import org.apache.solr.client.solrj.SolrServerException;
|
import org.apache.solr.client.solrj.SolrServerException;
|
||||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||||
@ -31,19 +33,27 @@ import org.openide.nodes.Node;
|
|||||||
import org.openide.windows.TopComponent;
|
import org.openide.windows.TopComponent;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||||
|
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||||
import org.sleuthkit.datamodel.FsContent;
|
import org.sleuthkit.datamodel.FsContent;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
|
||||||
public class LuceneQuery implements KeywordSearchQuery {
|
public class LuceneQuery implements KeywordSearchQuery {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(LuceneQuery.class.getName());
|
||||||
|
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
public LuceneQuery(String query) {
|
public LuceneQuery(String query) {
|
||||||
this.query = 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<FsContent> doQuery() throws RuntimeException {
|
||||||
List<FsContent> matches = new ArrayList<FsContent>();
|
List<FsContent> matches = new ArrayList<FsContent>();
|
||||||
|
|
||||||
boolean allMatchesFetched = false;
|
boolean allMatchesFetched = false;
|
||||||
@ -80,18 +90,26 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (SolrServerException ex) {
|
} catch (SolrServerException ex) {
|
||||||
|
logger.log(Level.WARNING, "Error executing Lucene Solr Query: " + query, ex);
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
// TODO: handle bad query strings, among other issues
|
// TODO: handle bad query strings, among other issues
|
||||||
} catch (SQLException ex) {
|
} 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<FsContent> matches = doQuery();
|
||||||
|
|
||||||
String pathText = "Lucene query: " + query;
|
String pathText = "Lucene query: " + query;
|
||||||
Node rootNode = new KeywordSearchNode(matches, 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
|
searchResultWin.requestActive(); // make it the active top component
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,10 +20,13 @@ package org.sleuthkit.autopsy.keywordsearch;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -44,12 +47,13 @@ import org.openide.windows.TopComponent;
|
|||||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
|
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeyValueThing;
|
import org.sleuthkit.autopsy.datamodel.KeyValueThing;
|
||||||
|
import org.sleuthkit.datamodel.FsContent;
|
||||||
|
|
||||||
public class RegexQuery implements KeywordSearchQuery {
|
public class RegexQuery implements KeywordSearchQuery {
|
||||||
|
|
||||||
private static final int TERMS_UNLIMITED = -1;
|
private static final int TERMS_UNLIMITED = -1;
|
||||||
//corresponds to field in Solr schema, analyzed with white-space tokenizer only
|
//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 String TERMS_HANDLER = "/terms";
|
||||||
private static final int TERMS_TIMEOUT = 90 * 1000; //in ms
|
private static final int TERMS_TIMEOUT = 90 * 1000; //in ms
|
||||||
private String query;
|
private String query;
|
||||||
@ -148,22 +152,49 @@ public class RegexQuery implements KeywordSearchQuery {
|
|||||||
return new KeyValueNode(thing, Children.create(new RegexResultDetailsChildFactory(thing), true));
|
return new KeyValueNode(thing, Children.create(new RegexResultDetailsChildFactory(thing), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RegexResultDetailsChildFactory extends ChildFactory<KeyValueThing> {
|
class RegexResultDetailsChildFactory extends ChildFactory<KeyValueThing> {
|
||||||
|
|
||||||
private KeyValueThing thing;
|
private KeyValueThing thing;
|
||||||
|
|
||||||
RegexResultDetailsChildFactory(KeyValueThing thing) {
|
RegexResultDetailsChildFactory(KeyValueThing thing) {
|
||||||
this.thing = thing;
|
this.thing = thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<KeyValueThing> toPopulate) {
|
protected boolean createKeys(List<KeyValueThing> toPopulate) {
|
||||||
//query
|
//use Lucene query to get files with regular expression match result
|
||||||
Map<String,Object> map = new LinkedHashMap<String,Object>();
|
final String keywordQuery = thing.getName();
|
||||||
map.put("#hits", -1);
|
LuceneQuery filesQuery = new LuceneQuery(keywordQuery);
|
||||||
KeyValueThing t = new KeyValueThing("TEST", map, 1);
|
List<FsContent> matches = filesQuery.doQuery();
|
||||||
//return toPopulate.addAll(things);
|
|
||||||
toPopulate.add(t);
|
//get unique match result files
|
||||||
|
Set<FsContent> uniqueMatches = new TreeSet<FsContent>(new Comparator<FsContent>() {
|
||||||
|
|
||||||
|
@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<String, Object> resMap = new LinkedHashMap<String, Object>();
|
||||||
|
//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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +206,7 @@ public class RegexQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node[] createNodesForKey(KeyValueThing thing) {
|
protected Node[] createNodesForKey(KeyValueThing thing) {
|
||||||
Node [] nodes = new Node[1];
|
Node[] nodes = new Node[1];
|
||||||
nodes[0] = new KeyValueNode(thing, Children.LEAF);
|
nodes[0] = new KeyValueNode(thing, Children.LEAF);
|
||||||
return nodes;
|
return nodes;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user