cleaned up ExtractedContentViewer, etc; restored unnecessary refactorings

This commit is contained in:
jmillman 2016-07-28 14:50:59 -04:00
parent 48f6f5e63d
commit 2e2d2e2fcd
7 changed files with 131 additions and 139 deletions

View File

@ -460,14 +460,15 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
@Override @Override
protected Node createNodeForKey(FileWithCCN key) { protected Node createNodeForKey(FileWithCCN key) {
//add all account artifacts for the file and the file itself to th elookup
try { try {
List<Object> artifacts = new ArrayList<>(); List<Object> lookupContents = new ArrayList<>();
for (long artId : key.artifactIDS) { for (long artId : key.artifactIDS) {
artifacts.add(skCase.getBlackboardArtifact(artId)); lookupContents.add(skCase.getBlackboardArtifact(artId));
} }
AbstractFile abstractFileById = skCase.getAbstractFileById(key.getObjID()); AbstractFile abstractFileById = skCase.getAbstractFileById(key.getObjID());
artifacts.add(abstractFileById); lookupContents.add(abstractFileById);
return new FileWithCCNNode(key, abstractFileById, artifacts.toArray()); return new FileWithCCNNode(key, abstractFileById, lookupContents.toArray());
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error getting content for file with ccn hits.", ex); //NON-NLS LOGGER.log(Level.SEVERE, "Error getting content for file with ccn hits.", ex); //NON-NLS
return null; return null;
@ -488,6 +489,15 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
private final FileWithCCN fileKey; private final FileWithCCN fileKey;
private final String fileName; private final String fileName;
/**
* Constructor
*
* @param key The FileWithCCN that backs this node.
* @param content The Content object the key represents.
* @param lookupContents The contents of this Node's lookup. It should
* contain the content object and the account
* artifacts.
*/
@NbBundle.Messages({ @NbBundle.Messages({
"# {0} - raw file name", "# {0} - raw file name",
"# {1} - solr chunk id", "# {1} - solr chunk id",

View File

@ -140,7 +140,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
//if this artifact has associated content, add the action to view the content in the timeline //if this artifact has associated content, add the action to view the content in the timeline
AbstractFile file = getLookup().lookup(AbstractFile.class); AbstractFile file = getLookup().lookup(AbstractFile.class);
if (null != file) { if (null != file) {
actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction(file)); actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
} }
@ -423,19 +422,18 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
List<BlackboardAttribute> attributes = artifact.getAttributes(); List<BlackboardAttribute> attributes = artifact.getAttributes();
String keyword = null; String keyword = null;
String regexp = null; String regexp = null;
boolean isRegexp = false;
for (BlackboardAttribute att : attributes) { for (BlackboardAttribute att : attributes) {
final int attributeTypeID = att.getAttributeType().getTypeID(); final int attributeTypeID = att.getAttributeType().getTypeID();
if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
keyword = att.getValueString(); keyword = att.getValueString();
} else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) { } else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) {
regexp = att.getValueString(); regexp = att.getValueString();
isRegexp = StringUtils.isNotBlank(regexp);
} else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { } else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
objectId = att.getValueLong(); objectId = att.getValueLong();
} }
} }
if (keyword != null) { if (keyword != null) {
boolean isRegexp = StringUtils.isNotBlank(regexp);
String origQuery = isRegexp ? regexp : keyword; String origQuery = isRegexp ? regexp : keyword;
return highlightFactory.createInstance(objectId, keyword, isRegexp, origQuery); return highlightFactory.createInstance(objectId, keyword, isRegexp, origQuery);
} }

View File

@ -72,6 +72,9 @@ class AccountsText implements IndexedText, TextMarkupLookup {
return displayName; return displayName;
} }
@NbBundle.Messages({
"AccountsText.creditCardNumber=Credit Card Number",
"AccountsText.creditCardNumbers=Credit Card Numbers"})
AccountsText(String objectId, Set<String> keywords) { AccountsText(String objectId, Set<String> keywords) {
this.solrDocumentId = objectId; this.solrDocumentId = objectId;
this.keywords.addAll(keywords); this.keywords.addAll(keywords);
@ -89,8 +92,8 @@ class AccountsText implements IndexedText, TextMarkupLookup {
} }
displayName = keywords.size() == 1 displayName = keywords.size() == 1
? Bundle.ExtractedContentViewer_creditCardNumber() ? Bundle.AccountsText_creditCardNumber()
: Bundle.ExtractedContentViewer_creditCardNumbers(); : Bundle.AccountsText_creditCardNumbers();
} }
long getObjectId() { long getObjectId() {

View File

@ -667,10 +667,10 @@ class ExtractedContentPanel extends javax.swing.JPanel {
* thread and then set the panel text in the EDT Helps not to block the UI * thread and then set the panel text in the EDT Helps not to block the UI
* while content from Solr is retrieved. * while content from Solr is retrieved.
*/ */
private final class SetMarkupWorker extends SwingWorker<Object, Void> { private final class SetMarkupWorker extends SwingWorker<String, Void> {
private final IndexedText source;
private IndexedText source;
private String markup;
private ProgressHandle progress; private ProgressHandle progress;
SetMarkupWorker(IndexedText source) { SetMarkupWorker(IndexedText source) {
@ -678,36 +678,38 @@ class ExtractedContentPanel extends javax.swing.JPanel {
} }
@Override @Override
protected Object doInBackground() throws Exception { protected String doInBackground() throws Exception {
progress = ProgressHandle.createHandle(NbBundle.getMessage(this.getClass(), "ExtractedContentPanel.SetMarkup.progress.loading")); progress = ProgressHandle.createHandle(NbBundle.getMessage(this.getClass(), "ExtractedContentPanel.SetMarkup.progress.loading"));
progress.setDisplayName(NbBundle.getMessage(this.getClass(), "ExtractedContentPanel.SetMarkup.progress.displayName")); progress.setDisplayName(NbBundle.getMessage(this.getClass(), "ExtractedContentPanel.SetMarkup.progress.displayName"));
progress.start(); progress.start();
progress.switchToIndeterminate(); progress.switchToIndeterminate();
markup = source.getText(); return source.getText();
return null;
} }
@NbBundle.Messages({
"ExtractedContentPanel.SetMarkup.error=There was an error getting the text for the selected source."})
@Override @Override
protected void done() { protected void done() {
//super.done(); super.done();
progress.finish(); progress.finish();
// see if there are any errors // see if there are any errors
// @@@ BC: Display the errors to the user somehow
try { try {
get(); String markup = get();
if (markup != null) {
setPanelText(markup, true);
} else {
setPanelText("", false);
}
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, "Error getting marked up text", ex); //NON-NLS logger.log(Level.SEVERE, "Error getting marked up text", ex); //NON-NLS
setPanelText(Bundle.ExtractedContentPanel_SetMarkup_error(), true);
} // catch and ignore if we were cancelled } // catch and ignore if we were cancelled
catch (java.util.concurrent.CancellationException ex) { catch (java.util.concurrent.CancellationException ex) {
} }
if (markup != null) {
setPanelText(markup, true);
} else {
setPanelText("", false);
}
updateControls(source); updateControls(source);
scrollToCurrentHit(source); scrollToCurrentHit(source);

View File

@ -18,7 +18,6 @@
*/ */
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import com.drew.lang.annotations.NotNull;
import java.awt.Component; import java.awt.Component;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -44,8 +43,6 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor;
import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
@ -56,11 +53,13 @@ import org.sleuthkit.datamodel.TskCoreException;
public class ExtractedContentViewer implements DataContentViewer { public class ExtractedContentViewer implements DataContentViewer {
private static final Logger logger = Logger.getLogger(ExtractedContentViewer.class.getName()); private static final Logger logger = Logger.getLogger(ExtractedContentViewer.class.getName());
private static final long INVALID_DOCUMENT_ID = 0L; private static final long INVALID_DOCUMENT_ID = 0L;
private static final BlackboardAttribute.Type TSK_ASSOCIATED_ARTIFACT_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
private ExtractedContentPanel panel; private ExtractedContentPanel panel;
private volatile Node currentNode = null; private volatile Node currentNode = null;
private IndexedText currentSource = null; private IndexedText currentSource = null;
List<IndexedText> sources = new ArrayList<>();
/** /**
* Constructs a content viewer that displays the indexed text associated * Constructs a content viewer that displays the indexed text associated
@ -77,9 +76,7 @@ public class ExtractedContentViewer implements DataContentViewer {
*/ */
@Override @Override
public void setNode(final Node node) { public void setNode(final Node node) {
/* // Clear the viewer.
* Clear the viewer.
*/
if (node == null) { if (node == null) {
currentNode = null; currentNode = null;
resetComponent(); resetComponent();
@ -98,13 +95,13 @@ public class ExtractedContentViewer implements DataContentViewer {
Lookup nodeLookup = node.getLookup(); Lookup nodeLookup = node.getLookup();
Content content = nodeLookup.lookup(Content.class); Content content = nodeLookup.lookup(Content.class);
Collection<? extends BlackboardArtifact> artifacts = nodeLookup.lookupAll(BlackboardArtifact.class);
/* /*
* Assemble a collection of all of the indexed text "sources" associated * Assemble a collection of all of the indexed text "sources" associated
* with the node. * with the node.
*/ */
sources.clear(); List<IndexedText> sources = new ArrayList<>();
IndexedText highlightedHitText = null; IndexedText highlightedHitText = null;
IndexedText rawContentText = null; IndexedText rawContentText = null;
IndexedText rawArtifactText = null; IndexedText rawArtifactText = null;
@ -117,9 +114,59 @@ public class ExtractedContentViewer implements DataContentViewer {
sources.addAll(nodeLookup.lookupAll(IndexedText.class)); sources.addAll(nodeLookup.lookupAll(IndexedText.class));
if (!sources.isEmpty()) { if (!sources.isEmpty()) {
//if the look up had any sources use them and don't make a new one.
highlightedHitText = sources.get(0); highlightedHitText = sources.get(0);
} else if (null != content && solrHasContent(content.getId())) { } else if (null != content && solrHasContent(content.getId())) {//if the lookup didn't have any sources, and solr has indexed the content...
highlightedHitText = addAccountHighlightedText(artifacts, content); /*
* get all the credit card artifacts and make a AccountsText object
* that will highlight them.
*/
String solrDocumentID = String.valueOf(content.getId()); //grab the object id as the solrDocumentID
Set<String> accountNumbers = new HashSet<>();
try {
//if the node had artifacts in the lookup use them, other wise look up all credit card artifacts for the content.
Collection<? extends BlackboardArtifact> artifacts = nodeLookup.lookupAll(BlackboardArtifact.class);
artifacts = (artifacts == null || artifacts.isEmpty())
? content.getArtifacts(TSK_CREDIT_CARD_ACCOUNT)
: artifacts;
/*
* For each artifact add the account number to the list of
* accountNumbers to highlight, and use the solrDocumentId
* attribute(in place of the content's object Id) if it exists
*
* NOTE: this assumes all the artifacts will be from the same
* solrDocumentId
*/
for (BlackboardArtifact artifact : artifacts) {
try {
BlackboardAttribute solrIDAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID));
if (solrIDAttr != null) {
String valueString = solrIDAttr.getValueString();
if (StringUtils.isNotBlank(valueString)) {
solrDocumentID = valueString;
}
}
BlackboardAttribute keyWordAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER));
if (keyWordAttr != null) {
String valueString = keyWordAttr.getValueString();
if (StringUtils.isNotBlank(valueString)) {
accountNumbers.add(valueString);
}
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to retrieve Blackboard Attributes", ex); //NON-NLS
}
}
if (accountNumbers.isEmpty() == false) {
highlightedHitText = new AccountsText(solrDocumentID, accountNumbers);
sources.add(highlightedHitText);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to retrieve Blackboard Artifacts", ex); //NON-NLS
}
} }
/* /*
@ -127,7 +174,8 @@ public class ExtractedContentViewer implements DataContentViewer {
* associated with the node. * associated with the node.
*/ */
if (null != content && solrHasContent(content.getId())) { if (null != content && solrHasContent(content.getId())) {
rawContentText = addRawContentText(content); rawContentText = new RawText(content, content.getId());
sources.add(rawContentText);
} }
/* /*
@ -136,12 +184,30 @@ public class ExtractedContentViewer implements DataContentViewer {
*/ */
BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class);
if (null != artifact) { if (null != artifact) {
rawArtifactText = addRawArtifactText(artifact); /**
* For keyword hit artifacts, add the text of the artifact that hit,
* not the hit artifact; otherwise add the text for the artifact.
*/
if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
try {
BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE);
if (attribute != null) {
long artifactId = attribute.getValueLong();
BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(artifactId);
rawArtifactText = new RawText(associatedArtifact, associatedArtifact.getArtifactID());
sources.add(rawArtifactText);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS
}
} else {
rawArtifactText = new RawText(artifact, artifact.getArtifactID());
sources.add(rawArtifactText);
}
} }
/* // Now set the default source to be displayed.
* Now set the default source to be displayed.
*/
if (null != highlightedHitText) { if (null != highlightedHitText) {
currentSource = highlightedHitText; currentSource = highlightedHitText;
} else if (null != rawContentText) { } else if (null != rawContentText) {
@ -150,9 +216,7 @@ public class ExtractedContentViewer implements DataContentViewer {
currentSource = rawArtifactText; currentSource = rawArtifactText;
} }
/* // Push the text sources into the panel.
* Push the text sources into the panel.
*/
for (IndexedText source : sources) { for (IndexedText source : sources) {
int currentPage = source.getCurrentPage(); int currentPage = source.getCurrentPage();
if (currentPage == 0 && source.hasNextPage()) { if (currentPage == 0 && source.hasNextPage()) {
@ -163,82 +227,6 @@ public class ExtractedContentViewer implements DataContentViewer {
setPanel(sources); setPanel(sources);
} }
private IndexedText addRawContentText(Content content) {
RawText rawContentText = new RawText(content, content.getId());
sources.add(rawContentText);
return rawContentText;
}
/**
* For keyword hit artifacts, add the text of the artifact that hit, not the
* hit artifact; otherwise add the text for the artifact.
*/
private IndexedText addRawArtifactText(BlackboardArtifact artifact) {
RawText rawArtifactText = null;
if (artifact.getArtifactTypeID() != TSK_KEYWORD_HIT.getTypeID()) {
rawArtifactText = new RawText(artifact, artifact.getArtifactID());
sources.add(rawArtifactText);
} else {
try {
BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE);
if (attribute != null) {
long artifactId = attribute.getValueLong();
BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(artifactId);
rawArtifactText = new RawText(associatedArtifact, associatedArtifact.getArtifactID());
sources.add(rawArtifactText);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS
}
}
return rawArtifactText;
}
@NbBundle.Messages({
"ExtractedContentViewer.creditCardNumber=Credit Card Number",
"ExtractedContentViewer.creditCardNumbers=Credit Card Numbers"})
private AccountsText addAccountHighlightedText(Collection<? extends BlackboardArtifact> artifacts, @NotNull Content content) {
String objectId = String.valueOf(content.getId());
Set<String> keywords = new HashSet<>();
try {
if (artifacts == null || artifacts.isEmpty()) {
artifacts = content.getArtifacts(TSK_CREDIT_CARD_ACCOUNT);
}
for (BlackboardArtifact artifact : artifacts) {
try {
BlackboardAttribute solrIDAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID));
if (solrIDAttr != null) {
String valueString = solrIDAttr.getValueString();
if (StringUtils.isNotBlank(valueString)) {
objectId = valueString;
}
}
BlackboardAttribute keyWordAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER));
if (keyWordAttr != null) {
String valueString = keyWordAttr.getValueString();
if (StringUtils.isNotBlank(valueString)) {
keywords.add(valueString);
}
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to retrieve Blackboard Attributes", ex); //NON-NLS
}
}
if (keywords.isEmpty() == false) {
AccountsText highlightedAccountText = new AccountsText(objectId,keywords);
sources.add(highlightedAccountText);
return highlightedAccountText;
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to retrieve Blackboard Artifacts", ex); //NON-NLS
}
return null;
}
private static final BlackboardAttribute.Type TSK_ASSOCIATED_ARTIFACT_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
private void scrollToCurrentHit() { private void scrollToCurrentHit() {
final IndexedText source = panel.getSelectedSource(); final IndexedText source = panel.getSelectedSource();
if (source == null || !source.isSearchable()) { if (source == null || !source.isSearchable()) {
@ -279,7 +267,7 @@ public class ExtractedContentViewer implements DataContentViewer {
@Override @Override
public void resetComponent() { public void resetComponent() {
setPanel(new ArrayList<IndexedText>()); setPanel(new ArrayList<>());
panel.resetDisplay(); panel.resetDisplay();
currentNode = null; currentNode = null;
currentSource = null; currentSource = null;
@ -302,11 +290,15 @@ public class ExtractedContentViewer implements DataContentViewer {
return true; return true;
} }
/*
* Is there a credit card artifact in the lookup
*/
Collection<? extends BlackboardArtifact> artifacts = node.getLookup().lookupAll(BlackboardArtifact.class); Collection<? extends BlackboardArtifact> artifacts = node.getLookup().lookupAll(BlackboardArtifact.class);
if (artifacts != null) {
for (BlackboardArtifact art : artifacts) { for (BlackboardArtifact art : artifacts) {
if (art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID()) { if (art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID()) {
return true; return true;
}
} }
} }
@ -348,19 +340,6 @@ public class ExtractedContentViewer implements DataContentViewer {
} }
} }
private class IsDirVisitor extends ContentVisitor.Default<Boolean> {
@Override
protected Boolean defaultVisit(Content cntnt) {
return false;
}
@Override
public Boolean visit(Directory d) {
return true;
}
}
/** /**
* Check if Solr has extracted content for a given node * Check if Solr has extracted content for a given node
* *

View File

@ -315,7 +315,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
//wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization
// store the data in HighlightedMatchesSource so that it can be looked up (in content viewer) // store the data in HighlightedMatchesSource so that it can be looked up (in content viewer)
HighlightedText highlights = new HighlightedText(key.solrObjectId, queryStr, !key.getQuery().isLiteral(), hits); HighlightedText highlights = new HighlightedText(key.solrObjectId, queryStr, !key.getQuery().isLiteral(), false, hits);
return new KeywordSearchFilterNode(highlights, kvNode); return new KeywordSearchFilterNode(highlights, kvNode);
} }

View File

@ -313,7 +313,7 @@ class LuceneQuery implements KeywordSearchQuery {
* *
* @return * @return
*/ */
static Set<SolrDocument> filterOneHitPerDocument(SolrDocumentList resultList) { private Set<SolrDocument> filterOneHitPerDocument(SolrDocumentList resultList) {
// sort the list so that we consistently pick the same chunk each time. // sort the list so that we consistently pick the same chunk each time.
// note this sort is doing a string comparison and not an integer comparison, so // note this sort is doing a string comparison and not an integer comparison, so
// chunk 10 will be smaller than chunk 9. // chunk 10 will be smaller than chunk 9.
@ -481,7 +481,7 @@ class LuceneQuery implements KeywordSearchQuery {
* Compares SolrDocuments based on their ID's. Two SolrDocuments with * Compares SolrDocuments based on their ID's. Two SolrDocuments with
* different chunk numbers are considered equal. * different chunk numbers are considered equal.
*/ */
static private class SolrDocumentComparatorIgnoresChunkId implements Comparator<SolrDocument> { private class SolrDocumentComparatorIgnoresChunkId implements Comparator<SolrDocument> {
@Override @Override
public int compare(SolrDocument left, SolrDocument right) { public int compare(SolrDocument left, SolrDocument right) {