Merge pull request #5411 from raman-bt/5707-attchmnt-msg-contentviewer

5707, 5708 attchmnt msg contentviewer
This commit is contained in:
Richard Cordovano 2019-11-13 15:00:08 -05:00 committed by GitHub
commit f128d54bb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 329 additions and 65 deletions

View File

@ -18,10 +18,13 @@
*/ */
package org.sleuthkit.autopsy.communications.relationships; package org.sleuthkit.autopsy.communications.relationships;
import com.google.gson.Gson;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
@ -32,15 +35,18 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.blackboardutils.FileAttachment;
import org.sleuthkit.datamodel.blackboardutils.MessageAttachments;
/** /**
* Factory for creating thumbnail children nodes. * Factory for creating thumbnail children nodes.
*/ */
final class AttachmentsChildren extends Children.Keys<AbstractFile> { final class AttachmentThumbnailsChildren extends Children.Keys<AbstractFile> {
private static final Logger logger = Logger.getLogger(AttachmentsChildren.class.getName()); private static final Logger LOGGER = Logger.getLogger(AttachmentThumbnailsChildren.class.getName());
private final Set<BlackboardArtifact> artifacts; private final Set<BlackboardArtifact> artifacts;
@ -51,17 +57,16 @@ final class AttachmentsChildren extends Children.Keys<AbstractFile> {
* The thumbnails will be initialls sorted by size, then name so that they * The thumbnails will be initialls sorted by size, then name so that they
* appear sorted by size by default. * appear sorted by size by default.
*/ */
AttachmentsChildren(Set<BlackboardArtifact> artifacts) { AttachmentThumbnailsChildren(Set<BlackboardArtifact> artifacts) {
super(false); super(false);
this.artifacts = artifacts; this.artifacts = artifacts;
} }
@Override @Override
protected Node[] createNodes(AbstractFile t) { protected Node[] createNodes(AbstractFile t) {
return new Node[]{new AttachementNode(t)}; return new Node[]{new AttachementThumbnailNode(t)};
} }
@Override @Override
@ -77,15 +82,36 @@ final class AttachmentsChildren extends Children.Keys<AbstractFile> {
return result; return result;
}); });
artifacts.forEach((bba) -> { artifacts.forEach(new Consumer<BlackboardArtifact>() {
try { @Override
for (Content childContent : bba.getChildren()) { public void accept(BlackboardArtifact bba) {
if (childContent instanceof AbstractFile) { try {
thumbnails.add((AbstractFile) childContent); // Get the attachments from TSK_ATTACHMENTS attribute.
BlackboardAttribute attachmentsAttr = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS));
if (attachmentsAttr != null) {
String jsonVal = attachmentsAttr.getValueString();
MessageAttachments msgAttachments = new Gson().fromJson(jsonVal, MessageAttachments.class);
Collection<FileAttachment> fileAttachments = msgAttachments.getFileAttachments();
for (FileAttachment fileAttachment : fileAttachments) {
long attachedFileObjId = fileAttachment.getObjectId();
if (attachedFileObjId >= 0) {
AbstractFile attachedFile = bba.getSleuthkitCase().getAbstractFileById(attachedFileObjId);
thumbnails.add(attachedFile);
}
}
} else { // backward compatibility - email message attachments are derived files, children of the message.
for (Content childContent : bba.getChildren()) {
if (childContent instanceof AbstractFile) {
thumbnails.add((AbstractFile) childContent);
}
}
} }
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS
} }
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS
} }
}); });
@ -95,9 +121,9 @@ final class AttachmentsChildren extends Children.Keys<AbstractFile> {
/** /**
* A node for representing a thumbnail. * A node for representing a thumbnail.
*/ */
static class AttachementNode extends FileNode { static class AttachementThumbnailNode extends FileNode {
AttachementNode(AbstractFile file) { AttachementThumbnailNode(AbstractFile file) {
super(file, false); super(file, false);
} }

View File

@ -129,7 +129,7 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
thumbnailViewer.resetComponent(); thumbnailViewer.resetComponent();
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentsChildren(artifactList)), tableEM), true, this.getClass().getName())); thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentThumbnailsChildren(artifactList)), tableEM), true, this.getClass().getName()));
} }
@Override @Override

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.communications.relationships; package org.sleuthkit.autopsy.communications.relationships;
import com.google.gson.Gson;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.Action; import javax.swing.Action;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -38,6 +39,8 @@ import static org.sleuthkit.autopsy.communications.relationships.RelationshipsNo
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.blackboardutils.MessageAttachments;
/** /**
* Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView * Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView
@ -97,7 +100,7 @@ class MessageNode extends BlackboardArtifactNode {
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "", sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
try { try {
sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", artifact.getChildrenCount())); //NON-NLS sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", getAttachmentsCount())); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS
} }
@ -144,4 +147,21 @@ class MessageNode extends BlackboardArtifactNode {
public Action getPreferredAction() { public Action getPreferredAction() {
return preferredAction; return preferredAction;
} }
private int getAttachmentsCount() throws TskCoreException {
final BlackboardArtifact artifact = getArtifact();
int attachmentsCount;
// Attachments are specified in an attribute TSK_ATTACHMENTS as JSON attribute
BlackboardAttribute attachmentsAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS));
if (attachmentsAttr != null) {
String jsonVal = attachmentsAttr.getValueString();
MessageAttachments msgAttachments = new Gson().fromJson(jsonVal, MessageAttachments.class);
attachmentsCount = msgAttachments.getAttachmentsCount();
} else { // legacy attachments may be children of message artifact.
attachmentsCount = artifact.getChildrenCount();
}
return attachmentsCount;
}
} }

View File

@ -18,15 +18,17 @@
*/ */
package org.sleuthkit.autopsy.contentviewers; package org.sleuthkit.autopsy.contentviewers;
import org.sleuthkit.autopsy.datamodel.AttachmentNode;
import com.google.gson.Gson;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
@ -35,15 +37,12 @@ import org.openide.explorer.ExplorerManager;
import org.openide.nodes.AbstractNode; import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.corecomponents.DataResultPanel; import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -67,7 +66,12 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHO
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.blackboardutils.FileAttachment;
import org.sleuthkit.datamodel.blackboardutils.MessageAttachments;
import org.sleuthkit.datamodel.blackboardutils.Attachment;
import org.sleuthkit.datamodel.blackboardutils.URLAttachment;
/** /**
* Shows SMS/MMS/EMail messages * Shows SMS/MMS/EMail messages
@ -541,11 +545,34 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
} }
private void configureAttachments() throws TskCoreException { private void configureAttachments() throws TskCoreException {
//TODO: Replace this with code to get the actual attachements!
final Set<AbstractFile> attachments = artifact.getChildren().stream() final Set<Attachment> attachments;
.filter(AbstractFile.class::isInstance)
.map(AbstractFile.class::cast) // Attachments are specified in an attribute TSK_ATTACHMENTS as JSON attribute
.collect(Collectors.toSet()); BlackboardAttribute attachmentsAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS));
if(attachmentsAttr != null) {
attachments = new HashSet<>();
String jsonVal = attachmentsAttr.getValueString();
MessageAttachments msgAttachments = new Gson().fromJson(jsonVal, MessageAttachments.class);
Collection<FileAttachment> fileAttachments = msgAttachments.getFileAttachments();
for (FileAttachment fileAttachment: fileAttachments) {
attachments.add(fileAttachment);
}
Collection<URLAttachment> urlAttachments = msgAttachments.getUrlAttachments();
for (URLAttachment urlAttachment: urlAttachments) {
attachments.add(urlAttachment);
}
} else { // For backward compatibility - email attachements are derived files and children of the email message artifact
attachments = new HashSet<>();
for (Content child: artifact.getChildren()) {
if (child instanceof AbstractFile) {
attachments.add(new FileAttachment((AbstractFile)child));
}
}
}
final int numberOfAttachments = attachments.size(); final int numberOfAttachments = attachments.size();
msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0); msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
@ -633,16 +660,20 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
return doc.html(); return doc.html();
} }
private static class AttachmentsChildren extends Children.Keys<AbstractFile> {
/**
* Creates child nodes for message attachments.
*/
private static class AttachmentsChildren extends Children.Keys<Attachment> {
private final Set<AbstractFile> attachments; private final Set<Attachment> attachments;
AttachmentsChildren(Set<AbstractFile> attachments) { AttachmentsChildren(Set<Attachment> attachments) {
this.attachments = attachments; this.attachments = attachments;
} }
@Override @Override
protected Node[] createNodes(AbstractFile t) { protected Node[] createNodes(Attachment t) {
return new Node[]{new AttachmentNode(t)}; return new Node[]{new AttachmentNode(t)};
} }
@ -652,40 +683,4 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
setKeys(attachments); setKeys(attachments);
} }
} }
/**
* Extension of FileNode customized for viewing attachments in the
* MessageContentViewer. It overrides createSheet() to customize what
* properties are shown in the table, and could also override getActions(),
* getPreferedAction(), etc.
*/
private static class AttachmentNode extends FileNode {
AttachmentNode(AbstractFile file) {
super(file, false);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Set<String> keepProps = new HashSet<>(Arrays.asList(
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
//Remove all other props except for the ones above
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
for (Property<?> p : sheetSet.getProperties()) {
if (!keepProps.contains(p.getName())) {
sheetSet.remove(p.getName());
}
}
return sheet;
}
}
} }

