mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
interim commit of refresh updates in tree. Still need to do interestingitems.
This commit is contained in:
parent
b37615e581
commit
33b463cd16
@ -50,13 +50,13 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
protected void refreshDirectoryTree() {
|
||||
// The way the "directory tree" currently works, a new tags sub-tree
|
||||
// needs to be made to reflect the results of invoking tag Actions. The
|
||||
// way to do this is to call DirectoryTreeTopComponent.refreshTree(),
|
||||
// way to do this is to call DirectoryTreeTopComponent.refreshResultsTree(),
|
||||
// which calls RootContentChildren.refreshKeys(BlackboardArtifact.ARTIFACT_TYPE... types)
|
||||
// for the RootContentChildren object that is the child factory for the
|
||||
// ResultsNode that is the root of the tags sub-tree. There is a switch
|
||||
// statement in RootContentChildren.refreshKeys() that maps both
|
||||
// BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE and BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT
|
||||
// to making a call to refreshKey(TagsNodeKey).
|
||||
DirectoryTreeTopComponent.findInstance().refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE);
|
||||
DirectoryTreeTopComponent.findInstance().refreshResultsTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children.Keys;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
@ -119,8 +118,8 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
||||
static class CreateAutopsyNodeVisitor extends AutopsyItemVisitor.Default<AbstractNode> {
|
||||
|
||||
@Override
|
||||
public ExtractedContentNode visit(ExtractedContent ec) {
|
||||
return new ExtractedContentNode(ec.getSleuthkitCase());
|
||||
public ExtractedContent.RootNode visit(ExtractedContent ec) {
|
||||
return ec.new RootNode(ec.getSleuthkitCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -145,22 +144,22 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(KeywordHits kh) {
|
||||
return kh.new KeywordHitsRootNode();
|
||||
return kh.new RootNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(HashsetHits hh) {
|
||||
return hh.new HashsetHitsRootNode();
|
||||
return hh.new RootNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(InterestingHits ih) {
|
||||
return ih.new InterestingHitsRootNode();
|
||||
return ih.new RootNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(EmailExtracted ee) {
|
||||
return ee.new EmailExtractedRootNode();
|
||||
return ee.new RootNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,8 +19,6 @@
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dfickling
|
||||
*/
|
||||
interface AutopsyItemVisitor<T> {
|
||||
|
||||
|
@ -41,8 +41,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
|
||||
/**
|
||||
* Node wrapping a blackboard artifact object. This represents a single artifact.
|
||||
* Its parent is typically an ArtifactTypeNode.
|
||||
* Node wrapping a blackboard artifact object. This is generated from several
|
||||
* places in the tree.
|
||||
*/
|
||||
public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
|
||||
|
@ -20,18 +20,8 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode;
|
||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
|
||||
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;
|
||||
import org.sleuthkit.autopsy.directorytree.BlackboardArtifactTagTypeNode;
|
||||
|
||||
/**
|
||||
@ -49,9 +39,9 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
|
||||
T visit(BlackboardArtifactNode ban);
|
||||
|
||||
T visit(ArtifactTypeNode atn);
|
||||
T visit(ExtractedContent.TypeNode atn);
|
||||
|
||||
T visit(ExtractedContentNode ecn);
|
||||
T visit(ExtractedContent.RootNode ecn);
|
||||
|
||||
T visit(FileTypeNode fsfn);
|
||||
|
||||
@ -69,27 +59,27 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
|
||||
T visit(RecentFilesFilterNode rffn);
|
||||
|
||||
T visit(KeywordHitsRootNode khrn);
|
||||
T visit(KeywordHits.RootNode khrn);
|
||||
|
||||
T visit(KeywordHitsListNode khsn);
|
||||
T visit(KeywordHits.ListNode khsn);
|
||||
|
||||
T visit(KeywordHitsKeywordNode khmln);
|
||||
T visit(KeywordHits.TermNode khmln);
|
||||
|
||||
T visit(HashsetHitsRootNode hhrn);
|
||||
T visit(HashsetHits.RootNode hhrn);
|
||||
|
||||
T visit(HashsetHitsSetNode hhsn);
|
||||
T visit(HashsetHits.HashsetNameNode hhsn);
|
||||
|
||||
T visit(EmailExtractedRootNode eern);
|
||||
T visit(EmailExtracted.RootNode eern);
|
||||
|
||||
T visit(EmailExtractedAccountNode eean);
|
||||
T visit(EmailExtracted.AccountNode eean);
|
||||
|
||||
T visit(EmailExtractedFolderNode eefn);
|
||||
T visit(EmailExtracted.FolderNode eefn);
|
||||
|
||||
T visit(TagsNode node);
|
||||
|
||||
T visit(InterestingHitsRootNode ihrn);
|
||||
T visit(InterestingHits.RootNode ihrn);
|
||||
|
||||
T visit(InterestingHitsSetNode ihsn);
|
||||
T visit(InterestingHits.SetNameNode ihsn);
|
||||
|
||||
T visit(TagNameNode node);
|
||||
|
||||
@ -155,12 +145,12 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(ArtifactTypeNode atn) {
|
||||
public T visit(ExtractedContent.TypeNode atn) {
|
||||
return defaultVisit(atn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(ExtractedContentNode ecn) {
|
||||
public T visit(ExtractedContent.RootNode ecn) {
|
||||
return defaultVisit(ecn);
|
||||
}
|
||||
|
||||
@ -205,17 +195,17 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(KeywordHitsRootNode khrn) {
|
||||
public T visit(KeywordHits.RootNode khrn) {
|
||||
return defaultVisit(khrn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(KeywordHitsListNode khsn) {
|
||||
public T visit(KeywordHits.ListNode khsn) {
|
||||
return defaultVisit(khsn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(KeywordHitsKeywordNode khmln) {
|
||||
public T visit(KeywordHits.TermNode khmln) {
|
||||
return defaultVisit(khmln);
|
||||
}
|
||||
|
||||
@ -235,37 +225,37 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(HashsetHitsRootNode hhrn) {
|
||||
public T visit(HashsetHits.RootNode hhrn) {
|
||||
return defaultVisit(hhrn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(HashsetHitsSetNode hhsn) {
|
||||
public T visit(HashsetHits.HashsetNameNode hhsn) {
|
||||
return defaultVisit(hhsn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(InterestingHitsRootNode ihrn) {
|
||||
public T visit(InterestingHits.RootNode ihrn) {
|
||||
return defaultVisit(ihrn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(InterestingHitsSetNode ihsn) {
|
||||
public T visit(InterestingHits.SetNameNode ihsn) {
|
||||
return defaultVisit(ihsn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(EmailExtractedRootNode eern) {
|
||||
public T visit(EmailExtracted.RootNode eern) {
|
||||
return defaultVisit(eern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(EmailExtractedAccountNode eean) {
|
||||
public T visit(EmailExtracted.AccountNode eean) {
|
||||
return defaultVisit(eean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(EmailExtractedFolderNode eefn) {
|
||||
public T visit(EmailExtracted.FolderNode eefn) {
|
||||
return defaultVisit(eefn);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@ -25,6 +27,9 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
@ -34,11 +39,14 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
|
||||
|
||||
/**
|
||||
* Support for TSK_EMAIL_MSG nodes and displaying emails in the directory tree
|
||||
* Email messages are grouped into parent folders, and the folders are grouped
|
||||
@ -54,64 +62,85 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
private static final String MAIL_FOLDER = NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.mailFolder.text");
|
||||
private static final String MAIL_PATH_SEPARATOR = "/";
|
||||
private SleuthkitCase skCase;
|
||||
private Map<String, Map<String, List<Long>>> accounts;
|
||||
private EmailResults emailResults;
|
||||
|
||||
|
||||
public EmailExtracted(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
accounts = new LinkedHashMap<>();
|
||||
emailResults = new EmailResults();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void initArtifacts() {
|
||||
accounts.clear();
|
||||
try {
|
||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID();
|
||||
int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID();
|
||||
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS
|
||||
+ "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "attribute_type_id=" + pathAttrId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
ResultSet rs = skCase.runQuery(query);
|
||||
while (rs.next()) {
|
||||
final String path = rs.getString("value_text"); //NON-NLS
|
||||
final long artifactId = rs.getLong("artifact_id"); //NON-NLS
|
||||
final Map<String, String> parsedPath = parsePath(path);
|
||||
final String account = parsedPath.get(MAIL_ACCOUNT);
|
||||
final String folder = parsedPath.get(MAIL_FOLDER);
|
||||
|
||||
Map<String, List<Long>> folders = accounts.get(account);
|
||||
if (folders == null) {
|
||||
folders = new LinkedHashMap<>();
|
||||
accounts.put(account, folders);
|
||||
}
|
||||
List<Long> messages = folders.get(folder);
|
||||
if (messages == null) {
|
||||
messages = new ArrayList<>();
|
||||
folders.put(folder, messages);
|
||||
}
|
||||
messages.add(artifactId);
|
||||
}
|
||||
skCase.closeRunQuery(rs);
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Cannot initialize email extraction", ex); //NON-NLS
|
||||
|
||||
private final class EmailResults extends Observable {
|
||||
private Map<String, Map<String, List<Long>>> accounts = new LinkedHashMap<>();
|
||||
|
||||
EmailResults() {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getAccounts() {
|
||||
return accounts.keySet();
|
||||
}
|
||||
|
||||
public Set<String> getFolders(String account) {
|
||||
return accounts.get(account).keySet();
|
||||
}
|
||||
|
||||
public List<Long> getArtifactIds(String account, String folder) {
|
||||
return accounts.get(account).get(folder);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
accounts.clear();
|
||||
try {
|
||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID();
|
||||
int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID();
|
||||
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS
|
||||
+ "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "attribute_type_id=" + pathAttrId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
ResultSet rs = skCase.runQuery(query);
|
||||
while (rs.next()) {
|
||||
final String path = rs.getString("value_text"); //NON-NLS
|
||||
final long artifactId = rs.getLong("artifact_id"); //NON-NLS
|
||||
final Map<String, String> parsedPath = parsePath(path);
|
||||
final String account = parsedPath.get(MAIL_ACCOUNT);
|
||||
final String folder = parsedPath.get(MAIL_FOLDER);
|
||||
|
||||
private static Map<String, String> parsePath(String path) {
|
||||
Map<String, String> parsed = new HashMap<>();
|
||||
String[] split = path.split(MAIL_PATH_SEPARATOR);
|
||||
if (split.length < 4) {
|
||||
logger.log(Level.WARNING, "Unexpected number of tokens when parsing email PATH: {0}, will use defaults", split.length); //NON-NLS
|
||||
parsed.put(MAIL_ACCOUNT, NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.defaultAcct.text"));
|
||||
parsed.put(MAIL_FOLDER, NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.defaultFolder.text"));
|
||||
Map<String, List<Long>> folders = accounts.get(account);
|
||||
if (folders == null) {
|
||||
folders = new LinkedHashMap<>();
|
||||
accounts.put(account, folders);
|
||||
}
|
||||
List<Long> messages = folders.get(folder);
|
||||
if (messages == null) {
|
||||
messages = new ArrayList<>();
|
||||
folders.put(folder, messages);
|
||||
}
|
||||
messages.add(artifactId);
|
||||
}
|
||||
skCase.closeRunQuery(rs);
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Cannot initialize email extraction", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> parsePath(String path) {
|
||||
Map<String, String> parsed = new HashMap<>();
|
||||
String[] split = path.split(MAIL_PATH_SEPARATOR);
|
||||
if (split.length < 4) {
|
||||
logger.log(Level.WARNING, "Unexpected number of tokens when parsing email PATH: {0}, will use defaults", split.length); //NON-NLS
|
||||
parsed.put(MAIL_ACCOUNT, NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.defaultAcct.text"));
|
||||
parsed.put(MAIL_FOLDER, NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.defaultFolder.text"));
|
||||
return parsed;
|
||||
}
|
||||
|
||||
parsed.put(MAIL_ACCOUNT, split[2]);
|
||||
parsed.put(MAIL_FOLDER, split[3]);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
parsed.put(MAIL_ACCOUNT, split[2]);
|
||||
parsed.put(MAIL_FOLDER, split[3]);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -122,94 +151,94 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
/**
|
||||
* Mail root node showing all emails
|
||||
*/
|
||||
public class EmailExtractedRootNodeFlat extends DisplayableItemNode {
|
||||
|
||||
public EmailExtractedRootNodeFlat() {
|
||||
super(Children.create(new EmailExtractedRootChildrenFlat(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
super.setName(LABEL_NAME);
|
||||
super.setDisplayName(DISPLAY_NAME);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); //NON-NLS
|
||||
initArtifacts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
//return v.visit(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@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<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.desc"),
|
||||
getName()));
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mail root child node showing flattened emails
|
||||
*/
|
||||
private class EmailExtractedRootChildrenFlat extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
private EmailExtractedRootChildrenFlat() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
//flatten all emails
|
||||
List<BlackboardArtifact> tempList = new ArrayList<>();
|
||||
for (String account : accounts.keySet()) {
|
||||
Map<String, List<Long>> folders = accounts.get(account);
|
||||
for (String folder : folders.keySet()) {
|
||||
List<Long> messages = folders.get(folder);
|
||||
for (long l : messages) {
|
||||
try {
|
||||
//TODO: bulk artifact gettings
|
||||
tempList.add(skCase.getBlackboardArtifact(l));
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "Error creating mail messages nodes", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list.addAll(tempList);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
||||
return new BlackboardArtifactNode(artifact);
|
||||
}
|
||||
}
|
||||
// public class FlatRootNode extends DisplayableItemNode {
|
||||
//
|
||||
// public FlatRootNode() {
|
||||
// super(Children.create(new FlatRootFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
// super.setName(LABEL_NAME);
|
||||
// super.setDisplayName(DISPLAY_NAME);
|
||||
// this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); //NON-NLS
|
||||
// initArtifacts();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isLeafTypeNode() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
// //return v.visit(this);
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @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<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
|
||||
// NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.displayName"),
|
||||
// NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.desc"),
|
||||
// getName()));
|
||||
// return s;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Mail root child node showing flattened emails
|
||||
// */
|
||||
// private class FlatRootFactory extends ChildFactory<BlackboardArtifact> {
|
||||
//
|
||||
// private FlatRootFactory() {
|
||||
// super();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
// //flatten all emails
|
||||
// List<BlackboardArtifact> tempList = new ArrayList<>();
|
||||
// for (String account : accounts.keySet()) {
|
||||
// Map<String, List<Long>> folders = accounts.get(account);
|
||||
// for (String folder : folders.keySet()) {
|
||||
// List<Long> messages = folders.get(folder);
|
||||
// for (long l : messages) {
|
||||
// try {
|
||||
// //TODO: bulk artifact gettings
|
||||
// tempList.add(skCase.getBlackboardArtifact(l));
|
||||
// } catch (TskException ex) {
|
||||
// logger.log(Level.WARNING, "Error creating mail messages nodes", ex); //NON-NLS
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// list.addAll(tempList);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Node createNodeForKey(BlackboardArtifact artifact) {
|
||||
// return new BlackboardArtifactNode(artifact);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Mail root node grouping all mail accounts, supports account-> folder
|
||||
* structure
|
||||
*/
|
||||
public class EmailExtractedRootNode extends DisplayableItemNode {
|
||||
public class RootNode extends DisplayableItemNode {
|
||||
|
||||
public EmailExtractedRootNode() {
|
||||
super(Children.create(new EmailExtractedRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
public RootNode() {
|
||||
super(Children.create(new AccountFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
super.setName(LABEL_NAME);
|
||||
super.setDisplayName(DISPLAY_NAME);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); //NON-NLS
|
||||
initArtifacts();
|
||||
emailResults.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -220,7 +249,6 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
//return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -244,30 +272,74 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
/**
|
||||
* Mail root child node creating each account node
|
||||
*/
|
||||
private class EmailExtractedRootChildren extends ChildFactory<String> {
|
||||
private class AccountFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||
|
||||
/* The pcl is in the class because it has the easiest mechanisms to add and remove itself
|
||||
* during its life cycles.
|
||||
*/
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
|
||||
if (eventType.equals(IngestManager.IngestEvent.DATA.toString())) {
|
||||
if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG) {
|
||||
emailResults.update();
|
||||
}
|
||||
}
|
||||
else if (eventType.equals(IngestManager.IngestEvent.INGEST_JOB_COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestEvent.INGEST_JOB_CANCELLED.toString())) {
|
||||
emailResults.update();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.addPropertyChangeListener(pcl);
|
||||
emailResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.removePropertyChangeListener(pcl);
|
||||
emailResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.addAll(accounts.keySet());
|
||||
list.addAll(emailResults.getAccounts());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new EmailExtractedAccountNode(key, accounts.get(key));
|
||||
return new AccountNode(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Account node representation
|
||||
*/
|
||||
public class EmailExtractedAccountNode extends DisplayableItemNode {
|
||||
|
||||
public EmailExtractedAccountNode(String name, Map<String, List<Long>> children) {
|
||||
super(Children.create(new EmailExtractedAccountChildrenNode(children), true), Lookups.singleton(name));
|
||||
super.setName(name);
|
||||
super.setDisplayName(name + " (" + children.size() + ")");
|
||||
public class AccountNode extends DisplayableItemNode implements Observer {
|
||||
private String accountName;
|
||||
|
||||
public AccountNode(String accountName) {
|
||||
super(Children.create(new FolderFactory(accountName), true), Lookups.singleton(accountName));
|
||||
super.setName(accountName);
|
||||
this.accountName = accountName;
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/account-icon-16.png"); //NON-NLS
|
||||
updateDisplayName();
|
||||
emailResults.addObserver(this);
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
super.setDisplayName(accountName + " (" + emailResults.getFolders(accountName) + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -296,43 +368,61 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Account node child creating sub nodes for every folder
|
||||
*/
|
||||
private class EmailExtractedAccountChildrenNode extends ChildFactory<String> {
|
||||
private class FolderFactory extends ChildFactory<String> implements Observer {
|
||||
|
||||
private Map<String, List<Long>> folders;
|
||||
private String accountName;
|
||||
|
||||
private EmailExtractedAccountChildrenNode(Map<String, List<Long>> folders) {
|
||||
private FolderFactory(String accountName) {
|
||||
super();
|
||||
this.folders = folders;
|
||||
this.accountName = accountName;
|
||||
emailResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.addAll(folders.keySet());
|
||||
|
||||
list.addAll(emailResults.getFolders(accountName));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new EmailExtractedFolderNode(key, folders.get(key));
|
||||
protected Node createNodeForKey(String folderName) {
|
||||
return new FolderNode(accountName, folderName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Node representing mail folder
|
||||
*/
|
||||
public class EmailExtractedFolderNode extends DisplayableItemNode {
|
||||
|
||||
public EmailExtractedFolderNode(String name, List<Long> children) {
|
||||
super(Children.create(new EmailExtractedFolderChildrenNode(children), true), Lookups.singleton(name));
|
||||
super.setName(name);
|
||||
super.setDisplayName(name + " (" + children.size() + ")");
|
||||
public class FolderNode extends DisplayableItemNode implements Observer {
|
||||
private String accountName;
|
||||
private String folderName;
|
||||
|
||||
public FolderNode(String accountName, String folderName) {
|
||||
super(Children.create(new MessageFactory(accountName, folderName), true), Lookups.singleton(accountName));
|
||||
super.setName(folderName);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-16.png"); //NON-NLS
|
||||
updateDisplayName();
|
||||
emailResults.addObserver(this);
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
super.setDisplayName(folderName + " (" + emailResults.getArtifactIds(accountName, folderName).size() + ")");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -361,38 +451,48 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Node representing mail folder content (mail messages)
|
||||
*/
|
||||
private class EmailExtractedFolderChildrenNode extends ChildFactory<BlackboardArtifact> {
|
||||
private class MessageFactory extends ChildFactory<Long> implements Observer {
|
||||
|
||||
private List<Long> messages;
|
||||
private String accountName;
|
||||
private String folderName;
|
||||
|
||||
private EmailExtractedFolderChildrenNode(List<Long> messages) {
|
||||
private MessageFactory(String accountName, String folderName) {
|
||||
super();
|
||||
this.messages = messages;
|
||||
this.accountName = accountName;
|
||||
this.folderName = folderName;
|
||||
emailResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
List<BlackboardArtifact> tempList = new ArrayList<>();
|
||||
for (long l : messages) {
|
||||
try {
|
||||
//TODO: bulk artifact gettings
|
||||
tempList.add(skCase.getBlackboardArtifact(l));
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "Error creating mail messages nodes", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
list.addAll(tempList);
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
list.addAll(emailResults.getArtifactIds(accountName, folderName));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
||||
return new BlackboardArtifactNode(artifact);
|
||||
protected Node createNodeForKey(Long artifactId) {
|
||||
try {
|
||||
BlackboardArtifact artifact = skCase.getBlackboardArtifact(artifactId);
|
||||
return new BlackboardArtifactNode(artifact);
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "Error creating mail messages nodes", ex); //NON-NLS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,17 +18,59 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CALENDAR_ENTRY;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INSTALLED_PROG;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
|
||||
/**
|
||||
* Parent of the "extracted content" artifacts to be displayed in the tree. Other
|
||||
* artifacts are displayed under other more specific parents.
|
||||
* Parent of the "extracted content" artifacts to be displayed in the tree.
|
||||
* Other artifacts are displayed under other more specific parents.
|
||||
*/
|
||||
class ExtractedContent implements AutopsyVisitableItem{
|
||||
public class ExtractedContent implements AutopsyVisitableItem {
|
||||
|
||||
SleuthkitCase skCase;
|
||||
private SleuthkitCase skCase;
|
||||
public static final String NAME = NbBundle.getMessage(RootNode.class, "ExtractedContentNode.name.text");
|
||||
|
||||
public ExtractedContent(SleuthkitCase skCase){
|
||||
public ExtractedContent(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
}
|
||||
|
||||
@ -37,7 +79,310 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
public SleuthkitCase getSleuthkitCase(){
|
||||
public SleuthkitCase getSleuthkitCase() {
|
||||
return skCase;
|
||||
}
|
||||
|
||||
public class RootNode extends DisplayableItemNode {
|
||||
|
||||
public RootNode(SleuthkitCase skCase) {
|
||||
super(Children.create(new TypeFactory(skCase), true), Lookups.singleton(NAME));
|
||||
super.setName(NAME);
|
||||
super.setDisplayName(NAME);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/extracted_content.png"); //NON-NLS
|
||||
}
|
||||
|
||||
@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<>(NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.desc"),
|
||||
NAME));
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the children for the ExtractedContent area of the results tree.
|
||||
* This area has all of the blackboard artifacts that are not displayed in a
|
||||
* more specific form elsewhere in the tree.
|
||||
*/
|
||||
private class TypeFactory extends ChildFactory.Detachable<BlackboardArtifact.ARTIFACT_TYPE> {
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final ArrayList<BlackboardArtifact.ARTIFACT_TYPE> doNotShow;
|
||||
// maps the artifact type to its child node
|
||||
private HashMap<BlackboardArtifact.ARTIFACT_TYPE, TypeNode> typeNodeList = new HashMap<>();
|
||||
|
||||
public TypeFactory(SleuthkitCase skCase) {
|
||||
super();
|
||||
this.skCase = skCase;
|
||||
|
||||
// these are shown in other parts of the UI tree
|
||||
doNotShow = new ArrayList<>();
|
||||
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO);
|
||||
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
|
||||
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT);
|
||||
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);
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
|
||||
if (eventType.equals(IngestManager.IngestEvent.DATA.toString())) {
|
||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||
if (doNotShow.contains(event.getArtifactType()) == false) {
|
||||
refresh(true);
|
||||
}
|
||||
} else if (eventType.equals(IngestManager.IngestEvent.INGEST_JOB_COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestEvent.INGEST_JOB_CANCELLED.toString())) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.addPropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.removePropertyChangeListener(pcl);
|
||||
typeNodeList.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact.ARTIFACT_TYPE> list) {
|
||||
try {
|
||||
List<BlackboardArtifact.ARTIFACT_TYPE> inUse = skCase.getBlackboardArtifactTypesInUse();
|
||||
inUse.removeAll(doNotShow);
|
||||
Collections.sort(inUse,
|
||||
new Comparator<BlackboardArtifact.ARTIFACT_TYPE>() {
|
||||
@Override
|
||||
public int compare(BlackboardArtifact.ARTIFACT_TYPE a, BlackboardArtifact.ARTIFACT_TYPE b) {
|
||||
return a.getDisplayName().compareTo(b.getDisplayName());
|
||||
}
|
||||
});
|
||||
list.addAll(inUse);
|
||||
|
||||
// the create node method will get called only for new types
|
||||
// refresh the counts if we already created them from a previous update
|
||||
for (BlackboardArtifact.ARTIFACT_TYPE art : inUse) {
|
||||
TypeNode node = typeNodeList.get(art);
|
||||
if (node != null) {
|
||||
node.updateDisplayName();
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(TypeFactory.class.getName()).log(Level.SEVERE, "Error getting list of artifacts in use: " + ex.getLocalizedMessage()); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact.ARTIFACT_TYPE key) {
|
||||
TypeNode node = new TypeNode(key, skCase);
|
||||
typeNodeList.put(key, node);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Node encapsulating blackboard artifact type. This is used on the
|
||||
* left-hand navigation side of the Autopsy UI as the parent node for all of
|
||||
* the artifacts of a given type. Its children will be
|
||||
* BlackboardArtifactNode objects.
|
||||
*/
|
||||
public class TypeNode extends DisplayableItemNode {
|
||||
|
||||
private BlackboardArtifact.ARTIFACT_TYPE type;
|
||||
private long childCount = 0;
|
||||
private SleuthkitCase skCase;
|
||||
|
||||
TypeNode(BlackboardArtifact.ARTIFACT_TYPE type, SleuthkitCase skCase) {
|
||||
super(Children.create(new ArtifactFactory(type, skCase), true), Lookups.singleton(type.getDisplayName()));
|
||||
super.setName(type.getLabel());
|
||||
this.skCase = skCase;
|
||||
this.type = type;
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/" + getIcon(type)); //NON-NLS
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
final void updateDisplayName() {
|
||||
// NOTE: This completely destroys our lazy-loading ideal
|
||||
// a performance increase might be had by adding a
|
||||
// "getBlackboardArtifactCount()" method to skCase
|
||||
try {
|
||||
this.childCount = skCase.getBlackboardArtifactsTypeCount(type.getTypeID());
|
||||
} catch (TskException ex) {
|
||||
Logger.getLogger(TypeNode.class.getName())
|
||||
.log(Level.WARNING, "Error getting child count", ex); //NON-NLS
|
||||
}
|
||||
super.setDisplayName(type.getDisplayName() + " (" + childCount + ")");
|
||||
}
|
||||
|
||||
@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<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"),
|
||||
type.getDisplayName()));
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"),
|
||||
childCount));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
// @@@ TODO: Merge with BlackboartArtifactNode.getIcon()
|
||||
private String getIcon(BlackboardArtifact.ARTIFACT_TYPE type) {
|
||||
switch (type) {
|
||||
case TSK_WEB_BOOKMARK:
|
||||
return "bookmarks.png"; //NON-NLS
|
||||
case TSK_WEB_COOKIE:
|
||||
return "cookies.png"; //NON-NLS
|
||||
case TSK_WEB_HISTORY:
|
||||
return "history.png"; //NON-NLS
|
||||
case TSK_WEB_DOWNLOAD:
|
||||
return "downloads.png"; //NON-NLS
|
||||
case TSK_INSTALLED_PROG:
|
||||
return "programs.png"; //NON-NLS
|
||||
case TSK_RECENT_OBJECT:
|
||||
return "recent_docs.png"; //NON-NLS
|
||||
case TSK_DEVICE_ATTACHED:
|
||||
return "usb_devices.png"; //NON-NLS
|
||||
case TSK_WEB_SEARCH_QUERY:
|
||||
return "searchquery.png"; //NON-NLS
|
||||
case TSK_METADATA_EXIF:
|
||||
return "camera-icon-16.png"; //NON-NLS
|
||||
case TSK_CONTACT:
|
||||
return "contact.png"; //NON-NLS
|
||||
case TSK_MESSAGE:
|
||||
return "message.png"; //NON-NLS
|
||||
case TSK_CALLLOG:
|
||||
return "calllog.png"; //NON-NLS
|
||||
case TSK_CALENDAR_ENTRY:
|
||||
return "calendar.png"; //NON-NLS
|
||||
case TSK_SPEED_DIAL_ENTRY:
|
||||
return "speeddialentry.png"; //NON-NLS
|
||||
case TSK_BLUETOOTH_PAIRING:
|
||||
return "bluetooth.png"; //NON-NLS
|
||||
case TSK_GPS_BOOKMARK:
|
||||
return "gpsfav.png"; //NON-NLS
|
||||
case TSK_GPS_LAST_KNOWN_LOCATION:
|
||||
return "gps-lastlocation.png"; //NON-NLS
|
||||
case TSK_GPS_SEARCH:
|
||||
return "gps-search.png"; //NON-NLS
|
||||
case TSK_SERVICE_ACCOUNT:
|
||||
return "account-icon-16.png"; //NON-NLS
|
||||
case TSK_ENCRYPTION_DETECTED:
|
||||
return "encrypted-file.png"; //NON-NLS
|
||||
case TSK_EXT_MISMATCH_DETECTED:
|
||||
return "mismatch-16.png"; //NON-NLS
|
||||
}
|
||||
return "artifact-icon.png"; //NON-NLS
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates children for a given artifact type
|
||||
*/
|
||||
private static class ArtifactFactory extends ChildFactory.Detachable<BlackboardArtifact> {
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private BlackboardArtifact.ARTIFACT_TYPE type;
|
||||
|
||||
public ArtifactFactory(BlackboardArtifact.ARTIFACT_TYPE type, SleuthkitCase skCase) {
|
||||
super();
|
||||
this.skCase = skCase;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
|
||||
if (eventType.equals(IngestManager.IngestEvent.DATA.toString())) {
|
||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||
if (event.getArtifactType() == type) {
|
||||
refresh(true);
|
||||
}
|
||||
} else if (eventType.equals(IngestManager.IngestEvent.INGEST_JOB_COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestEvent.INGEST_JOB_CANCELLED.toString())) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.addPropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
try {
|
||||
List<BlackboardArtifact> arts = skCase.getBlackboardArtifacts(type.getTypeID());
|
||||
list.addAll(arts);
|
||||
} catch (TskException ex) {
|
||||
Logger.getLogger(ArtifactFactory.class.getName()).log(Level.SEVERE, "Couldn't get blackboard artifacts from database", ex); //NON-NLS
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact key) {
|
||||
return new BlackboardArtifactNode(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,16 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
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.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@ -34,13 +38,16 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
|
||||
/**
|
||||
* Hash set hits node support
|
||||
* Hash set hits node support. Inner classes have all of the nodes in the tree.
|
||||
*/
|
||||
public class HashsetHits implements AutopsyVisitableItem {
|
||||
|
||||
@ -48,65 +55,85 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
private static final String DISPLAY_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName();
|
||||
private static final Logger logger = Logger.getLogger(HashsetHits.class.getName());
|
||||
private SleuthkitCase skCase;
|
||||
private Map<String, Set<Long>> hashSetHitsMap;
|
||||
|
||||
private HashsetResults hashsetResults;
|
||||
|
||||
public HashsetHits(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
hashSetHitsMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void initArtifacts() {
|
||||
hashSetHitsMap.clear();
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
int setNameId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID();
|
||||
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS
|
||||
+ "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "attribute_type_id=" + setNameId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
rs = skCase.runQuery(query);
|
||||
while (rs.next()) {
|
||||
String value = rs.getString("value_text"); //NON-NLS
|
||||
long artifactId = rs.getLong("artifact_id"); //NON-NLS
|
||||
if (!hashSetHitsMap.containsKey(value)) {
|
||||
hashSetHitsMap.put(value, new HashSet<Long>());
|
||||
}
|
||||
hashSetHitsMap.get(value).add(artifactId);
|
||||
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
|
||||
} finally {
|
||||
if (rs != null) {
|
||||
try {
|
||||
skCase.closeRunQuery(rs);
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Error closing result set after getting hashset hits", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
hashsetResults = new HashsetResults();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores all of the hashset results in a single class that is observable for the
|
||||
* child nodes
|
||||
*/
|
||||
private class HashsetResults extends Observable {
|
||||
// maps hashset name to list of artifacts for that set
|
||||
private Map<String, Set<Long>> hashSetHitsMap = new LinkedHashMap<>();
|
||||
|
||||
HashsetResults() {
|
||||
update();
|
||||
}
|
||||
|
||||
Set<String> getSetNames() {
|
||||
return hashSetHitsMap.keySet();
|
||||
}
|
||||
|
||||
Set<Long> getArtifactIds(String hashSetName) {
|
||||
return hashSetHitsMap.get(hashSetName);
|
||||
}
|
||||
|
||||
final void update() {
|
||||
hashSetHitsMap.clear();
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
int setNameId = ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
||||
int artId = ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID();
|
||||
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS
|
||||
+ "FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "attribute_type_id=" + setNameId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
rs = skCase.runQuery(query);
|
||||
while (rs.next()) {
|
||||
String setName = rs.getString("value_text"); //NON-NLS
|
||||
long artifactId = rs.getLong("artifact_id"); //NON-NLS
|
||||
if (!hashSetHitsMap.containsKey(setName)) {
|
||||
hashSetHitsMap.put(setName, new HashSet<Long>());
|
||||
}
|
||||
hashSetHitsMap.get(setName).add(artifactId);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
|
||||
} finally {
|
||||
if (rs != null) {
|
||||
try {
|
||||
skCase.closeRunQuery(rs);
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Error closing result set after getting hashset hits", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Node for the hash set hits
|
||||
* Top-level node for all hash sets
|
||||
*/
|
||||
public class HashsetHitsRootNode extends DisplayableItemNode {
|
||||
public class RootNode extends DisplayableItemNode {
|
||||
|
||||
public HashsetHitsRootNode() {
|
||||
super(Children.create(new HashsetHitsRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
public RootNode() {
|
||||
super(Children.create(new HashsetNameFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
super.setName(HASHSET_HITS);
|
||||
super.setDisplayName(DISPLAY_NAME);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); //NON-NLS
|
||||
initArtifacts();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -137,27 +164,80 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
private class HashsetHitsRootChildren extends ChildFactory<String> {
|
||||
/**
|
||||
* Creates child nodes for each hashset name
|
||||
*/
|
||||
private class HashsetNameFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||
|
||||
/* This should probably be in the HashsetHits class, but the factory has nice methods
|
||||
* for its startup and shutdown, so it seemed like a cleaner place to register the
|
||||
* property change listener.
|
||||
*/
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
|
||||
if (eventType.equals(IngestManager.IngestEvent.DATA.toString())) {
|
||||
if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == ARTIFACT_TYPE.TSK_HASHSET_HIT) {
|
||||
hashsetResults.update();
|
||||
}
|
||||
}
|
||||
else if (eventType.equals(IngestManager.IngestEvent.INGEST_JOB_COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestEvent.INGEST_JOB_CANCELLED.toString())) {
|
||||
hashsetResults.update();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.addAll(hashSetHitsMap.keySet());
|
||||
protected void addNotify() {
|
||||
IngestManager.addPropertyChangeListener(pcl);
|
||||
hashsetResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.removePropertyChangeListener(pcl);
|
||||
hashsetResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.addAll(hashsetResults.getSetNames());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new HashsetHitsSetNode(key, hashSetHitsMap.get(key));
|
||||
return new HashsetNameNode(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
public class HashsetHitsSetNode extends DisplayableItemNode {
|
||||
|
||||
public HashsetHitsSetNode(String name, Set<Long> children) {
|
||||
super(Children.create(new HashsetHitsSetChildren(children), true), Lookups.singleton(name));
|
||||
super.setName(name);
|
||||
super.setDisplayName(name + " (" + children.size() + ")");
|
||||
/**
|
||||
* Node for a hash set name
|
||||
*/
|
||||
public class HashsetNameNode extends DisplayableItemNode implements Observer {
|
||||
private String hashSetName;
|
||||
public HashsetNameNode(String hashSetName) {
|
||||
super(Children.create(new HitFactory(hashSetName), true), Lookups.singleton(hashSetName));
|
||||
super.setName(hashSetName);
|
||||
super.setDisplayName(hashSetName + " (0)");
|
||||
this.hashSetName = hashSetName;
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); //NON-NLS
|
||||
hashsetResults.addObserver(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the count in the display name
|
||||
*/
|
||||
private void updateName() {
|
||||
super.setDisplayName(hashSetName + " (" + hashsetResults.getArtifactIds(hashSetName).size() + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -186,33 +266,54 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateName();
|
||||
}
|
||||
}
|
||||
|
||||
private class HashsetHitsSetChildren extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
private Set<Long> children;
|
||||
|
||||
private HashsetHitsSetChildren(Set<Long> children) {
|
||||
/**
|
||||
* Creates the nodes for the hits in a given set.
|
||||
*/
|
||||
private class HitFactory extends ChildFactory.Detachable<Long> implements Observer {
|
||||
private String hashsetName;
|
||||
|
||||
private HitFactory(String hashsetName) {
|
||||
super();
|
||||
this.children = children;
|
||||
this.hashsetName = hashsetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
hashsetResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
for (long l : children) {
|
||||
try {
|
||||
//TODO: bulk artifact gettings
|
||||
list.add(skCase.getBlackboardArtifact(l));
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
protected void removeNotify() {
|
||||
hashsetResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
list.addAll(hashsetResults.getArtifactIds(hashsetName));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
||||
return new BlackboardArtifactNode(artifact);
|
||||
protected Node createNodeForKey(Long id) {
|
||||
try {
|
||||
BlackboardArtifact art = skCase.getBlackboardArtifact(id);
|
||||
return new BlackboardArtifactNode(art);
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -106,10 +106,10 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
/**
|
||||
* Node for the interesting items
|
||||
*/
|
||||
public class InterestingHitsRootNode extends DisplayableItemNode {
|
||||
public class RootNode extends DisplayableItemNode {
|
||||
|
||||
public InterestingHitsRootNode() {
|
||||
super(Children.create(new InterestingHitsRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
public RootNode() {
|
||||
super(Children.create(new SetNameFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||
super.setName(INTERESTING_ITEMS);
|
||||
super.setDisplayName(DISPLAY_NAME);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||
@ -144,7 +144,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
private class InterestingHitsRootChildren extends ChildFactory<String> {
|
||||
private class SetNameFactory extends ChildFactory<String> {
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
@ -154,14 +154,14 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new InterestingHitsSetNode(key, interestingItemsMap.get(key));
|
||||
return new SetNameNode(key, interestingItemsMap.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
public class InterestingHitsSetNode extends DisplayableItemNode {
|
||||
public class SetNameNode extends DisplayableItemNode {
|
||||
|
||||
public InterestingHitsSetNode(String name, Set<Long> children) {
|
||||
super(Children.create(new InterestingHitsSetChildren(children), true), Lookups.singleton(name));
|
||||
public SetNameNode(String name, Set<Long> children) {
|
||||
super(Children.create(new HitFactory(children), true), Lookups.singleton(name));
|
||||
super.setName(name);
|
||||
super.setDisplayName(name + " (" + children.size() + ")");
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||
@ -195,11 +195,11 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
private class InterestingHitsSetChildren extends ChildFactory<BlackboardArtifact> {
|
||||
private class HitFactory extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
private Set<Long> children;
|
||||
|
||||
private InterestingHitsSetChildren(Set<Long> children) {
|
||||
private HitFactory(Set<Long> children) {
|
||||
super();
|
||||
this.children = children;
|
||||
}
|
||||
|
@ -18,13 +18,16 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
@ -34,6 +37,8 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
@ -54,101 +59,123 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
.getMessage(KeywordHits.class, "KeywordHits.simpleLiteralSearch.text");
|
||||
public static final String SIMPLE_REGEX_SEARCH = NbBundle
|
||||
.getMessage(KeywordHits.class, "KeywordHits.singleRegexSearch.text");
|
||||
// Map from String (list name) to Map from string (keyword) to set<long> (artifact ids)
|
||||
private Map<String, Map<String, Set<Long>>> topLevelMap;
|
||||
private Map<String, Map<String, Set<Long>>> listsMap;
|
||||
// Map from String (literal keyword) to set<long> (artifact ids)
|
||||
private Map<String, Set<Long>> literalMap;
|
||||
// Map from String (regex keyword) to set<long> (artifact ids);
|
||||
private Map<String, Set<Long>> regexMap;
|
||||
Map<Long, Map<Long, String>> artifacts;
|
||||
private KeywordResults keywordResults;
|
||||
|
||||
public KeywordHits(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
artifacts = new LinkedHashMap<>();
|
||||
listsMap = new LinkedHashMap<>();
|
||||
literalMap = new LinkedHashMap<>();
|
||||
regexMap = new LinkedHashMap<>();
|
||||
topLevelMap = new LinkedHashMap<>();
|
||||
keywordResults = new KeywordResults();
|
||||
}
|
||||
|
||||
private void initMaps() {
|
||||
topLevelMap.clear();
|
||||
topLevelMap.put(SIMPLE_LITERAL_SEARCH, literalMap);
|
||||
topLevelMap.put(SIMPLE_REGEX_SEARCH, regexMap);
|
||||
listsMap.clear();
|
||||
regexMap.clear();
|
||||
literalMap.clear();
|
||||
for (Map.Entry<Long, Map<Long, String>> art : artifacts.entrySet()) {
|
||||
long id = art.getKey();
|
||||
Map<Long, String> attributes = art.getValue();
|
||||
// I think we can use attributes.remove(...) here?
|
||||
String listName = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()));
|
||||
String word = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()));
|
||||
String reg = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()));
|
||||
if (listName != null) {
|
||||
if (!listsMap.containsKey(listName)) {
|
||||
listsMap.put(listName, new LinkedHashMap<String, Set<Long>>());
|
||||
}
|
||||
if (!listsMap.get(listName).containsKey(word)) {
|
||||
listsMap.get(listName).put(word, new HashSet<Long>());
|
||||
}
|
||||
listsMap.get(listName).get(word).add(id);
|
||||
} else if (reg != null) {
|
||||
if (!regexMap.containsKey(reg)) {
|
||||
regexMap.put(reg, new HashSet<Long>());
|
||||
}
|
||||
regexMap.get(reg).add(id);
|
||||
} else {
|
||||
if (!literalMap.containsKey(word)) {
|
||||
literalMap.put(word, new HashSet<Long>());
|
||||
}
|
||||
literalMap.get(word).add(id);
|
||||
}
|
||||
topLevelMap.putAll(listsMap);
|
||||
|
||||
private final class KeywordResults extends Observable {
|
||||
// Map from listName/Type to Map of keyword to set of artifact Ids
|
||||
private Map<String, Map<String, Set<Long>>> topLevelMap;
|
||||
|
||||
KeywordResults() {
|
||||
topLevelMap = new LinkedHashMap<>();
|
||||
update();
|
||||
}
|
||||
|
||||
Set<String> getListNames() {
|
||||
return topLevelMap.keySet();
|
||||
}
|
||||
|
||||
Set<String> getKeywords(String listName) {
|
||||
return topLevelMap.get(listName).keySet();
|
||||
}
|
||||
|
||||
Set<Long> getArtifactIds(String listName, String keyword) {
|
||||
return topLevelMap.get(listName).get(keyword);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void initArtifacts() {
|
||||
artifacts.clear();
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
int setId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
||||
int wordId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID();
|
||||
int regexId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID();
|
||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID();
|
||||
String query = "SELECT blackboard_attributes.value_text,blackboard_attributes.artifact_id," //NON-NLS
|
||||
+ "blackboard_attributes.attribute_type_id FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "(blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id AND " //NON-NLS
|
||||
+ "blackboard_artifacts.artifact_type_id=" + artId //NON-NLS
|
||||
+ ") AND (attribute_type_id=" + setId + " OR " //NON-NLS
|
||||
+ "attribute_type_id=" + wordId + " OR " //NON-NLS
|
||||
+ "attribute_type_id=" + regexId + ")"; //NON-NLS
|
||||
rs = skCase.runQuery(query);
|
||||
while (rs.next()) {
|
||||
String value = rs.getString("value_text"); //NON-NLS
|
||||
long artifactId = rs.getLong("artifact_id"); //NON-NLS
|
||||
long typeId = rs.getLong("attribute_type_id"); //NON-NLS
|
||||
if (!artifacts.containsKey(artifactId)) {
|
||||
artifacts.put(artifactId, new LinkedHashMap<Long, String>());
|
||||
// populate maps based on artifactIds
|
||||
void populateMaps(Map<Long, Map<Long, String>> artifactIds) {
|
||||
topLevelMap.clear();
|
||||
|
||||
Map<String, Map<String, Set<Long>>> listsMap = new LinkedHashMap<>();
|
||||
// Map from String (literal keyword) to set<long> (artifact ids)
|
||||
Map<String, Set<Long>> literalMap = new LinkedHashMap<>();
|
||||
// Map from String (regex keyword) to set<long> (artifact ids);
|
||||
Map<String, Set<Long>> regexMap = new LinkedHashMap<>();
|
||||
|
||||
|
||||
// top-level nodes
|
||||
topLevelMap.put(SIMPLE_LITERAL_SEARCH, literalMap);
|
||||
topLevelMap.put(SIMPLE_REGEX_SEARCH, regexMap);
|
||||
|
||||
for (Map.Entry<Long, Map<Long, String>> art : artifactIds.entrySet()) {
|
||||
long id = art.getKey();
|
||||
Map<Long, String> attributes = art.getValue();
|
||||
|
||||
// I think we can use attributes.remove(...) here?
|
||||
String listName = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()));
|
||||
String word = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()));
|
||||
String reg = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()));
|
||||
if (listName != null) {
|
||||
if (!listsMap.containsKey(listName)) {
|
||||
listsMap.put(listName, new LinkedHashMap<String, Set<Long>>());
|
||||
}
|
||||
if (!listsMap.get(listName).containsKey(word)) {
|
||||
listsMap.get(listName).put(word, new HashSet<Long>());
|
||||
}
|
||||
listsMap.get(listName).get(word).add(id);
|
||||
} else if (reg != null) {
|
||||
if (!regexMap.containsKey(reg)) {
|
||||
regexMap.put(reg, new HashSet<Long>());
|
||||
}
|
||||
regexMap.get(reg).add(id);
|
||||
} else {
|
||||
if (!literalMap.containsKey(word)) {
|
||||
literalMap.put(word, new HashSet<Long>());
|
||||
}
|
||||
literalMap.get(word).add(id);
|
||||
}
|
||||
if (!value.equals("")) {
|
||||
artifacts.get(artifactId).put(typeId, value);
|
||||
}
|
||||
|
||||
topLevelMap.putAll(listsMap);
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
|
||||
} finally {
|
||||
if (rs != null) {
|
||||
try {
|
||||
skCase.closeRunQuery(rs);
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Error closing result set after getting keyword hits", ex); //NON-NLS
|
||||
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
Map<Long, Map<Long, String>> artifactIds = new LinkedHashMap<>();
|
||||
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
int setId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
||||
int wordId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID();
|
||||
int regexId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID();
|
||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID();
|
||||
String query = "SELECT blackboard_attributes.value_text,blackboard_attributes.artifact_id," //NON-NLS
|
||||
+ "blackboard_attributes.attribute_type_id FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "(blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id AND " //NON-NLS
|
||||
+ "blackboard_artifacts.artifact_type_id=" + artId //NON-NLS
|
||||
+ ") AND (attribute_type_id=" + setId + " OR " //NON-NLS
|
||||
+ "attribute_type_id=" + wordId + " OR " //NON-NLS
|
||||
+ "attribute_type_id=" + regexId + ")"; //NON-NLS
|
||||
rs = skCase.runQuery(query);
|
||||
while (rs.next()) {
|
||||
String value = rs.getString("value_text"); //NON-NLS
|
||||
long artifactId = rs.getLong("artifact_id"); //NON-NLS
|
||||
long typeId = rs.getLong("attribute_type_id"); //NON-NLS
|
||||
if (!artifactIds.containsKey(artifactId)) {
|
||||
artifactIds.put(artifactId, new LinkedHashMap<Long, String>());
|
||||
}
|
||||
if (!value.equals("")) {
|
||||
artifactIds.get(artifactId).put(typeId, value);
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
|
||||
} finally {
|
||||
if (rs != null) {
|
||||
try {
|
||||
skCase.closeRunQuery(rs);
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Error closing result set after getting keyword hits", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
populateMaps(artifactIds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,15 +184,14 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
public class KeywordHitsRootNode extends DisplayableItemNode {
|
||||
// Created by CreateAutopsyNodeVisitor
|
||||
public class RootNode extends DisplayableItemNode {
|
||||
|
||||
public KeywordHitsRootNode() {
|
||||
super(Children.create(new KeywordHitsRootChildren(), true), Lookups.singleton(KEYWORD_HITS));
|
||||
public RootNode() {
|
||||
super(Children.create(new ListFactory(), true), Lookups.singleton(KEYWORD_HITS));
|
||||
super.setName(NAME);
|
||||
super.setDisplayName(KEYWORD_HITS);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
||||
initArtifacts();
|
||||
initMaps();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -196,36 +222,73 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
private class KeywordHitsRootChildren extends ChildFactory<String> {
|
||||
private class ListFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
|
||||
if (eventType.equals(IngestManager.IngestEvent.DATA.toString())) {
|
||||
if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT) {
|
||||
keywordResults.update();
|
||||
}
|
||||
}
|
||||
else if (eventType.equals(IngestManager.IngestEvent.INGEST_JOB_COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestEvent.INGEST_JOB_CANCELLED.toString())) {
|
||||
keywordResults.update();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.addPropertyChangeListener(pcl);
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.removePropertyChangeListener(pcl);
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.addAll(topLevelMap.keySet());
|
||||
list.addAll(keywordResults.getListNames());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new KeywordHitsListNode(key, topLevelMap.get(key));
|
||||
return new ListNode(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
public class KeywordHitsListNode extends DisplayableItemNode {
|
||||
public class ListNode extends DisplayableItemNode implements Observer {
|
||||
private String listName;
|
||||
|
||||
private String name;
|
||||
private Map<String, Set<Long>> children;
|
||||
|
||||
public KeywordHitsListNode(String name, Map<String, Set<Long>> children) {
|
||||
super(Children.create(new KeywordHitsListChildren(children), true), Lookups.singleton(name));
|
||||
super.setName(name);
|
||||
int totalDescendants = 0;
|
||||
for (Set<Long> grandChildren : children.values()) {
|
||||
totalDescendants += grandChildren.size();
|
||||
}
|
||||
super.setDisplayName(name + " (" + totalDescendants + ")");
|
||||
public ListNode(String listName) {
|
||||
super(Children.create(new TermFactory(listName), true), Lookups.singleton(listName));
|
||||
super.setName(listName);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
||||
this.name = name;
|
||||
this.children = children;
|
||||
this.listName = listName;
|
||||
updateDisplayName();
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
int totalDescendants = 0;
|
||||
for (String word : keywordResults.getKeywords(listName)) {
|
||||
Set<Long> ids = keywordResults.getArtifactIds(listName, word);
|
||||
totalDescendants += ids.size();
|
||||
}
|
||||
super.setDisplayName(listName + " (" + totalDescendants + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -240,13 +303,13 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.desc"),
|
||||
name));
|
||||
listName));
|
||||
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.desc"),
|
||||
children.size()));
|
||||
keywordResults.getKeywords(listName).size()));
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -260,39 +323,71 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
private class KeywordHitsListChildren extends ChildFactory<String> {
|
||||
|
||||
private Map<String, Set<Long>> children;
|
||||
|
||||
private KeywordHitsListChildren(Map<String, Set<Long>> children) {
|
||||
private class TermFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||
private String setName;
|
||||
|
||||
private TermFactory(String setName) {
|
||||
super();
|
||||
this.children = children;
|
||||
this.setName = setName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.addAll(children.keySet());
|
||||
list.addAll(keywordResults.getKeywords(setName));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new KeywordHitsKeywordNode(key, children.get(key));
|
||||
return new TermNode(setName, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
public class KeywordHitsKeywordNode extends DisplayableItemNode {
|
||||
public class TermNode extends DisplayableItemNode implements Observer {
|
||||
|
||||
private Set<Long> children;
|
||||
private String setName;
|
||||
private String keyword;
|
||||
|
||||
public KeywordHitsKeywordNode(String name, Set<Long> children) {
|
||||
super(Children.create(new KeywordHitsKeywordChildren(children), true), Lookups.singleton(name));
|
||||
super.setName(name);
|
||||
super.setDisplayName(name + " (" + children.size() + ")");
|
||||
public TermNode(String setName, String keyword) {
|
||||
super(Children.create(new HitsFactory (setName, keyword), true), Lookups.singleton(keyword));
|
||||
super.setName(keyword);
|
||||
this.setName = setName;
|
||||
this.keyword = keyword;
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
||||
this.children = children;
|
||||
updateDisplayName();
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
super.setDisplayName(keyword + " (" + keywordResults.getArtifactIds(setName, keyword).size() + ")");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -322,70 +417,83 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.desc"),
|
||||
children.size()));
|
||||
keywordResults.getArtifactIds(setName, keyword).size()));
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
private class KeywordHitsKeywordChildren extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
private Set<Long> children;
|
||||
|
||||
private KeywordHitsKeywordChildren(Set<Long> children) {
|
||||
public class HitsFactory extends ChildFactory.Detachable<Long> implements Observer {
|
||||
private String keyword;
|
||||
private String setName;
|
||||
|
||||
public HitsFactory(String setName, String keyword) {
|
||||
super();
|
||||
this.children = children;
|
||||
this.setName = setName;
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
List<BlackboardArtifact> tempList = new ArrayList<>();
|
||||
for (long l : children) {
|
||||
try {
|
||||
//TODO: bulk artifact gettings
|
||||
tempList.add(skCase.getBlackboardArtifact(l));
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
list.addAll(tempList);
|
||||
protected void removeNotify() {
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
list.addAll(keywordResults.getArtifactIds(setName, keyword));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
||||
BlackboardArtifactNode n = new BlackboardArtifactNode(artifact);
|
||||
AbstractFile file;
|
||||
protected Node createNodeForKey(Long artifactId) {
|
||||
try {
|
||||
file = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "TskCoreException while constructing BlackboardArtifact Node from KeywordHitsKeywordChildren"); //NON-NLS
|
||||
return n;
|
||||
BlackboardArtifact art = skCase.getBlackboardArtifact(artifactId);
|
||||
BlackboardArtifactNode n = new BlackboardArtifactNode(art);
|
||||
AbstractFile file;
|
||||
try {
|
||||
file = art.getSleuthkitCase().getAbstractFileById(art.getObjectID());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "TskCoreException while constructing BlackboardArtifact Node from KeywordHitsKeywordChildren"); //NON-NLS
|
||||
return n;
|
||||
}
|
||||
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.modTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.modTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.modTime.desc"),
|
||||
ContentUtils.getStringTime(file.getMtime(), file)));
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.accessTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.accessTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.accessTime.desc"),
|
||||
ContentUtils.getStringTime(file.getAtime(), file)));
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.chgTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.chgTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.chgTime.desc"),
|
||||
ContentUtils.getStringTime(file.getCtime(), file)));
|
||||
return n;
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.modTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.modTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.modTime.desc"),
|
||||
ContentUtils.getStringTime(file.getMtime(), file)));
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.accessTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.accessTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.accessTime.desc"),
|
||||
ContentUtils.getStringTime(file.getAtime(), file)));
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.chgTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.chgTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.chgTime.desc"),
|
||||
ContentUtils.getStringTime(file.getCtime(), file)));
|
||||
|
||||
return n;
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ public class RootContentChildren extends AbstractContentChildren<Object> {
|
||||
//TODO this will be removed, Children should be listening for interesting
|
||||
//events from datamodel and calling refresh / refreshKey() themselves
|
||||
public void refreshKeys(BlackboardArtifact.ARTIFACT_TYPE... types) {
|
||||
// find the corresponding top-level node and refresh its children.
|
||||
// should be more effeciently stored than a list.
|
||||
for (Object o : contentKeys) {
|
||||
for (BlackboardArtifact.ARTIFACT_TYPE type : types) {
|
||||
switch (type) {
|
||||
@ -91,8 +93,10 @@ public class RootContentChildren extends AbstractContentChildren<Object> {
|
||||
this.refreshKey(o);
|
||||
break;
|
||||
default:
|
||||
if (o instanceof ExtractedContent)
|
||||
if (o instanceof ExtractedContent) {
|
||||
|
||||
this.refreshKey(o);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.directorytree.BlackboardArtifactTagTypeNode;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
@ -52,22 +53,26 @@ public class TagNameNode extends DisplayableItemNode {
|
||||
NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName())));
|
||||
this.tagName = tagName;
|
||||
|
||||
long tagsCount = 0;
|
||||
try {
|
||||
tagsCount = Case.getCurrentCase().getServices().getTagsManager().getContentTagsCountByTagName(tagName);
|
||||
tagsCount += Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName);
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
||||
}
|
||||
|
||||
super.setName(tagName.getDisplayName());
|
||||
super.setDisplayName(tagName.getDisplayName() + " (" + tagsCount + ")");
|
||||
setName(tagName.getDisplayName());
|
||||
updateDisplayName();
|
||||
if (tagName.getDisplayName().equals(NbBundle.getMessage(this.getClass(), "TagNameNode.bookmark.text"))) {
|
||||
setIconBaseWithExtension(BOOKMARK_TAG_ICON_PATH);
|
||||
} else {
|
||||
setIconBaseWithExtension(ICON_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
long tagsCount = 0;
|
||||
try {
|
||||
TagsManager tm = Case.getCurrentCase().getServices().getTagsManager();
|
||||
tagsCount = tm.getContentTagsCountByTagName(tagName);
|
||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName);
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
||||
}
|
||||
setDisplayName(tagName.getDisplayName() + " (" + tagsCount + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
@ -28,6 +30,9 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -76,8 +81,36 @@ class TagsNode extends DisplayableItemNode {
|
||||
return propertySheet;
|
||||
}
|
||||
|
||||
private static class TagNameNodeFactory extends ChildFactory<TagName> {
|
||||
private static class TagNameNodeFactory extends ChildFactory.Detachable<TagName> {
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
|
||||
if (eventType.equals(IngestManager.IngestEvent.DATA.toString())) {
|
||||
if ((((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT) ||
|
||||
((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
else if (eventType.equals(IngestManager.IngestEvent.INGEST_JOB_COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestEvent.INGEST_JOB_CANCELLED.toString())) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
IngestManager.addPropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
IngestManager.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<TagName> keys) {
|
||||
try {
|
||||
|
@ -33,14 +33,12 @@ import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.FilterNode;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ArtifactTypeNode;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentTagTypeNode;
|
||||
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
||||
@ -48,27 +46,27 @@ import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.De
|
||||
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ExtractedContentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.AccountNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.FolderNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted;
|
||||
import org.sleuthkit.autopsy.datamodel.ExtractedContent.TypeNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||
import org.sleuthkit.autopsy.datamodel.FileTypeNode;
|
||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
|
||||
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.HashsetHits;
|
||||
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetNameNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ImageNode;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode;
|
||||
import org.sleuthkit.autopsy.datamodel.InterestingHits;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.TermNode;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.ListNode;
|
||||
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
||||
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
||||
import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode;
|
||||
import org.sleuthkit.autopsy.datamodel.RecentFilesNode;
|
||||
import org.sleuthkit.autopsy.datamodel.FileTypesNode;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||
import org.sleuthkit.autopsy.datamodel.TagNameNode;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@ -367,47 +365,47 @@ public class DataResultFilterNode extends FilterNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(ExtractedContentNode ecn) {
|
||||
public AbstractAction visit(ExtractedContent.RootNode ecn) {
|
||||
return openChild(ecn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(KeywordHitsRootNode khrn) {
|
||||
public AbstractAction visit(KeywordHits.RootNode khrn) {
|
||||
return openChild(khrn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(HashsetHitsRootNode hhrn) {
|
||||
public AbstractAction visit(HashsetHits.RootNode hhrn) {
|
||||
return openChild(hhrn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(HashsetHitsSetNode hhsn) {
|
||||
public AbstractAction visit(HashsetNameNode hhsn) {
|
||||
return openChild(hhsn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(InterestingHitsRootNode iarn) {
|
||||
public AbstractAction visit(InterestingHits.RootNode iarn) {
|
||||
return openChild(iarn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(InterestingHitsSetNode iasn) {
|
||||
public AbstractAction visit(InterestingHits.SetNameNode iasn) {
|
||||
return openChild(iasn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(EmailExtractedRootNode eern) {
|
||||
public AbstractAction visit(EmailExtracted.RootNode eern) {
|
||||
return openChild(eern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(EmailExtractedAccountNode eean) {
|
||||
public AbstractAction visit(AccountNode eean) {
|
||||
return openChild(eean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(EmailExtractedFolderNode eefn) {
|
||||
public AbstractAction visit(FolderNode eefn) {
|
||||
return openChild(eefn);
|
||||
}
|
||||
|
||||
@ -443,7 +441,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(ArtifactTypeNode atn) {
|
||||
public AbstractAction visit(TypeNode atn) {
|
||||
return openChild(atn);
|
||||
}
|
||||
|
||||
@ -516,12 +514,12 @@ public class DataResultFilterNode extends FilterNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(KeywordHitsListNode khsn) {
|
||||
public AbstractAction visit(ListNode khsn) {
|
||||
return openChild(khsn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(KeywordHitsKeywordNode khmln) {
|
||||
public AbstractAction visit(TermNode khmln) {
|
||||
return openChild(khmln);
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.BlackboardResultViewer;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ExtractedContentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ExtractedContent.RootNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DataSources;
|
||||
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||
@ -73,6 +73,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
||||
|
||||
/**
|
||||
* Top component which displays something.
|
||||
@ -387,7 +388,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
|
||||
Children resultsChilds = results.getChildren();
|
||||
tree.expandNode(resultsChilds.findChild(KeywordHits.NAME));
|
||||
tree.expandNode(resultsChilds.findChild(ExtractedContentNode.NAME));
|
||||
tree.expandNode(resultsChilds.findChild(ExtractedContent.NAME));
|
||||
|
||||
|
||||
Node views = childNodes.findChild(ViewsNode.NAME);
|
||||
@ -587,7 +588,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
// change in node selection
|
||||
else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
respondSelection((Node[]) oldValue, (Node[]) newValue);
|
||||
} else if (changed.equals(IngestEvent.DATA.toString())) {
|
||||
}
|
||||
else if (changed.equals(IngestEvent.DATA.toString())) {
|
||||
final ModuleDataEvent event = (ModuleDataEvent) oldValue;
|
||||
if (event.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO) {
|
||||
return;
|
||||
@ -595,7 +597,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshTree(event.getArtifactType());
|
||||
// @@@ refreshResultsTree(event.getArtifactType());
|
||||
}
|
||||
});
|
||||
} else if (changed.equals(IngestEvent.INGEST_JOB_COMPLETED.toString())
|
||||
@ -603,15 +605,15 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshContentTree();
|
||||
refreshTree();
|
||||
refreshDataSourceTree();
|
||||
refreshResultsTree();
|
||||
}
|
||||
});
|
||||
} else if (changed.equals(IngestEvent.CONTENT_CHANGED.toString())) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshContentTree();
|
||||
refreshDataSourceTree();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -768,7 +770,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshContentTree();
|
||||
refreshDataSourceTree();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -776,7 +778,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
/**
|
||||
* Refreshes changed content nodes
|
||||
*/
|
||||
void refreshContentTree() {
|
||||
private void refreshDataSourceTree() {
|
||||
Node selectedNode = getSelectedNode();
|
||||
final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
|
||||
|
||||
@ -809,7 +811,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
* Refreshes the nodes in the tree to reflect updates in the database should
|
||||
* be called in the gui thread
|
||||
*/
|
||||
public void refreshTree(final BlackboardArtifact.ARTIFACT_TYPE... types) {
|
||||
public void refreshResultsTree(final BlackboardArtifact.ARTIFACT_TYPE... types) {
|
||||
//save current selection
|
||||
Node selectedNode = getSelectedNode();
|
||||
final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
|
||||
@ -820,44 +822,40 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
Children dirChilds = em.getRootContext().getChildren();
|
||||
|
||||
Node results = dirChilds.findChild(ResultsNode.NAME);
|
||||
|
||||
if (results == null) {
|
||||
logger.log(Level.SEVERE, "Cannot find Results filter node, won't refresh the bb tree"); //NON-NLS
|
||||
return;
|
||||
}
|
||||
|
||||
OriginalNode original = results.getLookup().lookup(OriginalNode.class);
|
||||
ResultsNode resultsNode = (ResultsNode) original.getNode();
|
||||
RootContentChildren resultsNodeChilds = (RootContentChildren) resultsNode.getChildren();
|
||||
resultsNodeChilds.refreshKeys(types);
|
||||
|
||||
|
||||
final TreeView tree = getTree();
|
||||
|
||||
tree.expandNode(results);
|
||||
// @@@ tree.expandNode(results);
|
||||
|
||||
Children resultsChilds = results.getChildren();
|
||||
|
||||
if (resultsChilds == null) //intermediate state check
|
||||
{
|
||||
if (resultsChilds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node childNode = resultsChilds.findChild(KeywordHits.NAME);
|
||||
if (childNode == null) //intermediate state check
|
||||
{
|
||||
if (childNode == null) {
|
||||
return;
|
||||
}
|
||||
tree.expandNode(childNode);
|
||||
// @@@tree.expandNode(childNode);
|
||||
|
||||
childNode = resultsChilds.findChild(ExtractedContentNode.NAME);
|
||||
if (childNode == null) //intermediate state check
|
||||
{
|
||||
childNode = resultsChilds.findChild(ExtractedContent.NAME);
|
||||
if (childNode == null) {
|
||||
return;
|
||||
}
|
||||
tree.expandNode(childNode);
|
||||
|
||||
//restores selection if it was under the Results node
|
||||
setSelectedNode(selectedPath, ResultsNode.NAME);
|
||||
|
||||
//@@@ setSelectedNode(selectedPath, ResultsNode.NAME);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -983,7 +981,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
logger.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
||||
}
|
||||
} else {
|
||||
Node extractedContent = resultsChilds.findChild(ExtractedContentNode.NAME);
|
||||
Node extractedContent = resultsChilds.findChild(ExtractedContent.NAME);
|
||||
Children extractedChilds = extractedContent.getChildren();
|
||||
treeNode = extractedChilds.findChild(type.getLabel());
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#Updated by build script
|
||||
#Tue, 22 Apr 2014 16:06:14 -0400
|
||||
#Sat, 03 May 2014 22:45:39 -0400
|
||||
LBL_splash_window_title=Starting Autopsy
|
||||
SPLASH_HEIGHT=288
|
||||
SPLASH_WIDTH=538
|
||||
|
@ -1,5 +1,5 @@
|
||||
#Updated by build script
|
||||
#Tue, 22 Apr 2014 16:06:14 -0400
|
||||
#Sat, 03 May 2014 22:45:39 -0400
|
||||
|
||||
CTL_MainWindow_Title=Autopsy 3.1.0_Beta
|
||||
CTL_MainWindow_Title_No_Project=Autopsy 3.1.0_Beta
|
||||
|
Loading…
x
Reference in New Issue
Block a user