Merge pull request #5506 from sleuthkit/release-4.14.0

Merge release-4.14.0 branch into develop branch
This commit is contained in:
Richard Cordovano 2019-12-17 12:16:58 -05:00 committed by GitHub
commit c5054227f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 233 additions and 34 deletions

View File

@ -345,6 +345,7 @@
<package>org.sleuthkit.autopsy.textextractors.configs</package> <package>org.sleuthkit.autopsy.textextractors.configs</package>
<package>org.sleuthkit.autopsy.texttranslation</package> <package>org.sleuthkit.autopsy.texttranslation</package>
<package>org.sleuthkit.datamodel</package> <package>org.sleuthkit.datamodel</package>
<package>org.sleuthkit.datamodel.blackboardutils</package>
</public-packages> </public-packages>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-lang3-3.8.1.jar</runtime-relative-path> <runtime-relative-path>ext/commons-lang3-3.8.1.jar</runtime-relative-path>

View File

@ -227,6 +227,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
// maps the artifact type to its child node // maps the artifact type to its child node
private final HashMap<BlackboardArtifact.Type, TypeNode> typeNodeList = new HashMap<>(); private final HashMap<BlackboardArtifact.Type, TypeNode> typeNodeList = new HashMap<>();
@SuppressWarnings("deprecation")
TypeFactory() { TypeFactory() {
super(); super();

View File

@ -41,7 +41,6 @@ import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
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.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;
import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory; import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory;
@ -259,15 +258,20 @@ public class DataResultFilterNode extends FilterNode {
@Override @Override
protected Node[] createNodes(Node key) { protected Node[] createNodes(Node key) {
// filter out all non-message artifacts, if displaying the results from the Data Source tree // if displaying the results from the Data Source tree
// filter out artifacts
// In older versions of Autopsy, attachments were children of email/message artifacts
// and hence email/messages with attachments are shown in the tree data source tree,
BlackboardArtifact art = key.getLookup().lookup(BlackboardArtifact.class); BlackboardArtifact art = key.getLookup().lookup(BlackboardArtifact.class);
if (art != null if (art != null && filterArtifacts
&& filterArtifacts && ((FilterNodeUtils.showMessagesInDatasourceTree() == false)
&& art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() || (FilterNodeUtils.showMessagesInDatasourceTree()
&& art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { && art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
&& art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()))) {
return new Node[]{}; return new Node[]{};
} }
return new Node[]{new DataResultFilterNode(key, sourceEm)}; return new Node[]{new DataResultFilterNode(key, sourceEm)};
} }
} }

View File

@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.directorytree;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.Action; import javax.swing.Action;
@ -33,17 +32,12 @@ 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.datamodel.BlackboardArtifactNode;
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.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; 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.Image;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.Volume;
/** /**
* A node filter (decorator) that sets the actions for a node in the tree view * A node filter (decorator) that sets the actions for a node in the tree view
@ -137,11 +131,18 @@ class DirectoryTreeFilterNode extends FilterNode {
numVisibleChildren--; numVisibleChildren--;
} }
} else if (child instanceof BlackboardArtifact) { } else if (child instanceof BlackboardArtifact) {
BlackboardArtifact bba = (BlackboardArtifact) child;
if (FilterNodeUtils.showMessagesInDatasourceTree()) {
// Only message type artifacts are displayed in the tree // In older versions of Autopsy, attachments were children of email/message artifacts
if ((bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) // and hence email/messages with attachments are shown in the directory tree.
&& (bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_MESSAGE.getTypeID())) { BlackboardArtifact bba = (BlackboardArtifact) child;
// Only message type artifacts are displayed in the tree
if ((bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID())
&& (bba.getArtifactTypeID() != ARTIFACT_TYPE.TSK_MESSAGE.getTypeID())) {
numVisibleChildren--;
}
}
else {
numVisibleChildren--; numVisibleChildren--;
} }
} }

View File

@ -0,0 +1,66 @@
/*
* Autopsy Forensic Browser
*
* Copyright 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.directorytree;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber;
/**
* Utility class for Directory tree.
*
*/
final class FilterNodeUtils {
private static final int ATTACHMENT_CHILDOF_MSG_MAX_DB_MAJOR_VER = 8;
private static final int ATTACHMENT_CHILDOF_MSG_MAX_DB_MINOR_VER = 4;
/**
* Empty private constructor
*/
private FilterNodeUtils() {
}
/**
* Prior to schema version 8.4, attachments were children of messages and
* hence messages with any attachment children are shown in the directory
* tree.
*
* At 8.4 and later, attachments are tracked as an attribute, and the message
* artifacts don't need to be shown in the directory tree.
*
* This method may be used to check the schema version and behave
* accordingly, in order to maintain backward compatibility.
*
* @return True if messages with attachment children should be shown in
* directory tree.
*/
static boolean showMessagesInDatasourceTree() {
boolean showMessagesInDatasourceTree = true;
if (Case.isCaseOpen()) {
CaseDbSchemaVersionNumber version = Case.getCurrentCase().getSleuthkitCase().getDBSchemaCreationVersion();
showMessagesInDatasourceTree
= ((version.getMajor() < ATTACHMENT_CHILDOF_MSG_MAX_DB_MAJOR_VER)
|| (version.getMajor() == ATTACHMENT_CHILDOF_MSG_MAX_DB_MAJOR_VER && version.getMinor() < ATTACHMENT_CHILDOF_MSG_MAX_DB_MINOR_VER));
}
return showMessagesInDatasourceTree;
}
}

View File

@ -431,6 +431,8 @@ public final class GeolocationTopComponent extends TopComponent {
Bundle.GeoTopComponent_filter_exception_Title(), Bundle.GeoTopComponent_filter_exception_Title(),
Bundle.GeoTopComponent_filter_exception_msg(), Bundle.GeoTopComponent_filter_exception_msg(),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
setWaypointLoading(false);
} }
}); });
} }

