Merge pull request #394 from raman-bt/develop

Display Interesting Items (Interesting Files, Interesting Artifacts) dir...
This commit is contained in:
Richard Cordovano 2014-01-08 12:06:58 -08:00
commit 635df51a6a
13 changed files with 325 additions and 8 deletions

View File

@ -34,12 +34,16 @@ import javax.swing.SwingWorker;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.contentviewers.Utilities;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.datamodel.ArtifactStringContent;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Instances of this class display the BlackboardArtifacts associated with the Content represented by a Node.
@ -471,7 +475,31 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
index = artifacts.indexOf(artifact);
if (index == -1) {
index = 0;
}
} else {
// if the artifact has an ASSOCIATED ARTIFACT, then we display the associated artifact instead
try {
for (BlackboardAttribute attr : artifact.getAttributes()) {
if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
long assocArtifactId = attr.getValueLong();
int assocArtifactIndex = -1;
for (BlackboardArtifact art: artifacts) {
if (assocArtifactId == art.getArtifactID()) {
assocArtifactIndex = artifacts.indexOf(art);
break;
}
}
if (assocArtifactIndex >= 0) {
index = assocArtifactIndex;
}
break;
}
}
}
catch (TskCoreException ex) {
logger.log(Level.WARNING, "Couldn't get associated artifact to display in Content Viewer.", ex);
}
}
}
if (isCancelled()) {

View File

@ -149,7 +149,12 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
public AbstractNode visit(HashsetHits hh) {
return hh.new HashsetHitsRootNode();
}
@Override
public AbstractNode visit(InterestingHits ih) {
return ih.new InterestingHitsRootNode();
}
@Override
public AbstractNode visit(EmailExtracted ee) {
return ee.new EmailExtractedRootNode();

View File

@ -53,6 +53,8 @@ public interface AutopsyItemVisitor<T> {
T visit(EmailExtracted ee);
T visit(TagsNodeKey tagsNodeKey);
T visit(InterestingHits ih);
T visit(DataSources i);
@ -128,7 +130,11 @@ public interface AutopsyItemVisitor<T> {
public T visit(HashsetHits hh) {
return defaultVisit(hh);
}
@Override
public T visit(InterestingHits ih) {
return defaultVisit(ih);
}
@Override
public T visit(EmailExtracted ee) {
return defaultVisit(ee);

View File

@ -55,6 +55,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
};
/**
@ -232,7 +233,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
final int attributeTypeID = attribute.getAttributeTypeID();
//skip some internal attributes that user shouldn't see
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()) {
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
continue;
} else {
switch (attribute.getValueType()) {

View File

@ -27,6 +27,8 @@ import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNod
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode;
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode;
import org.sleuthkit.autopsy.datamodel.InterestingHits.InterestingHitsRootNode;
import org.sleuthkit.autopsy.datamodel.InterestingHits.InterestingHitsSetNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode;
@ -84,7 +86,11 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(EmailExtractedFolderNode eefn);
T visit(TagsNode node);
T visit(InterestingHitsRootNode ihrn);
T visit(InterestingHitsSetNode ihsn);
T visit(TagNameNode node);
T visit(ContentTagTypeNode node);
@ -237,7 +243,17 @@ public interface DisplayableItemNodeVisitor<T> {
public T visit(HashsetHitsSetNode hhsn) {
return defaultVisit(hhsn);
}
@Override
public T visit(InterestingHitsRootNode ihrn) {
return defaultVisit(ihrn);
}
@Override
public T visit(InterestingHitsSetNode ihsn) {
return defaultVisit(ihsn);
}
@Override
public T visit(EmailExtractedRootNode eern) {
return defaultVisit(eern);

View File

@ -53,6 +53,8 @@ public class ExtractedContentChildren extends ChildFactory<BlackboardArtifact.AR
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT);
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT);
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE);
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
}
@Override

View File

@ -0,0 +1,221 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskException;
public class InterestingHits implements AutopsyVisitableItem {
private static final String INTERESTING_ITEMS = "INTERESTING ITEMS";
private static final String DISPLAY_NAME = "Interesting Items";
private static final Logger logger = Logger.getLogger(InterestingHits.class.getName());
private SleuthkitCase skCase;
private Map<String, Set<Long>> interestingItemsMap;
public InterestingHits(SleuthkitCase skCase) {
this.skCase = skCase;
interestingItemsMap = new LinkedHashMap<>();
}
@SuppressWarnings("deprecation")
private void initArtifacts() {
interestingItemsMap.clear();
loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
}
/*
* Reads the artifacts of specified type, grouped by Set, and loads into the interestingItemsMap
*/
private void loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE artType) {
ResultSet rs = null;
try {
int setNameId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
int artId = artType.getTypeID();
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id "
+ "FROM blackboard_attributes,blackboard_artifacts WHERE "
+ "attribute_type_id=" + setNameId
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id"
+ " AND blackboard_artifacts.artifact_type_id=" + artId;
rs = skCase.runQuery(query);
while (rs.next()) {
String value = rs.getString("value_text");
long artifactId = rs.getLong("artifact_id");
if (!interestingItemsMap.containsKey(value)) {
interestingItemsMap.put(value, new HashSet<Long>());
}
interestingItemsMap.get(value).add(artifactId);
}
} catch (SQLException ex) {
logger.log(Level.WARNING, "SQL Exception occurred: ", ex);
}
finally {
if (rs != null) {
try {
skCase.closeRunQuery(rs);
} catch (SQLException ex) {
logger.log(Level.WARNING, "Error closing result set after getting artifacts", ex);
}
}
}
}
@Override
public <T> T accept(AutopsyItemVisitor<T> v) {
return v.visit(this);
}
/**
* Node for the interesting items
*/
public class InterestingHitsRootNode extends DisplayableItemNode {
public InterestingHitsRootNode() {
super(Children.create(new InterestingHitsRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
super.setName(INTERESTING_ITEMS);
super.setDisplayName(DISPLAY_NAME);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png");
initArtifacts();
}
@Override
public boolean isLeafTypeNode() {
return false;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty("Name",
"Name",
"no description",
getName()));
return s;
}
}
private class InterestingHitsRootChildren extends ChildFactory<String> {
@Override
protected boolean createKeys(List<String> list) {
list.addAll(interestingItemsMap.keySet());
return true;
}
@Override
protected Node createNodeForKey(String key) {
return new InterestingHitsSetNode(key, interestingItemsMap.get(key));
}
}
public class InterestingHitsSetNode extends DisplayableItemNode {
public InterestingHitsSetNode(String name, Set<Long> children) {
super(Children.create(new InterestingHitsSetChildren(children), true), Lookups.singleton(name));
super.setName(name);
super.setDisplayName(name + " (" + children.size() + ")");
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png");
}
@Override
public boolean isLeafTypeNode() {
return true;
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty("Name",
"Name",
"no description",
getName()));
return s;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
}
private class InterestingHitsSetChildren extends ChildFactory<BlackboardArtifact> {
private Set<Long> children;
private InterestingHitsSetChildren(Set<Long> children) {
super();
this.children = children;
}
@Override
protected boolean createKeys(List<BlackboardArtifact> list) {
for (long l : children) {
try {
list.add(skCase.getBlackboardArtifact(l));
} catch (TskException ex) {
logger.log(Level.WARNING, "TSK Exception occurred", ex);
}
}
return true;
}
@Override
protected Node createNodeForKey(BlackboardArtifact artifact) {
return new BlackboardArtifactNode(artifact);
}
}
}

View File

@ -35,6 +35,7 @@ public class ResultsNode extends DisplayableItemNode {
new KeywordHits(sleuthkitCase),
new HashsetHits(sleuthkitCase),
new EmailExtracted(sleuthkitCase),
new InterestingHits(sleuthkitCase),
new TagsNodeKey()
)), Lookups.singleton(NAME));
setName(NAME);

View File

@ -84,7 +84,12 @@ public class RootContentChildren extends AbstractContentChildren<Object> {
case TSK_TAG_ARTIFACT:
if (o instanceof TagsNodeKey)
this.refreshKey(o);
break;
break;
case TSK_INTERESTING_FILE_HIT:
case TSK_INTERESTING_ARTIFACT_HIT:
if (o instanceof InterestingHits)
this.refreshKey(o);
break;
default:
if (o instanceof ExtractedContent)
this.refreshKey(o);
@ -96,9 +101,11 @@ public class RootContentChildren extends AbstractContentChildren<Object> {
this.refreshKey(o);
else if (o instanceof KeywordHits)
this.refreshKey(o);
else if (o instanceof TagsNodeKey)
this.refreshKey(o);
else if (o instanceof EmailExtracted)
this.refreshKey(o);
else if (o instanceof TagsNodeKey)
else if (o instanceof InterestingHits)
this.refreshKey(o);
else if (o instanceof ExtractedContent)
this.refreshKey(o);

View File

@ -56,6 +56,8 @@ import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNod
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode;
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode;
import org.sleuthkit.autopsy.datamodel.InterestingHits.InterestingHitsRootNode;
import org.sleuthkit.autopsy.datamodel.InterestingHits.InterestingHitsSetNode;
import org.sleuthkit.autopsy.datamodel.ImageNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode;
@ -184,7 +186,7 @@ public class DataResultFilterNode extends FilterNode {
final int artifactTypeID = ba.getArtifactTypeID();
if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()
|| artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|| artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() ) {
actions.add(new ViewContextAction("View File in Directory", ban));
} else {
// if the artifact links to another file, add an action to go to
@ -365,7 +367,17 @@ public class DataResultFilterNode extends FilterNode {
public AbstractAction visit(HashsetHitsSetNode hhsn) {
return openChild(hhsn);
}
@Override
public AbstractAction visit(InterestingHitsRootNode iarn) {
return openChild(iarn);
}
@Override
public AbstractAction visit(InterestingHitsSetNode iasn) {
return openChild(iasn);
}
@Override
public AbstractAction visit(EmailExtractedRootNode eern) {
return openChild(eern);

View File

@ -969,6 +969,23 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
} catch (TskException ex) {
logger.log(Level.WARNING, "Error retrieving attributes", ex);
}
} else if ( type.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) ||
type.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT) ) {
Node interestingItemsRootNode = resultsChilds.findChild(type.getLabel());
Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
try {
String setName = null;
List<BlackboardAttribute> attributes = art.getAttributes();
for (BlackboardAttribute att : attributes) {
int typeId = att.getAttributeTypeID();
if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
setName = att.getValueString();
}
}
treeNode = interestingItemsRootChildren.findChild(setName);
} catch (TskException ex) {
logger.log(Level.WARNING, "Error retrieving attributes", ex);
}
} else {
Node extractedContent = resultsChilds.findChild(ExtractedContentNode.NAME);
Children extractedChilds = extractedContent.getChildren();

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

View File

@ -302,7 +302,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
commitTimer.stop();
searchTimer.stop();
commitTimer = null;
searchTimer = null;
//searchTimer = null; // do not collect, final searcher might still be running, in which case it throws an exception
textExtractors.clear();
textExtractors = null;