View File

@ -0,0 +1,207 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017-2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import javax.swing.Action;
import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.contentviewers.MessageContentViewer;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datamodel.FileNode.getIconForFileType;
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.blackboardutils.Attachment;
import org.sleuthkit.datamodel.blackboardutils.FileAttachment;
import org.sleuthkit.datamodel.blackboardutils.URLAttachment;
/**
* Node for a message attachment.
*
*/
public final class AttachmentNode extends DisplayableItemNode {
private static final Logger LOGGER = Logger.getLogger(MessageContentViewer.class.getName());
private final Attachment attachment;
private final AbstractFile attachmentFile;
public AttachmentNode(Attachment attachment) {
super(Children.LEAF, createLookup(attachment));
super.setName(attachment.getLocation());
super.setDisplayName(attachment.getLocation()); // SET NODE DISPLAY NAME, I.E., TEXT IN FIRST TABLE CELL
this.attachment = attachment;
Long attachmentObjId = attachment.getObjId();
AbstractFile attchmentAbstractFile = null;
if (attachmentObjId != null && attachmentObjId > 0) {
try {
attchmentAbstractFile = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(attachmentObjId);
} catch (TskException | NoCurrentCaseException ex) {
LOGGER.log(Level.WARNING, "Error loading attachment file with object id " + attachmentObjId, ex); //NON-NLS
}
}
attachmentFile = attchmentAbstractFile;
// set the icon for node
setIcon();
}
@Override
@NbBundle.Messages({
"AttachmentNode.getActions.viewFileInDir.text=View File in Directory",
"AttachmentNode.getActions.viewInNewWin.text=View in New Window",
"AttachmentNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E",
"AttachmentNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash"})
public Action[] getActions(boolean context) {
List<Action> actionsList = new ArrayList<>();
actionsList.addAll(Arrays.asList(super.getActions(true)));
// If there is an attachment file
if (this.attachmentFile != null) {
actionsList.add(new ViewContextAction(Bundle.AttachmentNode_getActions_viewFileInDir_text(), this.attachmentFile));
actionsList.add(null); // Creates an item separator
actionsList.add(new NewWindowViewAction(Bundle.AttachmentNode_getActions_viewInNewWin_text(), this));
final Collection<AbstractFile> selectedFilesList
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
if (selectedFilesList.size() == 1) {
actionsList.add(new ExternalViewerAction(
Bundle.AttachmentNode_getActions_openInExtViewer_text(), this));
} else {
actionsList.add(ExternalViewerShortcutAction.getInstance());
}
actionsList.add(ViewFileInTimelineAction.createViewFileAction(this.attachmentFile));
actionsList.add(null); // Creates an item separator
actionsList.add(ExtractAction.getInstance());
actionsList.add(ExportCSVAction.getInstance());
actionsList.add(null); // Creates an item separator
actionsList.add(AddContentTagAction.getInstance());
if (1 == selectedFilesList.size()) {
actionsList.add(DeleteFileContentTagAction.getInstance());
}
actionsList.addAll(ContextMenuExtensionPoint.getActions());
}
return actionsList.toArray(new Action[0]);
}
@Override
protected Sheet createSheet() {
// Create a new property sheet.
Sheet sheet = new Sheet();
Sheet.Set sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
sheetSet.put(new NodeProperty<>("Location", "Location", "", this.attachment.getLocation()));
if (attachmentFile != null) {
long size = attachmentFile.getSize();
String mimeType = attachmentFile.getMIMEType();
// @TODO Vik-5762: get SCO Columns
sheetSet.put(new NodeProperty<>("Size", "Size", "", size));
if (StringUtils.isNotEmpty(mimeType)) {
sheetSet.put(new NodeProperty<>("Mime type", "Mime type", "", mimeType));
}
sheetSet.put(new NodeProperty<>("Known", "Known", "", attachmentFile.getKnown().getName()));
}
return sheet;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public boolean isLeafTypeNode() {
return true;
}
@Override
public String getItemType() {
return getClass().getName();
}
private static Lookup createLookup(Attachment attachment) {
Long attachmentObjId = attachment.getObjId();
if (attachmentObjId != null && attachmentObjId > 0) {
AbstractFile attachmentFile = null;
try {
attachmentFile = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(attachmentObjId);
if (attachmentFile != null) {
return Lookups.fixed(attachment, attachmentFile);
} else {
return Lookups.fixed(attachment);
}
} catch (TskException | NoCurrentCaseException ex) {
return Lookups.fixed(attachment);
}
}
return Lookups.fixed(attachment);
}
/**
* Set the icon based on attachment type
*/
private void setIcon() {
if (attachmentFile != null) {
this.setIconBaseWithExtension(getIconForFileType(attachmentFile));
} else if (attachment instanceof FileAttachment) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/document-question-16.png");
} else if (attachment instanceof URLAttachment) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/url-16.png");
} else {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png");
}
}
}