View File

@ -417,8 +417,6 @@ public class KdTree<T extends KdTree.XYZPoint> implements Iterable<T> {
} }
Double nodeDistance = node.id.euclideanDistance(value); Double nodeDistance = node.id.euclideanDistance(value);
if (nodeDistance.compareTo(lastDistance) < 0) { if (nodeDistance.compareTo(lastDistance) < 0) {
if (results.size() == K && lastNode != null)
results.remove(lastNode);
results.add(node); results.add(node);
} else if (nodeDistance.equals(lastDistance)) { } else if (nodeDistance.equals(lastDistance)) {
results.add(node); results.add(node);

View File

@ -70,6 +70,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.SwingUtilities;
import org.jxmapviewer.viewer.DefaultWaypointRenderer; import org.jxmapviewer.viewer.DefaultWaypointRenderer;
/** /**
@ -204,13 +205,12 @@ final public class MapPanel extends javax.swing.JPanel {
Iterator<MapWaypoint> iterator = waypointTree.iterator(); Iterator<MapWaypoint> iterator = waypointTree.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
MapWaypoint point = iterator.next(); MapWaypoint point = iterator.next();
if (point != currentlySelectedWaypoint) { set.add(point);
set.add(point);
}
} }
// Add the currentlySelectedWaypoint to the end so that // Add the currentlySelectedWaypoint to the end so that
// it will be painted last. // it will be painted last.
if (currentlySelectedWaypoint != null) { if (currentlySelectedWaypoint != null) {
set.remove(currentlySelectedWaypoint);
set.add(currentlySelectedWaypoint); set.add(currentlySelectedWaypoint);
} }
} }
@ -342,7 +342,11 @@ final public class MapPanel extends javax.swing.JPanel {
*/ */
private void showPopupMenu(Point point) { private void showPopupMenu(Point point) {
try { try {
MapWaypoint waypoint = findClosestWaypoint(point); List<MapWaypoint> waypoints = findClosestWaypoint(point);
MapWaypoint waypoint = null;
if(waypoints.size() > 0) {
waypoint = waypoints.get(0);
}
showPopupMenu(waypoint, point); showPopupMenu(waypoint, point);
// Change the details popup to the currently selected point only if // Change the details popup to the currently selected point only if
// it the popup is currently visible // it the popup is currently visible
@ -410,6 +414,7 @@ final public class MapPanel extends javax.swing.JPanel {
currentPopup = popupFactory.getPopup(this, detailPane, popupLocation.x, popupLocation.y); currentPopup = popupFactory.getPopup(this, detailPane, popupLocation.x, popupLocation.y);
currentPopup.show(); currentPopup.show();
mapViewer.revalidate();
mapViewer.repaint(); mapViewer.repaint();
} }
} }
@ -437,7 +442,7 @@ final public class MapPanel extends javax.swing.JPanel {
* @return A waypoint that is within 10 pixels of the given point, or null * @return A waypoint that is within 10 pixels of the given point, or null
* if none was found. * if none was found.
*/ */
private MapWaypoint findClosestWaypoint(Point mouseClickPoint) { private List<MapWaypoint> findClosestWaypoint(Point mouseClickPoint) {
if (waypointTree == null) { if (waypointTree == null) {
return null; return null;
} }
@ -446,7 +451,7 @@ final public class MapPanel extends javax.swing.JPanel {
GeoPosition geopos = mapViewer.getTileFactory().pixelToGeo(mouseClickPoint, mapViewer.getZoom()); GeoPosition geopos = mapViewer.getTileFactory().pixelToGeo(mouseClickPoint, mapViewer.getZoom());
// Get the 5 nearest neightbors to the point // Get the 5 nearest neightbors to the point
Collection<MapWaypoint> waypoints = waypointTree.nearestNeighbourSearch(20, MapWaypoint.getDummyWaypoint(geopos)); Collection<MapWaypoint> waypoints = waypointTree.nearestNeighbourSearch(10, MapWaypoint.getDummyWaypoint(geopos));
if (waypoints == null || waypoints.isEmpty()) { if (waypoints == null || waypoints.isEmpty()) {
return null; return null;
@ -456,6 +461,7 @@ final public class MapPanel extends javax.swing.JPanel {
// These maybe the points closest to lat/log was clicked but // These maybe the points closest to lat/log was clicked but
// that doesn't mean they are close in terms of pixles. // that doesn't mean they are close in terms of pixles.
List<MapWaypoint> closestPoints = new ArrayList<>();
while (iterator.hasNext()) { while (iterator.hasNext()) {
MapWaypoint nextWaypoint = iterator.next(); MapWaypoint nextWaypoint = iterator.next();
@ -466,11 +472,11 @@ final public class MapPanel extends javax.swing.JPanel {
(int) point.getY() - rect.y); (int) point.getY() - rect.y);
if (converted_gp_pt.distance(mouseClickPoint) < 10) { if (converted_gp_pt.distance(mouseClickPoint) < 10) {
return nextWaypoint; closestPoints.add(nextWaypoint);
} }
} }
return null; return closestPoints;
} }
/** /**
@ -629,8 +635,14 @@ final public class MapPanel extends javax.swing.JPanel {
}//GEN-LAST:event_mapViewerMouseMoved }//GEN-LAST:event_mapViewerMouseMoved
private void mapViewerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseClicked private void mapViewerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseClicked
if(!evt.isPopupTrigger() && (evt.getButton() == MouseEvent.BUTTON1)) { if(!evt.isPopupTrigger() && SwingUtilities.isLeftMouseButton(evt)) {
currentlySelectedWaypoint = findClosestWaypoint(evt.getPoint()); List<MapWaypoint> waypoints = findClosestWaypoint(evt.getPoint());
if(waypoints.size() > 0) {
currentlySelectedWaypoint = waypoints.get(0);
}
// currentlySelectedWaypoint = findClosestWaypoint(evt.getPoint());
showDetailsPopup(); showDetailsPopup();
} }
}//GEN-LAST:event_mapViewerMouseClicked }//GEN-LAST:event_mapViewerMouseClicked

View File

@ -0,0 +1,79 @@
/*
* Autopsy Forensic Browser
*
* Copyright 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.geolocation.datamodel;
import java.util.Map;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
/**
* Class wraps any artifact that is not one of the known types, but have the
* TSK_GEO_LONGITUDE and TSK_GEO_LATITUDE attributes.
*
*/
final class CustomArtifactWaypoint extends Waypoint {
/**
* Constructs a new waypoint from the given artifact.
*
* @param artifact BlackboardArtifact for this waypoint
*
* @throws GeoLocationDataException
*/
CustomArtifactWaypoint(BlackboardArtifact artifact) throws GeoLocationDataException {
this(artifact, getAttributesFromArtifactAsMap(artifact));
}
/**
* Constructs a new CustomArtifactWaypoint.
*
* @param artifact BlackboardArtifact for this waypoint
* @param attributeMap A Map of the BlackboardAttributes for the given
* artifact.
*
* @throws GeoLocationDataException
*/
private CustomArtifactWaypoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
super(artifact,
getLabelFromArtifact(attributeMap),
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME).getValueLong() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE).getValueDouble() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE).getValueDouble() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE).getValueDouble() : null,
null, attributeMap, null);
}
/**
* Gets the label for this waypoint.
*
* @param artifact BlackboardArtifact for waypoint
*
* @return Returns a label for the waypoint, or empty string if no label was
* found.
*/
private static String getLabelFromArtifact(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) {
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
if (attribute != null) {
return attribute.getDisplayString();
}
return "";
}
}

View File

@ -71,7 +71,7 @@ final class LastKnownWaypoint extends Waypoint {
"LastKnownWaypoint_Label=Last Known Location",}) "LastKnownWaypoint_Label=Last Known Location",})
private static String getLabelFromArtifact(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException { private static String getLabelFromArtifact(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME); BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
String label = attribute.getDisplayString(); String label = attribute != null ? attribute.getDisplayString() : Bundle.LastKnownWaypoint_Label();
if (label == null || label.isEmpty()) { if (label == null || label.isEmpty()) {
label = Bundle.LastKnownWaypoint_Label(); label = Bundle.LastKnownWaypoint_Label();

View File

@ -592,8 +592,11 @@ public final class WaypointBuilder {
Route route = new Route(artifact); Route route = new Route(artifact);
waypoints.addAll(route.getRoute()); waypoints.addAll(route.getRoute());
break; break;
case TSK_GPS_LAST_KNOWN_LOCATION:
waypoints.add(new LastKnownWaypoint(artifact));
break;
default: default:
throw new GeoLocationDataException(String.format("Unable to create waypoint for artifact of type %s", type.toString())); waypoints.add(new CustomArtifactWaypoint(artifact));
} }
return waypoints; return waypoints;

View File

@ -15,6 +15,7 @@ ThunderbirdMboxFileIngestModule.addArtifact.indexError.message=Failed to index e
# {0} - file name # {0} - file name
# {1} - file ID # {1} - file ID
ThunderbirdMboxFileIngestModule.errorMessage.outOfDiskSpace=Out of disk space. Cannot copy '{0}' (id={1}) to parse. ThunderbirdMboxFileIngestModule.errorMessage.outOfDiskSpace=Out of disk space. Cannot copy '{0}' (id={1}) to parse.
ThunderbirdMboxFileIngestModule.handleAttch.addAttachmentsErrorMsg=Failed to add attachments to email message.
ThunderbirdMboxFileIngestModule.moduleName=Email Parser ThunderbirdMboxFileIngestModule.moduleName=Email Parser
ThunderbirdMboxFileIngestModule.noOpenCase.errMsg=Exception while getting open case. ThunderbirdMboxFileIngestModule.noOpenCase.errMsg=Exception while getting open case.
ThunderbirdMboxFileIngestModule.processPst.errMsg.outOfDiskSpace=Out of disk space. Cannot copy {0} to parse. ThunderbirdMboxFileIngestModule.processPst.errMsg.outOfDiskSpace=Out of disk space. Cannot copy {0} to parse.

View File

@ -22,6 +22,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -58,6 +59,9 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskDataException;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper;
import org.sleuthkit.datamodel.blackboardutils.FileAttachment;
import org.sleuthkit.datamodel.blackboardutils.MessageAttachments;
/** /**
* File-level ingest module that detects MBOX, PST, and vCard files based on * File-level ingest module that detects MBOX, PST, and vCard files based on
@ -70,6 +74,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
private FileManager fileManager; private FileManager fileManager;
private IngestJobContext context; private IngestJobContext context;
private Blackboard blackboard; private Blackboard blackboard;
private CommunicationArtifactsHelper communicationArtifactsHelper;
private Case currentCase; private Case currentCase;
@ -129,6 +134,15 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
logger.log(Level.WARNING, null, ex); logger.log(Level.WARNING, null, ex);
} }
try {
communicationArtifactsHelper = new CommunicationArtifactsHelper(currentCase.getSleuthkitCase(),
EmailParserModuleFactory.getModuleName(), abstractFile, Account.Type.EMAIL);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Failed to create CommunicationArtifactsHelper for file with object id = %d", abstractFile.getId()), ex);
return ProcessResult.ERROR;
}
if (isMbox) { if (isMbox) {
return processMBox(abstractFile); return processMBox(abstractFile);
} }
@ -267,7 +281,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
} else if (mboxParentDir.contains("/ImapMail/")) { //NON-NLS } else if (mboxParentDir.contains("/ImapMail/")) { //NON-NLS
emailFolder = mboxParentDir.substring(mboxParentDir.indexOf("/ImapMail/") + 9); //NON-NLS emailFolder = mboxParentDir.substring(mboxParentDir.indexOf("/ImapMail/") + 9); //NON-NLS
} }
emailFolder = emailFolder + mboxFileName; emailFolder += mboxFileName;
emailFolder = emailFolder.replaceAll(".sbd", ""); //NON-NLS emailFolder = emailFolder.replaceAll(".sbd", ""); //NON-NLS
String fileName; String fileName;
@ -487,8 +501,12 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
* *
* @return List of attachments * @return List of attachments
*/ */
@NbBundle.Messages({
"ThunderbirdMboxFileIngestModule.handleAttch.addAttachmentsErrorMsg=Failed to add attachments to email message."
})
private List<AbstractFile> handleAttachments(List<EmailMessage.Attachment> attachments, AbstractFile abstractFile, BlackboardArtifact messageArtifact) { private List<AbstractFile> handleAttachments(List<EmailMessage.Attachment> attachments, AbstractFile abstractFile, BlackboardArtifact messageArtifact) {
List<AbstractFile> files = new ArrayList<>(); List<AbstractFile> files = new ArrayList<>();
List<FileAttachment> fileAttachments = new ArrayList<>();
for (EmailMessage.Attachment attach : attachments) { for (EmailMessage.Attachment attach : attachments) {
String filename = attach.getName(); String filename = attach.getName();
long crTime = attach.getCrTime(); long crTime = attach.getCrTime();
@ -501,12 +519,14 @@ 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, messageArtifact, "", size, cTime, crTime, aTime, mTime, true, abstractFile, "",
EmailParserModuleFactory.getModuleName(), EmailParserModuleFactory.getModuleVersion(), "", encodingType); EmailParserModuleFactory.getModuleName(), EmailParserModuleFactory.getModuleVersion(), "", encodingType);
associateAttachmentWithMesssge(messageArtifact, df); associateAttachmentWithMesssge(messageArtifact, df);
files.add(df); files.add(df);
fileAttachments.add(new FileAttachment(df));
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
postErrorMessage( postErrorMessage(
NbBundle.getMessage(this.getClass(), "ThunderbirdMboxFileIngestModule.handleAttch.errMsg", NbBundle.getMessage(this.getClass(), "ThunderbirdMboxFileIngestModule.handleAttch.errMsg",
@ -516,6 +536,17 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
logger.log(Level.INFO, "", ex); logger.log(Level.INFO, "", ex);
} }
} }
try {
communicationArtifactsHelper.addAttachments(messageArtifact, new MessageAttachments(fileAttachments, Collections.emptyList()));
} catch (TskCoreException ex) {
postErrorMessage(
NbBundle.getMessage(this.getClass(), "ThunderbirdMboxFileIngestModule.handleAttch.addAttachmentsErrorMsg"),
"");
logger.log(Level.INFO, "Failed to add attachments to email message.", ex);
}
return files; return files;
} }