mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
2841: Attachments are children of messages.
2692: Messages & Attachments show in DataSource tree
This commit is contained in:
parent
4fdea244af
commit
a4dc97af6e
@ -45,6 +45,7 @@ import org.sleuthkit.datamodel.LocalFilesDataSource;
|
|||||||
import org.sleuthkit.datamodel.TskDataException;
|
import org.sleuthkit.datamodel.TskDataException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.AbstractContent;
|
||||||
import org.sleuthkit.datamodel.CarvingResult;
|
import org.sleuthkit.datamodel.CarvingResult;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
@ -295,7 +296,7 @@ public class FileManager implements Closeable {
|
|||||||
* @param atime The accessed time of the file.
|
* @param atime The accessed time of the file.
|
||||||
* @param mtime The modified time of the file.
|
* @param mtime The modified time of the file.
|
||||||
* @param isFile True if a file, false if a directory.
|
* @param isFile True if a file, false if a directory.
|
||||||
* @param parentFile The parent file from which the file was derived.
|
* @param parentObj The parent object from which the file was derived.
|
||||||
* @param rederiveDetails The details needed to re-derive file (will be
|
* @param rederiveDetails The details needed to re-derive file (will be
|
||||||
* specific to the derivation method), currently
|
* specific to the derivation method), currently
|
||||||
* unused.
|
* unused.
|
||||||
@ -317,7 +318,7 @@ public class FileManager implements Closeable {
|
|||||||
long size,
|
long size,
|
||||||
long ctime, long crtime, long atime, long mtime,
|
long ctime, long crtime, long atime, long mtime,
|
||||||
boolean isFile,
|
boolean isFile,
|
||||||
AbstractFile parentFile,
|
Content parentObj,
|
||||||
String rederiveDetails, String toolName, String toolVersion, String otherDetails,
|
String rederiveDetails, String toolName, String toolVersion, String otherDetails,
|
||||||
TskData.EncodingType encodingType) throws TskCoreException {
|
TskData.EncodingType encodingType) throws TskCoreException {
|
||||||
if (null == caseDb) {
|
if (null == caseDb) {
|
||||||
@ -325,7 +326,7 @@ public class FileManager implements Closeable {
|
|||||||
}
|
}
|
||||||
return caseDb.addDerivedFile(fileName, localPath, size,
|
return caseDb.addDerivedFile(fileName, localPath, size,
|
||||||
ctime, crtime, atime, mtime,
|
ctime, crtime, atime, mtime,
|
||||||
isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails, encodingType);
|
isFile, parentObj, rederiveDetails, toolName, toolVersion, otherDetails, encodingType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,7 @@ import org.openide.util.NbBundle;
|
|||||||
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
|
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts.AccountsRootNode;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts.AccountsRootNode;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
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;
|
||||||
@ -117,6 +118,11 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
return new SlackFileNode(sf);
|
return new SlackFileNode(sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractContentNode<? extends Content> visit(BlackboardArtifact art) {
|
||||||
|
return new BlackboardArtifactNode(art);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractContentNode<? extends Content> defaultVisit(SleuthkitVisitableItem di) {
|
protected AbstractContentNode<? extends Content> defaultVisit(SleuthkitVisitableItem di) {
|
||||||
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(),
|
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(),
|
||||||
|
@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.datamodel;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.openide.util.NbBundle;
|
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -48,8 +48,18 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
|
|||||||
* @param content Underlying Content instances
|
* @param content Underlying Content instances
|
||||||
*/
|
*/
|
||||||
AbstractContentNode(T content) {
|
AbstractContentNode(T content) {
|
||||||
|
this(content, Lookups.singleton(content) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles aspects that depend on the Content object
|
||||||
|
*
|
||||||
|
* @param content Underlying Content instances
|
||||||
|
* @param lookup The Lookup object for the node.
|
||||||
|
*/
|
||||||
|
AbstractContentNode(T content, Lookup lookup) {
|
||||||
//TODO consider child factory for the content children
|
//TODO consider child factory for the content children
|
||||||
super(new ContentChildren(content), Lookups.singleton(content));
|
super(new ContentChildren(content), lookup);
|
||||||
this.content = content;
|
this.content = content;
|
||||||
//super.setName(ContentUtils.getSystemName(content));
|
//super.setName(ContentUtils.getSystemName(content));
|
||||||
super.setName("content_" + Long.toString(content.getId())); //NON-NLS
|
super.setName("content_" + Long.toString(content.getId())); //NON-NLS
|
||||||
@ -66,8 +76,7 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
throw new UnsupportedOperationException(
|
super.setName(name);
|
||||||
NbBundle.getMessage(this.getClass(), "AbstractContentNode.exception.cannotChangeSysName.msg"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,6 +25,7 @@ import java.beans.PropertyChangeListener;
|
|||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -34,6 +35,7 @@ import java.util.logging.Level;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -43,9 +45,11 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
|
|||||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
|
import static org.sleuthkit.autopsy.datamodel.DataModelActionsFactory.VIEW_IN_NEW_WINDOW;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
|
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
||||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
@ -61,7 +65,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* Node wrapping a blackboard artifact object. This is generated from several
|
* Node wrapping a blackboard artifact object. This is generated from several
|
||||||
* places in the tree.
|
* places in the tree.
|
||||||
*/
|
*/
|
||||||
public class BlackboardArtifactNode extends DisplayableItemNode {
|
public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifact> {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
|
||||||
|
|
||||||
@ -72,6 +76,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
private final BlackboardArtifact artifact;
|
private final BlackboardArtifact artifact;
|
||||||
private Content associated = null;
|
private Content associated = null;
|
||||||
private List<NodeProperty<? extends Object>> customProperties;
|
private List<NodeProperty<? extends Object>> customProperties;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Artifact types which should have the full unique path of the associated
|
* Artifact types which should have the full unique path of the associated
|
||||||
* content as a property.
|
* content as a property.
|
||||||
@ -130,22 +135,17 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
* @param iconPath icon to use for the artifact
|
* @param iconPath icon to use for the artifact
|
||||||
*/
|
*/
|
||||||
public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
|
public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
|
||||||
super(Children.LEAF, createLookup(artifact));
|
super(artifact, createLookup(artifact));
|
||||||
|
|
||||||
this.artifact = artifact;
|
this.artifact = artifact;
|
||||||
|
|
||||||
// Look for associated Content i.e. the source file for the artifact
|
// Look for associated Content i.e. the source file for the artifact
|
||||||
if (this.getLookup().lookupAll(Content.class).size() > 1) {
|
|
||||||
for (Content content : this.getLookup().lookupAll(Content.class)) {
|
for (Content content : this.getLookup().lookupAll(Content.class)) {
|
||||||
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){
|
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){
|
||||||
this.associated = content;
|
this.associated = content;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (null == this.associated ) {
|
|
||||||
this.associated = this.getLookup().lookup(Content.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setName(Long.toString(artifact.getArtifactID()));
|
this.setName(Long.toString(artifact.getArtifactID()));
|
||||||
this.setDisplayName();
|
this.setDisplayName();
|
||||||
@ -160,32 +160,18 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
* @param artifact artifact to encapsulate
|
* @param artifact artifact to encapsulate
|
||||||
*/
|
*/
|
||||||
public BlackboardArtifactNode(BlackboardArtifact artifact) {
|
public BlackboardArtifactNode(BlackboardArtifact artifact) {
|
||||||
super(Children.LEAF, createLookup(artifact));
|
|
||||||
|
|
||||||
this.artifact = artifact;
|
this(artifact, ExtractedContent.getIconFilePath(artifact.getArtifactTypeID()));
|
||||||
|
|
||||||
// Look for associated Content - the source file for the artifact
|
|
||||||
if (this.getLookup().lookupAll(Content.class).size() > 1) {
|
|
||||||
for (Content content : this.getLookup().lookupAll(Content.class)) {
|
|
||||||
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){
|
|
||||||
this.associated = content;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (null == this.associated ) {
|
|
||||||
this.associated = this.getLookup().lookup(Content.class);
|
|
||||||
}
|
|
||||||
this.setName(Long.toString(artifact.getArtifactID()));
|
|
||||||
this.setDisplayName();
|
|
||||||
this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS
|
|
||||||
Case.addPropertyChangeListener(pcl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeListeners() {
|
private void removeListeners() {
|
||||||
Case.removePropertyChangeListener(pcl);
|
Case.removePropertyChangeListener(pcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlackboardArtifact getArtifact() {
|
||||||
|
return this.artifact;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
|
"BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
|
||||||
@ -235,9 +221,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
*/
|
*/
|
||||||
private void setDisplayName() {
|
private void setDisplayName() {
|
||||||
String displayName = ""; //NON-NLS
|
String displayName = ""; //NON-NLS
|
||||||
if (associated != null) {
|
|
||||||
displayName = associated.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a node for a keyword hit on an artifact, we set the
|
// If this is a node for a keyword hit on an artifact, we set the
|
||||||
// display name to be the artifact type name followed by " Artifact"
|
// display name to be the artifact type name followed by " Artifact"
|
||||||
@ -262,9 +245,30 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
// Do nothing since the display name will be set to the file name.
|
// Do nothing since the display name will be set to the file name.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setDisplayName(displayName);
|
|
||||||
|
if (displayName.isEmpty() && artifact != null) {
|
||||||
|
displayName = artifact.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setDisplayName(displayName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of the associated source file/content
|
||||||
|
*
|
||||||
|
* @return source file/content name
|
||||||
|
*/
|
||||||
|
public String getSrcName() {
|
||||||
|
|
||||||
|
String srcName = "";
|
||||||
|
if (associated != null) {
|
||||||
|
srcName = associated.getName();
|
||||||
|
}
|
||||||
|
return srcName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
|
"BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
|
||||||
"BlackboardArtifactNode.createSheet.artifactType.name=Artifact Type",
|
"BlackboardArtifactNode.createSheet.artifactType.name=Artifact Type",
|
||||||
@ -288,7 +292,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
|
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
|
||||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
|
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
|
||||||
NO_DESCR,
|
NO_DESCR,
|
||||||
this.getDisplayName()));
|
this.getSrcName()));
|
||||||
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||||
try {
|
try {
|
||||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
||||||
@ -579,4 +583,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
public String getItemType() {
|
public String getItemType() {
|
||||||
return getClass().getName();
|
return getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(ContentNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,9 @@ interface ContentNodeVisitor<T> {
|
|||||||
|
|
||||||
T visit(SlackFileNode sfn);
|
T visit(SlackFileNode sfn);
|
||||||
|
|
||||||
|
T visit(BlackboardArtifactNode bban);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor with an implementable default behavior for all types. Override
|
* Visitor with an implementable default behavior for all types. Override
|
||||||
* specific visit types to not use the default behavior.
|
* specific visit types to not use the default behavior.
|
||||||
@ -100,5 +103,10 @@ interface ContentNodeVisitor<T> {
|
|||||||
public T visit(SlackFileNode sfn) {
|
public T visit(SlackFileNode sfn) {
|
||||||
return defaultVisit(sfn);
|
return defaultVisit(sfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T visit(BlackboardArtifactNode bban) {
|
||||||
|
return defaultVisit(bban);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,7 +428,7 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLeafTypeNode() {
|
public boolean isLeafTypeNode() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.directorytree;
|
|||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.beans.PropertyVetoException;
|
import java.beans.PropertyVetoException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -43,6 +44,7 @@ import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
|||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
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.BlackboardArtifactNode;
|
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||||
@ -71,6 +73,8 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||||
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
|
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node used to wrap another node before passing it to the result viewers. The
|
* A node used to wrap another node before passing it to the result viewers. The
|
||||||
@ -210,6 +214,26 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
return propertySets;
|
return propertySets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the display name for the wrapped node.
|
||||||
|
*
|
||||||
|
* OutlineView used in the DataResult table uses getDisplayName() to populate
|
||||||
|
* the first column, which is Source File.
|
||||||
|
*
|
||||||
|
* Hence this override to return the 'correct' displayName for the wrapped node.
|
||||||
|
*
|
||||||
|
* @return The display name for the node.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
final Node orig = getOriginal();
|
||||||
|
String name = orig.getDisplayName();
|
||||||
|
if ((orig instanceof BlackboardArtifactNode)) {
|
||||||
|
name = ((BlackboardArtifactNode) orig).getSrcName();
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds information about which child node of this node, if any, should be
|
* Adds information about which child node of this node, if any, should be
|
||||||
* selected. Can be null.
|
* selected. Can be null.
|
||||||
@ -248,16 +272,20 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
|
|
||||||
private boolean filterKnown;
|
private boolean filterKnown;
|
||||||
private boolean filterSlack;
|
private boolean filterSlack;
|
||||||
|
private boolean filterArtifacts; // display message artifacts in the DataSource subtree
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the constructor
|
* the constructor
|
||||||
*/
|
*/
|
||||||
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
|
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
|
||||||
super(arg);
|
super(arg);
|
||||||
|
|
||||||
|
this.filterArtifacts = false;
|
||||||
switch (SelectionContext.getSelectionContext(arg)) {
|
switch (SelectionContext.getSelectionContext(arg)) {
|
||||||
case DATA_SOURCES:
|
case DATA_SOURCES:
|
||||||
filterSlack = filterSlackFromDataSources;
|
filterSlack = filterSlackFromDataSources;
|
||||||
filterKnown = filterKnownFromDataSources;
|
filterKnown = filterKnownFromDataSources;
|
||||||
|
filterArtifacts = true;
|
||||||
break;
|
break;
|
||||||
case VIEWS:
|
case VIEWS:
|
||||||
filterSlack = filterSlackFromViews;
|
filterSlack = filterSlackFromViews;
|
||||||
@ -291,6 +319,16 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
return new Node[]{};
|
return new Node[]{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filter out all non-message artifacts, if displaying the results from the Data Source tree
|
||||||
|
BlackboardArtifact art = key.getLookup().lookup(BlackboardArtifact.class);
|
||||||
|
if (art != null && filterArtifacts) {
|
||||||
|
if ( (art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) &&
|
||||||
|
(art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
|
||||||
|
return new Node[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
|
return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,6 +497,18 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractAction visit(BlackboardArtifactNode ban) {
|
public AbstractAction visit(BlackboardArtifactNode ban) {
|
||||||
|
BlackboardArtifact artifact = ban.getArtifact();
|
||||||
|
try {
|
||||||
|
if ( (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) ||
|
||||||
|
(artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
|
||||||
|
if (artifact.hasChildren()) {
|
||||||
|
return openChild(ban);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (TskCoreException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting children from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
|
||||||
|
}
|
||||||
return new ViewContextAction(
|
return new ViewContextAction(
|
||||||
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban);
|
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode;
|
|||||||
import org.openide.nodes.FilterNode;
|
import org.openide.nodes.FilterNode;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||||
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.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
@ -36,6 +37,7 @@ import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
|||||||
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.VolumeNode;
|
import org.sleuthkit.autopsy.datamodel.VolumeNode;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
import org.sleuthkit.datamodel.LayoutFile;
|
import org.sleuthkit.datamodel.LayoutFile;
|
||||||
@ -198,7 +200,7 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
|
|||||||
List<Content> derivedChildren = node.getContentChildren();
|
List<Content> derivedChildren = node.getContentChildren();
|
||||||
//child of a file, must be a (derived) file too
|
//child of a file, must be a (derived) file too
|
||||||
for (Content childContent : derivedChildren) {
|
for (Content childContent : derivedChildren) {
|
||||||
if (((AbstractFile) childContent).isDir()) {
|
if ((childContent instanceof AbstractFile) && ((AbstractFile) childContent).isDir()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -249,6 +251,16 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
|
|||||||
return defaultVisit(ft);
|
return defaultVisit(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean visit(BlackboardArtifactNode bbafn) {
|
||||||
|
// Only show Message arttifacts with children
|
||||||
|
if ( (bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) ||
|
||||||
|
(bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
|
||||||
|
return bbafn.hasContentChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default<Boolean> {
|
private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default<Boolean> {
|
||||||
@ -292,10 +304,23 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
|
|||||||
//return vdn.hasContentChildren();
|
//return vdn.hasContentChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean visit(FileTypesNode fileTypes) {
|
public Boolean visit(FileTypesNode fileTypes) {
|
||||||
return defaultVisit(fileTypes);
|
return defaultVisit(fileTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean visit(BlackboardArtifactNode bbafn) {
|
||||||
|
|
||||||
|
// Only show Message arttifacts with children
|
||||||
|
if ( (bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) ||
|
||||||
|
(bbafn.getArtifact().getArtifactTypeID() == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) ) {
|
||||||
|
return bbafn.hasContentChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,17 @@ import java.util.logging.Level;
|
|||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.nodes.FilterNode;
|
import org.openide.nodes.FilterNode;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
|
import org.openide.util.Exceptions;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.openide.util.lookup.ProxyLookup;
|
import org.openide.util.lookup.ProxyLookup;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
|
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
@ -77,7 +80,7 @@ class DirectoryTreeFilterNode extends FilterNode {
|
|||||||
String name = orig.getDisplayName();
|
String name = orig.getDisplayName();
|
||||||
if (orig instanceof AbstractContentNode) {
|
if (orig instanceof AbstractContentNode) {
|
||||||
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||||
if (file != null) {
|
if ((file != null) && (false == (orig instanceof BlackboardArtifactNode)) ){
|
||||||
try {
|
try {
|
||||||
int numVisibleChildren = getVisibleChildCount(file);
|
int numVisibleChildren = getVisibleChildCount(file);
|
||||||
|
|
||||||
@ -92,6 +95,15 @@ class DirectoryTreeFilterNode extends FilterNode {
|
|||||||
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (orig instanceof BlackboardArtifactNode) {
|
||||||
|
BlackboardArtifact artifact = ((BlackboardArtifactNode) orig).getArtifact();
|
||||||
|
try {
|
||||||
|
int numAttachments = artifact.getChildrenCount();
|
||||||
|
name = name + " \u200E(\u200E" + numAttachments + ")\u200E"; //NON-NLS
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error getting chidlren count for atifact: " + artifact, ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -115,7 +127,7 @@ class DirectoryTreeFilterNode extends FilterNode {
|
|||||||
if (purgeKnownFiles || purgeSlackFiles) {
|
if (purgeKnownFiles || purgeSlackFiles) {
|
||||||
// Purge known and/or slack files from the file count
|
// Purge known and/or slack files from the file count
|
||||||
for (int i = 0; i < childList.size(); i++) {
|
for (int i = 0; i < childList.size(); i++) {
|
||||||
Content child = (Content) childList.get(i);
|
Content child = childList.get(i);
|
||||||
if (child instanceof AbstractFile) {
|
if (child instanceof AbstractFile) {
|
||||||
AbstractFile childFile = (AbstractFile) child;
|
AbstractFile childFile = (AbstractFile) child;
|
||||||
if ((purgeKnownFiles && childFile.getKnown() == TskData.FileKnown.KNOWN)
|
if ((purgeKnownFiles && childFile.getKnown() == TskData.FileKnown.KNOWN)
|
||||||
@ -126,6 +138,7 @@ class DirectoryTreeFilterNode extends FilterNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return numVisibleChildren;
|
return numVisibleChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,11 +295,15 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
|||||||
*/
|
*/
|
||||||
private void processEmails(List<EmailMessage> emails, AbstractFile abstractFile) {
|
private void processEmails(List<EmailMessage> emails, AbstractFile abstractFile) {
|
||||||
List<AbstractFile> derivedFiles = new ArrayList<>();
|
List<AbstractFile> derivedFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (EmailMessage email : emails) {
|
for (EmailMessage email : emails) {
|
||||||
if (email.hasAttachment()) {
|
BlackboardArtifact msgArtifact = addArtifact(email, abstractFile);
|
||||||
derivedFiles.addAll(handleAttachments(email.getAttachments(), abstractFile));
|
|
||||||
|
if ((msgArtifact != null) && (email.hasAttachment())) {
|
||||||
|
derivedFiles.addAll(handleAttachments(email.getAttachments(), abstractFile, msgArtifact ));
|
||||||
}
|
}
|
||||||
addArtifact(email, abstractFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (derivedFiles.isEmpty() == false) {
|
if (derivedFiles.isEmpty() == false) {
|
||||||
@ -320,7 +324,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private List<AbstractFile> handleAttachments(List<EmailMessage.Attachment> attachments, AbstractFile abstractFile) {
|
private List<AbstractFile> handleAttachments(List<EmailMessage.Attachment> attachments, AbstractFile abstractFile, BlackboardArtifact messageArtifact) {
|
||||||
List<AbstractFile> files = new ArrayList<>();
|
List<AbstractFile> files = new ArrayList<>();
|
||||||
for (EmailMessage.Attachment attach : attachments) {
|
for (EmailMessage.Attachment attach : attachments) {
|
||||||
String filename = attach.getName();
|
String filename = attach.getName();
|
||||||
@ -334,7 +338,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
DerivedFile df = fileManager.addDerivedFile(filename, relPath,
|
DerivedFile df = fileManager.addDerivedFile(filename, relPath,
|
||||||
size, cTime, crTime, aTime, mTime, true, abstractFile, "",
|
size, cTime, crTime, aTime, mTime, true, messageArtifact, "",
|
||||||
EmailParserModuleFactory.getModuleName(), EmailParserModuleFactory.getModuleVersion(), "", encodingType);
|
EmailParserModuleFactory.getModuleName(), EmailParserModuleFactory.getModuleVersion(), "", encodingType);
|
||||||
files.add(df);
|
files.add(df);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
@ -356,7 +360,8 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
|||||||
* @param abstractFile
|
* @param abstractFile
|
||||||
*/
|
*/
|
||||||
@Messages({"ThunderbirdMboxFileIngestModule.addArtifact.indexError.message=Failed to index email message detected artifact for keyword search."})
|
@Messages({"ThunderbirdMboxFileIngestModule.addArtifact.indexError.message=Failed to index email message detected artifact for keyword search."})
|
||||||
private void addArtifact(EmailMessage email, AbstractFile abstractFile) {
|
private BlackboardArtifact addArtifact(EmailMessage email, AbstractFile abstractFile) {
|
||||||
|
BlackboardArtifact bbart = null;
|
||||||
List<BlackboardAttribute> bbattributes = new ArrayList<>();
|
List<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||||
String to = email.getRecipients();
|
String to = email.getRecipients();
|
||||||
String cc = email.getCc();
|
String cc = email.getCc();
|
||||||
@ -415,11 +420,8 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
|||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF, EmailParserModuleFactory.getModuleName(), rtf));
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF, EmailParserModuleFactory.getModuleName(), rtf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BlackboardArtifact bbart;
|
|
||||||
bbart = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
|
bbart = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
|
||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
|
|
||||||
@ -433,6 +435,8 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
|||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.WARNING, null, ex);
|
logger.log(Level.WARNING, null, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bbart;
|
||||||
}
|
}
|
||||||
|
|
||||||
void postErrorMessage(String subj, String details) {
|
void postErrorMessage(String subj, String details) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user