View File

@ -43,6 +43,11 @@ ArtifactStringContent.attrsTableHeader.type=Type
ArtifactStringContent.attrsTableHeader.value=Value ArtifactStringContent.attrsTableHeader.value=Value
ArtifactStringContent.failedToGetAttributes.message=Failed to get some or all attributes from case database ArtifactStringContent.failedToGetAttributes.message=Failed to get some or all attributes from case database
ArtifactStringContent.failedToGetSourcePath.message=Failed to get source file path from case database ArtifactStringContent.failedToGetSourcePath.message=Failed to get source file path from case database
AttachmentNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E
AttachmentNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash
AttachmentNode.getActions.viewFileInDir.text=View File in Directory
AttachmentNode.getActions.viewInNewWin.text=View in New Window
# {0} - node name
BaseChildFactory.NoSuchEventBusException.message=No event bus for node: {0} BaseChildFactory.NoSuchEventBusException.message=No event bus for node: {0}
BlackboardArtifactNode.createSheet.artifactDetails.displayName=Result Details BlackboardArtifactNode.createSheet.artifactDetails.displayName=Result Details
BlackboardArtifactNode.createSheet.artifactDetails.name=Result Details BlackboardArtifactNode.createSheet.artifactDetails.name=Result Details

View File

@ -186,6 +186,11 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(InterestingHits.InterestingItemTypeNode aThis); T visit(InterestingHits.InterestingItemTypeNode aThis);
/*
* Attachments
*/
T visit(AttachmentNode node);
/** /**
* 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.
@ -522,5 +527,11 @@ public interface DisplayableItemNodeVisitor<T> {
public T visit(Accounts.DefaultAccountTypeNode node) { public T visit(Accounts.DefaultAccountTypeNode node) {
return defaultVisit(node); return defaultVisit(node);
} }
@Override
public T visit(AttachmentNode node) {
return defaultVisit(node);
}
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B