mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge branch 'keyword-search-prototype' of github.com:sleuthkit/autopsy into keyword-search-prototype
This commit is contained in:
commit
6a6753868e
@ -61,4 +61,10 @@ public interface DataResultViewer {
|
||||
* preparation for permanently disposing of it.
|
||||
*/
|
||||
public void clearComponent();
|
||||
|
||||
/**
|
||||
* Expand node, if supported by the viewed
|
||||
* @param n Node to expand
|
||||
*/
|
||||
public void expandNode(Node n);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Node.Property;
|
||||
import org.openide.nodes.Node.PropertySet;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.lookup.AbstractLookup;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||
|
||||
@ -64,6 +65,18 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
|
||||
this.em.addPropertyChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand node
|
||||
* @param n Node to expand
|
||||
*/
|
||||
@Override
|
||||
public void expandNode(Node n) {
|
||||
if ( this.tableScrollPanel != null) {
|
||||
OutlineView ov = ((OutlineView) this.tableScrollPanel);
|
||||
ov.expandNode(n);
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
|
@ -91,6 +91,16 @@ public class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Expand node
|
||||
* @param n Node to expand
|
||||
*/
|
||||
@Override
|
||||
public void expandNode(Node n) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNode(Node givenNode) {
|
||||
// change the cursor to "waiting cursor" for this operation
|
||||
|
@ -57,7 +57,7 @@ class HighlightedMatchesSource implements MarkupSource {
|
||||
public String getMarkup() {
|
||||
|
||||
SolrQuery q = new SolrQuery();
|
||||
final String queryEscaped = KeywordSearchUtil.escapeLuceneQuery(solrQuery);
|
||||
final String queryEscaped = KeywordSearchUtil.escapeLuceneQuery(solrQuery, true);
|
||||
|
||||
q.setQuery(queryEscaped);
|
||||
q.addFilterQuery("id:" + content.getId());
|
||||
|
@ -18,13 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer;
|
||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType;
|
||||
|
@ -18,9 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -104,14 +102,25 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
}
|
||||
keywordTable.setCellSelectionEnabled(false);
|
||||
|
||||
//create some empty rows
|
||||
//tableModel.initEmpty();
|
||||
|
||||
//test
|
||||
tableModel.addKeyword("\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d");
|
||||
tableModel.addKeyword("\\d\\d\\.\\d\\d\\d\\.*");
|
||||
tableModel.addKeyword("text");
|
||||
|
||||
loadDefaultKeywords();
|
||||
}
|
||||
|
||||
private void loadDefaultKeywords() {
|
||||
//some hardcoded keywords for testing
|
||||
|
||||
//phone number
|
||||
tableModel.addKeyword("\\d\\d\\d[\\.-]\\d\\d\\d[\\.-]\\d\\d\\d\\d");
|
||||
tableModel.addKeyword("\\d{8,10}");
|
||||
tableModel.addKeyword("phone|fax");
|
||||
//IP address
|
||||
tableModel.addKeyword("(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])");
|
||||
//email
|
||||
tableModel.addKeyword("[e\\-]{0,2}mail");
|
||||
tableModel.addKeyword("[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}");
|
||||
//URL
|
||||
tableModel.addKeyword("ftp|sftp|ssh|http|https|www");
|
||||
//escaped literal word \d\d\d
|
||||
tableModel.addKeyword("\\Q\\d\\d\\d\\E");
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
@ -309,11 +318,11 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
}//GEN-LAST:event_addWordButtonActionPerformed
|
||||
|
||||
private void saveListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveListButtonActionPerformed
|
||||
// TODO add your handling code here:
|
||||
|
||||
}//GEN-LAST:event_saveListButtonActionPerformed
|
||||
|
||||
private void chLiteralWordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chLiteralWordActionPerformed
|
||||
// TODO add your handling code here:
|
||||
|
||||
}//GEN-LAST:event_chLiteralWordActionPerformed
|
||||
|
||||
private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
|
||||
@ -343,12 +352,12 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
|
||||
@Override
|
||||
public void componentOpened() {
|
||||
// TODO add custom code on component opening
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentClosed() {
|
||||
// TODO add custom code on component closing
|
||||
|
||||
}
|
||||
|
||||
void writeProperties(java.util.Properties p) {
|
||||
@ -385,6 +394,10 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
Map<String, Boolean> ret = new LinkedHashMap<String, Boolean>();
|
||||
for (String s : selected) {
|
||||
if (!s.trim().equals("")) {
|
||||
//use false for isLiteral because we are currently escaping
|
||||
//the keyword earlier as it is stored
|
||||
//might need to change and pass isLiteral if the query object
|
||||
//needs to treat it specially
|
||||
ret.put(s, false);
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,14 @@ import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.apache.solr.client.solrj.response.TermsResponse.Term;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode.FsContentPropertyType;
|
||||
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
|
||||
@ -140,17 +144,25 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueThing> {
|
||||
@Override
|
||||
protected Node createNodeForKey(KeyValueThing thing) {
|
||||
ChildFactory<KeyValueThing> childFactory = null;
|
||||
switch (presentation) {
|
||||
case COLLAPSE:
|
||||
childFactory = new ResultCollapsedChildFactory(thing);
|
||||
break;
|
||||
case DETAIL:
|
||||
childFactory = new ResulTermsMatchesChildFactory(things);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return new KeyValueNode(thing, Children.create(childFactory, true));
|
||||
if (presentation == Presentation.COLLAPSE) {
|
||||
childFactory = new ResultCollapsedChildFactory(thing);
|
||||
final Node ret = new KeyValueNode(thing, Children.create(childFactory, true));
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//DataResultViewerTable view = Utilities.actionsGlobalContext().lookup(DataResultViewerTable.class);
|
||||
for (DataResultViewer view : Lookup.getDefault().lookupAll(DataResultViewer.class)) {
|
||||
view.expandNode(ret);
|
||||
}
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
} else {
|
||||
|
||||
childFactory = new ResulTermsMatchesChildFactory(things);
|
||||
return new KeyValueNode(thing, Children.create(childFactory, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,10 +196,16 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueThing> {
|
||||
//the query is executed later on demand
|
||||
StringBuilder highlightQuery = new StringBuilder();
|
||||
Collection<Term> terms = tcq.getTerms();
|
||||
final int lastTerm = terms.size() - 1;
|
||||
int curTerm = 0;
|
||||
for (Term term : terms) {
|
||||
final String termS = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
|
||||
highlightQuery.append(termS);
|
||||
highlightQuery.append(" ");
|
||||
final String termS = KeywordSearchUtil.escapeLuceneQuery(term.getTerm(), true);
|
||||
if (!termS.contains("*")) {
|
||||
highlightQuery.append(termS);
|
||||
if (lastTerm != curTerm) {
|
||||
highlightQuery.append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
//String highlightQueryEscaped = KeywordSearchUtil.escapeLuceneQuery(highlightQuery.toString());
|
||||
String highlightQueryEscaped = highlightQuery.toString();
|
||||
|
@ -58,10 +58,32 @@ public class KeywordSearchUtil {
|
||||
return dirName;
|
||||
}
|
||||
|
||||
public static String escapeLuceneQuery(String query) {
|
||||
/**
|
||||
* Perform standard escaping / encoding into UTF-8 before sending over net
|
||||
* @param query to be encoded
|
||||
* @param escapeLuceneChars if true perform first escaping of Lucene specific special chars
|
||||
* such as /+-&|!(){}[]^"~*?:\ and treat the whole query as literal word
|
||||
* @return encoded query
|
||||
*/
|
||||
public static String escapeLuceneQuery(String query, boolean escapeLuceneChars) {
|
||||
String queryEscaped = null;
|
||||
String inputString = query;
|
||||
|
||||
if (escapeLuceneChars == true) {
|
||||
final String ESCAPE_CHARS = "/+-&|!(){}[]^\"~*?:\\";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i< inputString.length(); ++i) {
|
||||
char c = inputString.charAt(i);
|
||||
if (ESCAPE_CHARS.contains(Character.toString(c)) ) {
|
||||
sb.append("\\");
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
inputString = sb.toString();
|
||||
}
|
||||
|
||||
try {
|
||||
queryEscaped = URLEncoder.encode(query, "UTF-8");
|
||||
queryEscaped = URLEncoder.encode(inputString, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException ex) {
|
||||
logger.log(Level.SEVERE, "Error escaping URL query, should not happen.", ex);
|
||||
@ -70,6 +92,7 @@ public class KeywordSearchUtil {
|
||||
return queryEscaped;
|
||||
}
|
||||
|
||||
|
||||
public static void displayDialog(final String title, final String message, final DIALOG_MESSAGE_TYPE type) {
|
||||
int messageType;
|
||||
if (type == DIALOG_MESSAGE_TYPE.ERROR)
|
||||
|
@ -56,7 +56,7 @@ public class LuceneQuery implements KeywordSearchQuery {
|
||||
|
||||
@Override
|
||||
public void escape() {
|
||||
queryEscaped = KeywordSearchUtil.escapeLuceneQuery(query);
|
||||
queryEscaped = KeywordSearchUtil.escapeLuceneQuery(query, true);
|
||||
isEscaped = true;
|
||||
}
|
||||
|
||||
|
@ -165,17 +165,23 @@ public class TermComponentQuery implements KeywordSearchQuery {
|
||||
//it's much more efficient and should yield the same file IDs as per match queries
|
||||
//requires http POST query method due to potentially large query size
|
||||
StringBuilder filesQueryB = new StringBuilder();
|
||||
final int lastTerm = terms.size() - 1;
|
||||
int curTerm = 0;
|
||||
for (Term term : terms) {
|
||||
//final String termS = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
|
||||
final String termS = term.getTerm();
|
||||
filesQueryB.append(termS);
|
||||
filesQueryB.append(" ");
|
||||
if (!termS.contains("*")) {
|
||||
filesQueryB.append(termS);
|
||||
if (curTerm != lastTerm) {
|
||||
filesQueryB.append(" ");
|
||||
}
|
||||
}
|
||||
++curTerm;
|
||||
}
|
||||
List<FsContent> uniqueMatches = new ArrayList<FsContent>();
|
||||
|
||||
if (! terms.isEmpty()) {
|
||||
if (!terms.isEmpty()) {
|
||||
LuceneQuery filesQuery = new LuceneQuery(filesQueryB.toString());
|
||||
filesQuery.escape(); //TODO escaping invididual terms above instead could make a difference to Solr
|
||||
filesQuery.escape();
|
||||
try {
|
||||
uniqueMatches = filesQuery.performQuery();
|
||||
} catch (RuntimeException e) {
|
||||
@ -196,6 +202,7 @@ public class TermComponentQuery implements KeywordSearchQuery {
|
||||
}
|
||||
|
||||
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user