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() {
|
protected void refreshDirectoryTree() {
|
||||||
// The way the "directory tree" currently works, a new tags sub-tree
|
// 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
|
// 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)
|
// which calls RootContentChildren.refreshKeys(BlackboardArtifact.ARTIFACT_TYPE... types)
|
||||||
// for the RootContentChildren object that is the child factory for the
|
// 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
|
// ResultsNode that is the root of the tags sub-tree. There is a switch
|
||||||
// statement in RootContentChildren.refreshKeys() that maps both
|
// statement in RootContentChildren.refreshKeys() that maps both
|
||||||
// BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE and BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT
|
// BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE and BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT
|
||||||
// to making a call to refreshKey(TagsNodeKey).
|
// 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.Children.Keys;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.DerivedFile;
|
import org.sleuthkit.datamodel.DerivedFile;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
@ -119,8 +118,8 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
static class CreateAutopsyNodeVisitor extends AutopsyItemVisitor.Default<AbstractNode> {
|
static class CreateAutopsyNodeVisitor extends AutopsyItemVisitor.Default<AbstractNode> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ExtractedContentNode visit(ExtractedContent ec) {
|
public ExtractedContent.RootNode visit(ExtractedContent ec) {
|
||||||
return new ExtractedContentNode(ec.getSleuthkitCase());
|
return ec.new RootNode(ec.getSleuthkitCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -145,22 +144,22 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(KeywordHits kh) {
|
public AbstractNode visit(KeywordHits kh) {
|
||||||
return kh.new KeywordHitsRootNode();
|
return kh.new RootNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(HashsetHits hh) {
|
public AbstractNode visit(HashsetHits hh) {
|
||||||
return hh.new HashsetHitsRootNode();
|
return hh.new RootNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(InterestingHits ih) {
|
public AbstractNode visit(InterestingHits ih) {
|
||||||
return ih.new InterestingHitsRootNode();
|
return ih.new RootNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(EmailExtracted ee) {
|
public AbstractNode visit(EmailExtracted ee) {
|
||||||
return ee.new EmailExtractedRootNode();
|
return ee.new RootNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author dfickling
|
|
||||||
*/
|
*/
|
||||||
interface AutopsyItemVisitor<T> {
|
interface AutopsyItemVisitor<T> {
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node wrapping a blackboard artifact object. This represents a single artifact.
|
* Node wrapping a blackboard artifact object. This is generated from several
|
||||||
* Its parent is typically an ArtifactTypeNode.
|
* places in the tree.
|
||||||
*/
|
*/
|
||||||
public class BlackboardArtifactNode extends DisplayableItemNode {
|
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.DeletedContentsChildren.DeletedContentNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
|
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.FileSizeRootChildren.FileSizeNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
|
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;
|
import org.sleuthkit.autopsy.directorytree.BlackboardArtifactTagTypeNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,9 +39,9 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
|
|
||||||
T visit(BlackboardArtifactNode ban);
|
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);
|
T visit(FileTypeNode fsfn);
|
||||||
|
|
||||||
@ -69,27 +59,27 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
|
|
||||||
T visit(RecentFilesFilterNode rffn);
|
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(TagsNode node);
|
||||||
|
|
||||||
T visit(InterestingHitsRootNode ihrn);
|
T visit(InterestingHits.RootNode ihrn);
|
||||||
|
|
||||||
T visit(InterestingHitsSetNode ihsn);
|
T visit(InterestingHits.SetNameNode ihsn);
|
||||||
|
|
||||||
T visit(TagNameNode node);
|
T visit(TagNameNode node);
|
||||||
|
|
||||||
@ -155,12 +145,12 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(ArtifactTypeNode atn) {
|
public T visit(ExtractedContent.TypeNode atn) {
|
||||||
return defaultVisit(atn);
|
return defaultVisit(atn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(ExtractedContentNode ecn) {
|
public T visit(ExtractedContent.RootNode ecn) {
|
||||||
return defaultVisit(ecn);
|
return defaultVisit(ecn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,17 +195,17 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(KeywordHitsRootNode khrn) {
|
public T visit(KeywordHits.RootNode khrn) {
|
||||||
return defaultVisit(khrn);
|
return defaultVisit(khrn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(KeywordHitsListNode khsn) {
|
public T visit(KeywordHits.ListNode khsn) {
|
||||||
return defaultVisit(khsn);
|
return defaultVisit(khsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(KeywordHitsKeywordNode khmln) {
|
public T visit(KeywordHits.TermNode khmln) {
|
||||||
return defaultVisit(khmln);
|
return defaultVisit(khmln);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,37 +225,37 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(HashsetHitsRootNode hhrn) {
|
public T visit(HashsetHits.RootNode hhrn) {
|
||||||
return defaultVisit(hhrn);
|
return defaultVisit(hhrn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(HashsetHitsSetNode hhsn) {
|
public T visit(HashsetHits.HashsetNameNode hhsn) {
|
||||||
return defaultVisit(hhsn);
|
return defaultVisit(hhsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(InterestingHitsRootNode ihrn) {
|
public T visit(InterestingHits.RootNode ihrn) {
|
||||||
return defaultVisit(ihrn);
|
return defaultVisit(ihrn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(InterestingHitsSetNode ihsn) {
|
public T visit(InterestingHits.SetNameNode ihsn) {
|
||||||
return defaultVisit(ihsn);
|
return defaultVisit(ihsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(EmailExtractedRootNode eern) {
|
public T visit(EmailExtracted.RootNode eern) {
|
||||||
return defaultVisit(eern);
|
return defaultVisit(eern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(EmailExtractedAccountNode eean) {
|
public T visit(EmailExtracted.AccountNode eean) {
|
||||||
return defaultVisit(eean);
|
return defaultVisit(eean);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(EmailExtractedFolderNode eefn) {
|
public T visit(EmailExtracted.FolderNode eefn) {
|
||||||
return defaultVisit(eefn);
|
return defaultVisit(eefn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -25,6 +27,9 @@ import java.util.HashMap;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -34,11 +39,14 @@ import org.openide.nodes.Children;
|
|||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.lookup.Lookups;
|
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.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for TSK_EMAIL_MSG nodes and displaying emails in the directory tree
|
* 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
|
* 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_FOLDER = NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.mailFolder.text");
|
||||||
private static final String MAIL_PATH_SEPARATOR = "/";
|
private static final String MAIL_PATH_SEPARATOR = "/";
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
private Map<String, Map<String, List<Long>>> accounts;
|
private EmailResults emailResults;
|
||||||
|
|
||||||
|
|
||||||
public EmailExtracted(SleuthkitCase skCase) {
|
public EmailExtracted(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
accounts = new LinkedHashMap<>();
|
emailResults = new EmailResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
private final class EmailResults extends Observable {
|
||||||
private void initArtifacts() {
|
private Map<String, Map<String, List<Long>>> accounts = new LinkedHashMap<>();
|
||||||
accounts.clear();
|
|
||||||
try {
|
EmailResults() {
|
||||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID();
|
update();
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
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, List<Long>> folders = accounts.get(account);
|
||||||
Map<String, String> parsed = new HashMap<>();
|
if (folders == null) {
|
||||||
String[] split = path.split(MAIL_PATH_SEPARATOR);
|
folders = new LinkedHashMap<>();
|
||||||
if (split.length < 4) {
|
accounts.put(account, folders);
|
||||||
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"));
|
List<Long> messages = folders.get(folder);
|
||||||
parsed.put(MAIL_FOLDER, NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.defaultFolder.text"));
|
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;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
parsed.put(MAIL_ACCOUNT, split[2]);
|
|
||||||
parsed.put(MAIL_FOLDER, split[3]);
|
|
||||||
return parsed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -122,94 +151,94 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
|||||||
/**
|
/**
|
||||||
* Mail root node showing all emails
|
* Mail root node showing all emails
|
||||||
*/
|
*/
|
||||||
public class EmailExtractedRootNodeFlat extends DisplayableItemNode {
|
// public class FlatRootNode extends DisplayableItemNode {
|
||||||
|
//
|
||||||
public EmailExtractedRootNodeFlat() {
|
// public FlatRootNode() {
|
||||||
super(Children.create(new EmailExtractedRootChildrenFlat(), true), Lookups.singleton(DISPLAY_NAME));
|
// super(Children.create(new FlatRootFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||||
super.setName(LABEL_NAME);
|
// super.setName(LABEL_NAME);
|
||||||
super.setDisplayName(DISPLAY_NAME);
|
// super.setDisplayName(DISPLAY_NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); //NON-NLS
|
// this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); //NON-NLS
|
||||||
initArtifacts();
|
// initArtifacts();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public boolean isLeafTypeNode() {
|
// public boolean isLeafTypeNode() {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
// public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
//return v.visit(this);
|
// //return v.visit(this);
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected Sheet createSheet() {
|
// protected Sheet createSheet() {
|
||||||
Sheet s = super.createSheet();
|
// Sheet s = super.createSheet();
|
||||||
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
// Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
||||||
if (ss == null) {
|
// if (ss == null) {
|
||||||
ss = Sheet.createPropertiesSet();
|
// ss = Sheet.createPropertiesSet();
|
||||||
s.put(ss);
|
// s.put(ss);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.name"),
|
// 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.displayName"),
|
||||||
NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.desc"),
|
// NbBundle.getMessage(this.getClass(), "EmailExtracted.createSheet.name.desc"),
|
||||||
getName()));
|
// getName()));
|
||||||
return s;
|
// return s;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Mail root child node showing flattened emails
|
// * Mail root child node showing flattened emails
|
||||||
*/
|
// */
|
||||||
private class EmailExtractedRootChildrenFlat extends ChildFactory<BlackboardArtifact> {
|
// private class FlatRootFactory extends ChildFactory<BlackboardArtifact> {
|
||||||
|
//
|
||||||
private EmailExtractedRootChildrenFlat() {
|
// private FlatRootFactory() {
|
||||||
super();
|
// super();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
// protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||||
//flatten all emails
|
// //flatten all emails
|
||||||
List<BlackboardArtifact> tempList = new ArrayList<>();
|
// List<BlackboardArtifact> tempList = new ArrayList<>();
|
||||||
for (String account : accounts.keySet()) {
|
// for (String account : accounts.keySet()) {
|
||||||
Map<String, List<Long>> folders = accounts.get(account);
|
// Map<String, List<Long>> folders = accounts.get(account);
|
||||||
for (String folder : folders.keySet()) {
|
// for (String folder : folders.keySet()) {
|
||||||
List<Long> messages = folders.get(folder);
|
// List<Long> messages = folders.get(folder);
|
||||||
for (long l : messages) {
|
// for (long l : messages) {
|
||||||
try {
|
// try {
|
||||||
//TODO: bulk artifact gettings
|
// //TODO: bulk artifact gettings
|
||||||
tempList.add(skCase.getBlackboardArtifact(l));
|
// tempList.add(skCase.getBlackboardArtifact(l));
|
||||||
} catch (TskException ex) {
|
// } catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, "Error creating mail messages nodes", ex); //NON-NLS
|
// logger.log(Level.WARNING, "Error creating mail messages nodes", ex); //NON-NLS
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
list.addAll(tempList);
|
// list.addAll(tempList);
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
// protected Node createNodeForKey(BlackboardArtifact artifact) {
|
||||||
return new BlackboardArtifactNode(artifact);
|
// return new BlackboardArtifactNode(artifact);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mail root node grouping all mail accounts, supports account-> folder
|
* Mail root node grouping all mail accounts, supports account-> folder
|
||||||
* structure
|
* structure
|
||||||
*/
|
*/
|
||||||
public class EmailExtractedRootNode extends DisplayableItemNode {
|
public class RootNode extends DisplayableItemNode {
|
||||||
|
|
||||||
public EmailExtractedRootNode() {
|
public RootNode() {
|
||||||
super(Children.create(new EmailExtractedRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
|
super(Children.create(new AccountFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||||
super.setName(LABEL_NAME);
|
super.setName(LABEL_NAME);
|
||||||
super.setDisplayName(DISPLAY_NAME);
|
super.setDisplayName(DISPLAY_NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); //NON-NLS
|
||||||
initArtifacts();
|
emailResults.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -220,7 +249,6 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
//return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -244,30 +272,74 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
|||||||
/**
|
/**
|
||||||
* Mail root child node creating each account node
|
* 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
|
@Override
|
||||||
protected boolean createKeys(List<String> list) {
|
protected boolean createKeys(List<String> list) {
|
||||||
list.addAll(accounts.keySet());
|
list.addAll(emailResults.getAccounts());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(String key) {
|
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
|
* Account node representation
|
||||||
*/
|
*/
|
||||||
public class EmailExtractedAccountNode extends DisplayableItemNode {
|
public class AccountNode extends DisplayableItemNode implements Observer {
|
||||||
|
private String accountName;
|
||||||
public EmailExtractedAccountNode(String name, Map<String, List<Long>> children) {
|
|
||||||
super(Children.create(new EmailExtractedAccountChildrenNode(children), true), Lookups.singleton(name));
|
public AccountNode(String accountName) {
|
||||||
super.setName(name);
|
super(Children.create(new FolderFactory(accountName), true), Lookups.singleton(accountName));
|
||||||
super.setDisplayName(name + " (" + children.size() + ")");
|
super.setName(accountName);
|
||||||
|
this.accountName = accountName;
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/account-icon-16.png"); //NON-NLS
|
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
|
@Override
|
||||||
@ -296,43 +368,61 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
|||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
updateDisplayName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account node child creating sub nodes for every folder
|
* 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();
|
super();
|
||||||
this.folders = folders;
|
this.accountName = accountName;
|
||||||
|
emailResults.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<String> list) {
|
protected boolean createKeys(List<String> list) {
|
||||||
list.addAll(folders.keySet());
|
list.addAll(emailResults.getFolders(accountName));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(String key) {
|
protected Node createNodeForKey(String folderName) {
|
||||||
return new EmailExtractedFolderNode(key, folders.get(key));
|
return new FolderNode(accountName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
refresh(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node representing mail folder
|
* Node representing mail folder
|
||||||
*/
|
*/
|
||||||
public class EmailExtractedFolderNode extends DisplayableItemNode {
|
public class FolderNode extends DisplayableItemNode implements Observer {
|
||||||
|
private String accountName;
|
||||||
public EmailExtractedFolderNode(String name, List<Long> children) {
|
private String folderName;
|
||||||
super(Children.create(new EmailExtractedFolderChildrenNode(children), true), Lookups.singleton(name));
|
|
||||||
super.setName(name);
|
public FolderNode(String accountName, String folderName) {
|
||||||
super.setDisplayName(name + " (" + children.size() + ")");
|
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
|
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
|
@Override
|
||||||
@ -361,38 +451,48 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
|||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
updateDisplayName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node representing mail folder content (mail messages)
|
* 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();
|
super();
|
||||||
this.messages = messages;
|
this.accountName = accountName;
|
||||||
|
this.folderName = folderName;
|
||||||
|
emailResults.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
protected boolean createKeys(List<Long> list) {
|
||||||
List<BlackboardArtifact> tempList = new ArrayList<>();
|
list.addAll(emailResults.getArtifactIds(accountName, folderName));
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
protected Node createNodeForKey(Long artifactId) {
|
||||||
return new BlackboardArtifactNode(artifact);
|
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
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011-2014 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,17 +18,59 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
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.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent of the "extracted content" artifacts to be displayed in the tree. Other
|
* Parent of the "extracted content" artifacts to be displayed in the tree.
|
||||||
* artifacts are displayed under other more specific parents.
|
* 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;
|
this.skCase = skCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +79,310 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SleuthkitCase getSleuthkitCase(){
|
public SleuthkitCase getSleuthkitCase() {
|
||||||
return skCase;
|
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;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
@ -34,13 +38,16 @@ import org.openide.nodes.Children;
|
|||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.lookup.Lookups;
|
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.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.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskException;
|
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 {
|
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 String DISPLAY_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName();
|
||||||
private static final Logger logger = Logger.getLogger(HashsetHits.class.getName());
|
private static final Logger logger = Logger.getLogger(HashsetHits.class.getName());
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
private Map<String, Set<Long>> hashSetHitsMap;
|
private HashsetResults hashsetResults;
|
||||||
|
|
||||||
public HashsetHits(SleuthkitCase skCase) {
|
public HashsetHits(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
hashSetHitsMap = new LinkedHashMap<>();
|
hashsetResults = new HashsetResults();
|
||||||
}
|
|
||||||
|
|
||||||
@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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
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() {
|
public RootNode() {
|
||||||
super(Children.create(new HashsetHitsRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
|
super(Children.create(new HashsetNameFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||||
super.setName(HASHSET_HITS);
|
super.setName(HASHSET_HITS);
|
||||||
super.setDisplayName(DISPLAY_NAME);
|
super.setDisplayName(DISPLAY_NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); //NON-NLS
|
||||||
initArtifacts();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
protected boolean createKeys(List<String> list) {
|
protected void addNotify() {
|
||||||
list.addAll(hashSetHitsMap.keySet());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(String key) {
|
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 {
|
/**
|
||||||
|
* Node for a hash set name
|
||||||
public HashsetHitsSetNode(String name, Set<Long> children) {
|
*/
|
||||||
super(Children.create(new HashsetHitsSetChildren(children), true), Lookups.singleton(name));
|
public class HashsetNameNode extends DisplayableItemNode implements Observer {
|
||||||
super.setName(name);
|
private String hashSetName;
|
||||||
super.setDisplayName(name + " (" + children.size() + ")");
|
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
|
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
|
@Override
|
||||||
@ -186,33 +266,54 @@ public class HashsetHits implements AutopsyVisitableItem {
|
|||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
updateName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HashsetHitsSetChildren extends ChildFactory<BlackboardArtifact> {
|
/**
|
||||||
|
* Creates the nodes for the hits in a given set.
|
||||||
private Set<Long> children;
|
*/
|
||||||
|
private class HitFactory extends ChildFactory.Detachable<Long> implements Observer {
|
||||||
private HashsetHitsSetChildren(Set<Long> children) {
|
private String hashsetName;
|
||||||
|
|
||||||
|
private HitFactory(String hashsetName) {
|
||||||
super();
|
super();
|
||||||
this.children = children;
|
this.hashsetName = hashsetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addNotify() {
|
||||||
|
hashsetResults.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
protected void removeNotify() {
|
||||||
for (long l : children) {
|
hashsetResults.deleteObserver(this);
|
||||||
try {
|
}
|
||||||
//TODO: bulk artifact gettings
|
|
||||||
list.add(skCase.getBlackboardArtifact(l));
|
@Override
|
||||||
} catch (TskException ex) {
|
protected boolean createKeys(List<Long> list) {
|
||||||
logger.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS
|
list.addAll(hashsetResults.getArtifactIds(hashsetName));
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
protected Node createNodeForKey(Long id) {
|
||||||
return new BlackboardArtifactNode(artifact);
|
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
|
* Node for the interesting items
|
||||||
*/
|
*/
|
||||||
public class InterestingHitsRootNode extends DisplayableItemNode {
|
public class RootNode extends DisplayableItemNode {
|
||||||
|
|
||||||
public InterestingHitsRootNode() {
|
public RootNode() {
|
||||||
super(Children.create(new InterestingHitsRootChildren(), true), Lookups.singleton(DISPLAY_NAME));
|
super(Children.create(new SetNameFactory(), true), Lookups.singleton(DISPLAY_NAME));
|
||||||
super.setName(INTERESTING_ITEMS);
|
super.setName(INTERESTING_ITEMS);
|
||||||
super.setDisplayName(DISPLAY_NAME);
|
super.setDisplayName(DISPLAY_NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
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
|
@Override
|
||||||
protected boolean createKeys(List<String> list) {
|
protected boolean createKeys(List<String> list) {
|
||||||
@ -154,14 +154,14 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(String key) {
|
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) {
|
public SetNameNode(String name, Set<Long> children) {
|
||||||
super(Children.create(new InterestingHitsSetChildren(children), true), Lookups.singleton(name));
|
super(Children.create(new HitFactory(children), true), Lookups.singleton(name));
|
||||||
super.setName(name);
|
super.setName(name);
|
||||||
super.setDisplayName(name + " (" + children.size() + ")");
|
super.setDisplayName(name + " (" + children.size() + ")");
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
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 Set<Long> children;
|
||||||
|
|
||||||
private InterestingHitsSetChildren(Set<Long> children) {
|
private HitFactory(Set<Long> children) {
|
||||||
super();
|
super();
|
||||||
this.children = children;
|
this.children = children;
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -34,6 +37,8 @@ import org.openide.nodes.Children;
|
|||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.lookup.Lookups;
|
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.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
@ -54,101 +59,123 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
.getMessage(KeywordHits.class, "KeywordHits.simpleLiteralSearch.text");
|
.getMessage(KeywordHits.class, "KeywordHits.simpleLiteralSearch.text");
|
||||||
public static final String SIMPLE_REGEX_SEARCH = NbBundle
|
public static final String SIMPLE_REGEX_SEARCH = NbBundle
|
||||||
.getMessage(KeywordHits.class, "KeywordHits.singleRegexSearch.text");
|
.getMessage(KeywordHits.class, "KeywordHits.singleRegexSearch.text");
|
||||||
// Map from String (list name) to Map from string (keyword) to set<long> (artifact ids)
|
private KeywordResults keywordResults;
|
||||||
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;
|
|
||||||
|
|
||||||
public KeywordHits(SleuthkitCase skCase) {
|
public KeywordHits(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
artifacts = new LinkedHashMap<>();
|
keywordResults = new KeywordResults();
|
||||||
listsMap = new LinkedHashMap<>();
|
|
||||||
literalMap = new LinkedHashMap<>();
|
|
||||||
regexMap = new LinkedHashMap<>();
|
|
||||||
topLevelMap = new LinkedHashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initMaps() {
|
private final class KeywordResults extends Observable {
|
||||||
topLevelMap.clear();
|
// Map from listName/Type to Map of keyword to set of artifact Ids
|
||||||
topLevelMap.put(SIMPLE_LITERAL_SEARCH, literalMap);
|
private Map<String, Map<String, Set<Long>>> topLevelMap;
|
||||||
topLevelMap.put(SIMPLE_REGEX_SEARCH, regexMap);
|
|
||||||
listsMap.clear();
|
KeywordResults() {
|
||||||
regexMap.clear();
|
topLevelMap = new LinkedHashMap<>();
|
||||||
literalMap.clear();
|
update();
|
||||||
for (Map.Entry<Long, Map<Long, String>> art : artifacts.entrySet()) {
|
}
|
||||||
long id = art.getKey();
|
|
||||||
Map<Long, String> attributes = art.getValue();
|
Set<String> getListNames() {
|
||||||
// I think we can use attributes.remove(...) here?
|
return topLevelMap.keySet();
|
||||||
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()));
|
Set<String> getKeywords(String listName) {
|
||||||
if (listName != null) {
|
return topLevelMap.get(listName).keySet();
|
||||||
if (!listsMap.containsKey(listName)) {
|
}
|
||||||
listsMap.put(listName, new LinkedHashMap<String, Set<Long>>());
|
|
||||||
}
|
Set<Long> getArtifactIds(String listName, String keyword) {
|
||||||
if (!listsMap.get(listName).containsKey(word)) {
|
return topLevelMap.get(listName).get(keyword);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
// populate maps based on artifactIds
|
||||||
private void initArtifacts() {
|
void populateMaps(Map<Long, Map<Long, String>> artifactIds) {
|
||||||
artifacts.clear();
|
topLevelMap.clear();
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
Map<String, Map<String, Set<Long>>> listsMap = new LinkedHashMap<>();
|
||||||
int setId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
// Map from String (literal keyword) to set<long> (artifact ids)
|
||||||
int wordId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID();
|
Map<String, Set<Long>> literalMap = new LinkedHashMap<>();
|
||||||
int regexId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID();
|
// Map from String (regex keyword) to set<long> (artifact ids);
|
||||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID();
|
Map<String, Set<Long>> regexMap = new LinkedHashMap<>();
|
||||||
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
|
// top-level nodes
|
||||||
+ "blackboard_artifacts.artifact_type_id=" + artId //NON-NLS
|
topLevelMap.put(SIMPLE_LITERAL_SEARCH, literalMap);
|
||||||
+ ") AND (attribute_type_id=" + setId + " OR " //NON-NLS
|
topLevelMap.put(SIMPLE_REGEX_SEARCH, regexMap);
|
||||||
+ "attribute_type_id=" + wordId + " OR " //NON-NLS
|
|
||||||
+ "attribute_type_id=" + regexId + ")"; //NON-NLS
|
for (Map.Entry<Long, Map<Long, String>> art : artifactIds.entrySet()) {
|
||||||
rs = skCase.runQuery(query);
|
long id = art.getKey();
|
||||||
while (rs.next()) {
|
Map<Long, String> attributes = art.getValue();
|
||||||
String value = rs.getString("value_text"); //NON-NLS
|
|
||||||
long artifactId = rs.getLong("artifact_id"); //NON-NLS
|
// I think we can use attributes.remove(...) here?
|
||||||
long typeId = rs.getLong("attribute_type_id"); //NON-NLS
|
String listName = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()));
|
||||||
if (!artifacts.containsKey(artifactId)) {
|
String word = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()));
|
||||||
artifacts.put(artifactId, new LinkedHashMap<Long, String>());
|
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("")) {
|
topLevelMap.putAll(listsMap);
|
||||||
artifacts.get(artifactId).put(typeId, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SQLException ex) {
|
setChanged();
|
||||||
logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
|
notifyObservers();
|
||||||
} finally {
|
}
|
||||||
if (rs != null) {
|
|
||||||
try {
|
public void update() {
|
||||||
skCase.closeRunQuery(rs);
|
Map<Long, Map<Long, String>> artifactIds = new LinkedHashMap<>();
|
||||||
} catch (SQLException ex) {
|
|
||||||
logger.log(Level.WARNING, "Error closing result set after getting keyword hits", ex); //NON-NLS
|
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);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KeywordHitsRootNode extends DisplayableItemNode {
|
// Created by CreateAutopsyNodeVisitor
|
||||||
|
public class RootNode extends DisplayableItemNode {
|
||||||
|
|
||||||
public KeywordHitsRootNode() {
|
public RootNode() {
|
||||||
super(Children.create(new KeywordHitsRootChildren(), true), Lookups.singleton(KEYWORD_HITS));
|
super(Children.create(new ListFactory(), true), Lookups.singleton(KEYWORD_HITS));
|
||||||
super.setName(NAME);
|
super.setName(NAME);
|
||||||
super.setDisplayName(KEYWORD_HITS);
|
super.setDisplayName(KEYWORD_HITS);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
||||||
initArtifacts();
|
|
||||||
initMaps();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
protected boolean createKeys(List<String> list) {
|
protected boolean createKeys(List<String> list) {
|
||||||
list.addAll(topLevelMap.keySet());
|
list.addAll(keywordResults.getListNames());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(String key) {
|
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;
|
public ListNode(String listName) {
|
||||||
private Map<String, Set<Long>> children;
|
super(Children.create(new TermFactory(listName), true), Lookups.singleton(listName));
|
||||||
|
super.setName(listName);
|
||||||
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 + ")");
|
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
||||||
this.name = name;
|
this.listName = listName;
|
||||||
this.children = children;
|
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
|
@Override
|
||||||
@ -240,13 +303,13 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.name"),
|
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.displayName"),
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.desc"),
|
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.desc"),
|
||||||
name));
|
listName));
|
||||||
|
|
||||||
|
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.name"),
|
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.displayName"),
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.desc"),
|
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.desc"),
|
||||||
children.size()));
|
keywordResults.getKeywords(listName).size()));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -260,39 +323,71 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
updateDisplayName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class KeywordHitsListChildren extends ChildFactory<String> {
|
private class TermFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||||
|
private String setName;
|
||||||
private Map<String, Set<Long>> children;
|
|
||||||
|
private TermFactory(String setName) {
|
||||||
private KeywordHitsListChildren(Map<String, Set<Long>> children) {
|
|
||||||
super();
|
super();
|
||||||
this.children = children;
|
this.setName = setName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addNotify() {
|
||||||
|
keywordResults.addObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeNotify() {
|
||||||
|
keywordResults.deleteObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<String> list) {
|
protected boolean createKeys(List<String> list) {
|
||||||
list.addAll(children.keySet());
|
list.addAll(keywordResults.getKeywords(setName));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(String key) {
|
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) {
|
public TermNode(String setName, String keyword) {
|
||||||
super(Children.create(new KeywordHitsKeywordChildren(children), true), Lookups.singleton(name));
|
super(Children.create(new HitsFactory (setName, keyword), true), Lookups.singleton(keyword));
|
||||||
super.setName(name);
|
super.setName(keyword);
|
||||||
super.setDisplayName(name + " (" + children.size() + ")");
|
this.setName = setName;
|
||||||
|
this.keyword = keyword;
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
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
|
@Override
|
||||||
@ -322,70 +417,83 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.name"),
|
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.displayName"),
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.desc"),
|
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.desc"),
|
||||||
children.size()));
|
keywordResults.getArtifactIds(setName, keyword).size()));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class KeywordHitsKeywordChildren extends ChildFactory<BlackboardArtifact> {
|
public class HitsFactory extends ChildFactory.Detachable<Long> implements Observer {
|
||||||
|
private String keyword;
|
||||||
private Set<Long> children;
|
private String setName;
|
||||||
|
|
||||||
private KeywordHitsKeywordChildren(Set<Long> children) {
|
public HitsFactory(String setName, String keyword) {
|
||||||
super();
|
super();
|
||||||
this.children = children;
|
this.setName = setName;
|
||||||
|
this.keyword = keyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addNotify() {
|
||||||
|
keywordResults.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
protected void removeNotify() {
|
||||||
List<BlackboardArtifact> tempList = new ArrayList<>();
|
keywordResults.deleteObserver(this);
|
||||||
for (long l : children) {
|
}
|
||||||
try {
|
|
||||||
//TODO: bulk artifact gettings
|
@Override
|
||||||
tempList.add(skCase.getBlackboardArtifact(l));
|
protected boolean createKeys(List<Long> list) {
|
||||||
} catch (TskException ex) {
|
list.addAll(keywordResults.getArtifactIds(setName, keyword));
|
||||||
logger.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list.addAll(tempList);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(BlackboardArtifact artifact) {
|
protected Node createNodeForKey(Long artifactId) {
|
||||||
BlackboardArtifactNode n = new BlackboardArtifactNode(artifact);
|
|
||||||
AbstractFile file;
|
|
||||||
try {
|
try {
|
||||||
file = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
|
BlackboardArtifact art = skCase.getBlackboardArtifact(artifactId);
|
||||||
} catch (TskCoreException ex) {
|
BlackboardArtifactNode n = new BlackboardArtifactNode(art);
|
||||||
logger.log(Level.SEVERE, "TskCoreException while constructing BlackboardArtifact Node from KeywordHitsKeywordChildren"); //NON-NLS
|
AbstractFile file;
|
||||||
return n;
|
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<>(
|
@Override
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.modTime.name"),
|
public void update(Observable o, Object arg) {
|
||||||
NbBundle.getMessage(this.getClass(),
|
refresh(true);
|
||||||
"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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,8 @@ public class RootContentChildren extends AbstractContentChildren<Object> {
|
|||||||
//TODO this will be removed, Children should be listening for interesting
|
//TODO this will be removed, Children should be listening for interesting
|
||||||
//events from datamodel and calling refresh / refreshKey() themselves
|
//events from datamodel and calling refresh / refreshKey() themselves
|
||||||
public void refreshKeys(BlackboardArtifact.ARTIFACT_TYPE... types) {
|
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 (Object o : contentKeys) {
|
||||||
for (BlackboardArtifact.ARTIFACT_TYPE type : types) {
|
for (BlackboardArtifact.ARTIFACT_TYPE type : types) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -91,8 +93,10 @@ public class RootContentChildren extends AbstractContentChildren<Object> {
|
|||||||
this.refreshKey(o);
|
this.refreshKey(o);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (o instanceof ExtractedContent)
|
if (o instanceof ExtractedContent) {
|
||||||
|
|
||||||
this.refreshKey(o);
|
this.refreshKey(o);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import org.openide.nodes.Sheet;
|
|||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.directorytree.BlackboardArtifactTagTypeNode;
|
import org.sleuthkit.autopsy.directorytree.BlackboardArtifactTagTypeNode;
|
||||||
import org.sleuthkit.datamodel.TagName;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
@ -52,22 +53,26 @@ public class TagNameNode extends DisplayableItemNode {
|
|||||||
NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName())));
|
NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName())));
|
||||||
this.tagName = tagName;
|
this.tagName = tagName;
|
||||||
|
|
||||||
long tagsCount = 0;
|
setName(tagName.getDisplayName());
|
||||||
try {
|
updateDisplayName();
|
||||||
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 + ")");
|
|
||||||
if (tagName.getDisplayName().equals(NbBundle.getMessage(this.getClass(), "TagNameNode.bookmark.text"))) {
|
if (tagName.getDisplayName().equals(NbBundle.getMessage(this.getClass(), "TagNameNode.bookmark.text"))) {
|
||||||
setIconBaseWithExtension(BOOKMARK_TAG_ICON_PATH);
|
setIconBaseWithExtension(BOOKMARK_TAG_ICON_PATH);
|
||||||
} else {
|
} else {
|
||||||
setIconBaseWithExtension(ICON_PATH);
|
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
|
@Override
|
||||||
protected Sheet createSheet() {
|
protected Sheet createSheet() {
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.nodes.ChildFactory;
|
import org.openide.nodes.ChildFactory;
|
||||||
@ -28,6 +30,9 @@ import org.openide.util.NbBundle;
|
|||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
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.TagName;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
@ -76,8 +81,36 @@ class TagsNode extends DisplayableItemNode {
|
|||||||
return propertySheet;
|
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
|
@Override
|
||||||
protected boolean createKeys(List<TagName> keys) {
|
protected boolean createKeys(List<TagName> keys) {
|
||||||
try {
|
try {
|
||||||
|
@ -33,14 +33,12 @@ import javax.swing.AbstractAction;
|
|||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.ChildFactory;
|
|
||||||
import org.openide.nodes.FilterNode;
|
import org.openide.nodes.FilterNode;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
|
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.ArtifactTypeNode;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentTagTypeNode;
|
import org.sleuthkit.autopsy.datamodel.ContentTagTypeNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
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.DeletedContent.DeletedContentsNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode;
|
import org.sleuthkit.autopsy.datamodel.EmailExtracted.AccountNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode;
|
import org.sleuthkit.autopsy.datamodel.EmailExtracted.FolderNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode;
|
import org.sleuthkit.autopsy.datamodel.EmailExtracted;
|
||||||
import org.sleuthkit.autopsy.datamodel.ExtractedContentNode;
|
import org.sleuthkit.autopsy.datamodel.ExtractedContent.TypeNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileTypeNode;
|
import org.sleuthkit.autopsy.datamodel.FileTypeNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
|
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
|
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode;
|
import org.sleuthkit.autopsy.datamodel.HashsetHits;
|
||||||
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode;
|
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetNameNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.InterestingHits.InterestingHitsRootNode;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.InterestingHits.InterestingHitsSetNode;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.ImageNode;
|
import org.sleuthkit.autopsy.datamodel.ImageNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode;
|
import org.sleuthkit.autopsy.datamodel.InterestingHits;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode;
|
import org.sleuthkit.autopsy.datamodel.KeywordHits.TermNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode;
|
import org.sleuthkit.autopsy.datamodel.KeywordHits.ListNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode;
|
import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.RecentFilesNode;
|
import org.sleuthkit.autopsy.datamodel.RecentFilesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileTypesNode;
|
import org.sleuthkit.autopsy.datamodel.FileTypesNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||||
import org.sleuthkit.autopsy.datamodel.TagNameNode;
|
import org.sleuthkit.autopsy.datamodel.TagNameNode;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -367,47 +365,47 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(ExtractedContentNode ecn) {
|
public AbstractAction visit(ExtractedContent.RootNode ecn) {
|
||||||
return openChild(ecn);
|
return openChild(ecn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(KeywordHitsRootNode khrn) {
|
public AbstractAction visit(KeywordHits.RootNode khrn) {
|
||||||
return openChild(khrn);
|
return openChild(khrn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(HashsetHitsRootNode hhrn) {
|
public AbstractAction visit(HashsetHits.RootNode hhrn) {
|
||||||
return openChild(hhrn);
|
return openChild(hhrn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(HashsetHitsSetNode hhsn) {
|
public AbstractAction visit(HashsetNameNode hhsn) {
|
||||||
return openChild(hhsn);
|
return openChild(hhsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(InterestingHitsRootNode iarn) {
|
public AbstractAction visit(InterestingHits.RootNode iarn) {
|
||||||
return openChild(iarn);
|
return openChild(iarn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(InterestingHitsSetNode iasn) {
|
public AbstractAction visit(InterestingHits.SetNameNode iasn) {
|
||||||
return openChild(iasn);
|
return openChild(iasn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(EmailExtractedRootNode eern) {
|
public AbstractAction visit(EmailExtracted.RootNode eern) {
|
||||||
return openChild(eern);
|
return openChild(eern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(EmailExtractedAccountNode eean) {
|
public AbstractAction visit(AccountNode eean) {
|
||||||
return openChild(eean);
|
return openChild(eean);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(EmailExtractedFolderNode eefn) {
|
public AbstractAction visit(FolderNode eefn) {
|
||||||
return openChild(eefn);
|
return openChild(eefn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +441,7 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(ArtifactTypeNode atn) {
|
public AbstractAction visit(TypeNode atn) {
|
||||||
return openChild(atn);
|
return openChild(atn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,12 +514,12 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(KeywordHitsListNode khsn) {
|
public AbstractAction visit(ListNode khsn) {
|
||||||
return openChild(khsn);
|
return openChild(khsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(KeywordHitsKeywordNode khmln) {
|
public AbstractAction visit(TermNode khmln) {
|
||||||
return openChild(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.DataResultTopComponent;
|
||||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
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.DataSources;
|
||||||
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||||
@ -73,6 +73,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top component which displays something.
|
* Top component which displays something.
|
||||||
@ -387,7 +388,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
|
|
||||||
Children resultsChilds = results.getChildren();
|
Children resultsChilds = results.getChildren();
|
||||||
tree.expandNode(resultsChilds.findChild(KeywordHits.NAME));
|
tree.expandNode(resultsChilds.findChild(KeywordHits.NAME));
|
||||||
tree.expandNode(resultsChilds.findChild(ExtractedContentNode.NAME));
|
tree.expandNode(resultsChilds.findChild(ExtractedContent.NAME));
|
||||||
|
|
||||||
|
|
||||||
Node views = childNodes.findChild(ViewsNode.NAME);
|
Node views = childNodes.findChild(ViewsNode.NAME);
|
||||||
@ -587,7 +588,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
// change in node selection
|
// change in node selection
|
||||||
else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||||
respondSelection((Node[]) oldValue, (Node[]) newValue);
|
respondSelection((Node[]) oldValue, (Node[]) newValue);
|
||||||
} else if (changed.equals(IngestEvent.DATA.toString())) {
|
}
|
||||||
|
else if (changed.equals(IngestEvent.DATA.toString())) {
|
||||||
final ModuleDataEvent event = (ModuleDataEvent) oldValue;
|
final ModuleDataEvent event = (ModuleDataEvent) oldValue;
|
||||||
if (event.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO) {
|
if (event.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO) {
|
||||||
return;
|
return;
|
||||||
@ -595,7 +597,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
refreshTree(event.getArtifactType());
|
// @@@ refreshResultsTree(event.getArtifactType());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (changed.equals(IngestEvent.INGEST_JOB_COMPLETED.toString())
|
} 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() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
refreshContentTree();
|
refreshDataSourceTree();
|
||||||
refreshTree();
|
refreshResultsTree();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (changed.equals(IngestEvent.CONTENT_CHANGED.toString())) {
|
} else if (changed.equals(IngestEvent.CONTENT_CHANGED.toString())) {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
refreshContentTree();
|
refreshDataSourceTree();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -768,7 +770,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
refreshContentTree();
|
refreshDataSourceTree();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -776,7 +778,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
/**
|
/**
|
||||||
* Refreshes changed content nodes
|
* Refreshes changed content nodes
|
||||||
*/
|
*/
|
||||||
void refreshContentTree() {
|
private void refreshDataSourceTree() {
|
||||||
Node selectedNode = getSelectedNode();
|
Node selectedNode = getSelectedNode();
|
||||||
final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
|
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
|
* Refreshes the nodes in the tree to reflect updates in the database should
|
||||||
* be called in the gui thread
|
* 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
|
//save current selection
|
||||||
Node selectedNode = getSelectedNode();
|
Node selectedNode = getSelectedNode();
|
||||||
final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
|
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();
|
Children dirChilds = em.getRootContext().getChildren();
|
||||||
|
|
||||||
Node results = dirChilds.findChild(ResultsNode.NAME);
|
Node results = dirChilds.findChild(ResultsNode.NAME);
|
||||||
|
|
||||||
if (results == null) {
|
if (results == null) {
|
||||||
logger.log(Level.SEVERE, "Cannot find Results filter node, won't refresh the bb tree"); //NON-NLS
|
logger.log(Level.SEVERE, "Cannot find Results filter node, won't refresh the bb tree"); //NON-NLS
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OriginalNode original = results.getLookup().lookup(OriginalNode.class);
|
OriginalNode original = results.getLookup().lookup(OriginalNode.class);
|
||||||
ResultsNode resultsNode = (ResultsNode) original.getNode();
|
ResultsNode resultsNode = (ResultsNode) original.getNode();
|
||||||
RootContentChildren resultsNodeChilds = (RootContentChildren) resultsNode.getChildren();
|
RootContentChildren resultsNodeChilds = (RootContentChildren) resultsNode.getChildren();
|
||||||
resultsNodeChilds.refreshKeys(types);
|
resultsNodeChilds.refreshKeys(types);
|
||||||
|
|
||||||
|
|
||||||
final TreeView tree = getTree();
|
final TreeView tree = getTree();
|
||||||
|
// @@@ tree.expandNode(results);
|
||||||
tree.expandNode(results);
|
|
||||||
|
|
||||||
Children resultsChilds = results.getChildren();
|
Children resultsChilds = results.getChildren();
|
||||||
|
if (resultsChilds == null) {
|
||||||
if (resultsChilds == null) //intermediate state check
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node childNode = resultsChilds.findChild(KeywordHits.NAME);
|
Node childNode = resultsChilds.findChild(KeywordHits.NAME);
|
||||||
if (childNode == null) //intermediate state check
|
if (childNode == null) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tree.expandNode(childNode);
|
// @@@tree.expandNode(childNode);
|
||||||
|
|
||||||
childNode = resultsChilds.findChild(ExtractedContentNode.NAME);
|
childNode = resultsChilds.findChild(ExtractedContent.NAME);
|
||||||
if (childNode == null) //intermediate state check
|
if (childNode == null) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tree.expandNode(childNode);
|
tree.expandNode(childNode);
|
||||||
|
|
||||||
//restores selection if it was under the Results node
|
//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
|
logger.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Node extractedContent = resultsChilds.findChild(ExtractedContentNode.NAME);
|
Node extractedContent = resultsChilds.findChild(ExtractedContent.NAME);
|
||||||
Children extractedChilds = extractedContent.getChildren();
|
Children extractedChilds = extractedContent.getChildren();
|
||||||
treeNode = extractedChilds.findChild(type.getLabel());
|
treeNode = extractedChilds.findChild(type.getLabel());
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#Updated by build script
|
#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
|
LBL_splash_window_title=Starting Autopsy
|
||||||
SPLASH_HEIGHT=288
|
SPLASH_HEIGHT=288
|
||||||
SPLASH_WIDTH=538
|
SPLASH_WIDTH=538
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#Updated by build script
|
#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=Autopsy 3.1.0_Beta
|
||||||
CTL_MainWindow_Title_No_Project=Autopsy 3.1.0_Beta
|
CTL_MainWindow_Title_No_Project=Autopsy 3.1.0_Beta
|
||||||
|
Loading…
x
Reference in New Issue
Block a user