From c0cdc38e71d372d2893d15bbca9da083997a3000 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 11 Dec 2019 12:54:59 -0500 Subject: [PATCH 1/8] 5709: Email attachments - Use CommunicationsArtifactsHelper to add the attachments to email messages. - Updated the DirectoryTree & DataResultsTable to not show message artifacts for 'new' cases, but continue to show them for older cases. --- Core/nbproject/project.xml | 1 + .../directorytree/DataResultFilterNode.java | 23 +++---- .../DirectoryTreeFilterNode.java | 23 +++---- .../directorytree/DirectoryTreeUtils.java | 60 +++++++++++++++++++ .../Bundle.properties-MERGED | 1 + .../ThunderbirdMboxFileIngestModule.java | 35 ++++++++++- 6 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 83aefea7c5..17e5d82284 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -345,6 +345,7 @@ org.sleuthkit.autopsy.textextractors.configs org.sleuthkit.autopsy.texttranslation org.sleuthkit.datamodel + org.sleuthkit.datamodel.blackboardutils ext/commons-lang3-3.8.1.jar diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index 548fb881be..262ea986a7 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -41,7 +41,6 @@ import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction; import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory; @@ -258,16 +257,20 @@ public class DataResultFilterNode extends FilterNode { @Override 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 + // unless there are message artifacts with attachments as children BlackboardArtifact art = key.getLookup().lookup(BlackboardArtifact.class); - if (art != null - && filterArtifacts - && 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)}; + if (art != null && filterArtifacts) { + + if ((DirectoryTreeUtils.showMessagesInDirTree() == false) || + (DirectoryTreeUtils.showMessagesInDirTree() && + 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)}; } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java index c9070015f2..c5d5712ec8 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.directorytree; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.logging.Level; import javax.swing.Action; @@ -33,17 +32,12 @@ import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.AbstractContentNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; -import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.TskCoreException; 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 @@ -137,11 +131,18 @@ class DirectoryTreeFilterNode extends FilterNode { numVisibleChildren--; } } else if (child instanceof BlackboardArtifact) { - 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())) { + + if (DirectoryTreeUtils.showMessagesInDirTree()) { + // In older versions of Autopsy, attachments were children of email/message artifacts + // and hence email/messages with attachments are shown in the directory tree. + 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--; } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java new file mode 100644 index 0000000000..bf84561f21 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java @@ -0,0 +1,60 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 Basis Technology Corp. + * Contact: carrier sleuthkit 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 DirectoryTreeUtils { + + private static final int ATTACHMENT_CHILDOF_MSG_MAX_DB_MAJOR_VER = 8; + private static final int ATTACHMENT_CHILDOF_MSG_MAX_DB_MINOR_VER = 4; + + + /** + * 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, attachments are tracked as an attribute, and the message artifact + * 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 showMessagesInDirTree() { + boolean showMessagesInDirTree = true; + if (Case.isCaseOpen()) { + CaseDbSchemaVersionNumber version = Case.getCurrentCase().getSleuthkitCase().getDBSchemaCreationVersion(); + showMessagesInDirTree + = ((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 showMessagesInDirTree; + } + +} diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties-MERGED b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties-MERGED index cdfd241886..90ce00170c 100755 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties-MERGED +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties-MERGED @@ -15,6 +15,7 @@ ThunderbirdMboxFileIngestModule.addArtifact.indexError.message=Failed to index e # {0} - file name # {1} - file ID 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.noOpenCase.errMsg=Exception while getting open case. ThunderbirdMboxFileIngestModule.processPst.errMsg.outOfDiskSpace=Out of disk space. Cannot copy {0} to parse. diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java index f1260f269f..419173fcff 100644 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -58,6 +59,9 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskDataException; 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 @@ -70,6 +74,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { private FileManager fileManager; private IngestJobContext context; private Blackboard blackboard; + private CommunicationArtifactsHelper communicationArtifactsHelper; private Case currentCase; @@ -129,6 +134,15 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { 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 %s", abstractFile.getName()), ex); + return ProcessResult.ERROR; + } + + if (isMbox) { return processMBox(abstractFile); } @@ -267,7 +281,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { } else if (mboxParentDir.contains("/ImapMail/")) { //NON-NLS emailFolder = mboxParentDir.substring(mboxParentDir.indexOf("/ImapMail/") + 9); //NON-NLS } - emailFolder = emailFolder + mboxFileName; + emailFolder += mboxFileName; emailFolder = emailFolder.replaceAll(".sbd", ""); //NON-NLS String fileName; @@ -487,8 +501,12 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { * * @return List of attachments */ + @NbBundle.Messages({ + "ThunderbirdMboxFileIngestModule.handleAttch.addAttachmentsErrorMsg=Failed to add attachments to email message." +}) private List handleAttachments(List attachments, AbstractFile abstractFile, BlackboardArtifact messageArtifact) { List files = new ArrayList<>(); + List fileAttachments = new ArrayList<>(); for (EmailMessage.Attachment attach : attachments) { String filename = attach.getName(); long crTime = attach.getCrTime(); @@ -501,12 +519,14 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { try { 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); associateAttachmentWithMesssge(messageArtifact, df); files.add(df); + + fileAttachments.add(new FileAttachment(df)); } catch (TskCoreException ex) { postErrorMessage( NbBundle.getMessage(this.getClass(), "ThunderbirdMboxFileIngestModule.handleAttch.errMsg", @@ -516,6 +536,17 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { 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; } From 858d50765c14b9c1a513bd188b89215fc3cb7efd Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 11 Dec 2019 13:26:46 -0500 Subject: [PATCH 2/8] Addressed Codacy comments. --- .../directorytree/DataResultFilterNode.java | 15 +++++++-------- .../autopsy/directorytree/DirectoryTreeUtils.java | 8 +++++++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index 262ea986a7..1eb22316c4 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -261,15 +261,14 @@ public class DataResultFilterNode extends FilterNode { // filter out artifacts // unless there are message artifacts with attachments as children BlackboardArtifact art = key.getLookup().lookup(BlackboardArtifact.class); - if (art != null && filterArtifacts) { + if (art != null && filterArtifacts + && ((DirectoryTreeUtils.showMessagesInDirTree() == false) + || (DirectoryTreeUtils.showMessagesInDirTree() + && art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() + && art.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()))) { + return new Node[]{}; + } - if ((DirectoryTreeUtils.showMessagesInDirTree() == false) || - (DirectoryTreeUtils.showMessagesInDirTree() && - 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)}; } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java index bf84561f21..40b3954897 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java @@ -30,7 +30,13 @@ final class DirectoryTreeUtils { 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 DirectoryTreeUtils() { + + } /** * Prior to schema version 8.4, attachments were children of messages and From a96e7d6859ec2ba6411ae09f2a7c957d8b25c7d4 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 11 Dec 2019 19:21:50 -0500 Subject: [PATCH 3/8] 5709: Email attachments. - address review comments. --- .../autopsy/datamodel/ExtractedContent.java | 1 + .../directorytree/DataResultFilterNode.java | 10 ++++++---- .../directorytree/DirectoryTreeFilterNode.java | 2 +- ...ectoryTreeUtils.java => FilterNodeUtils.java} | 16 ++++++++-------- .../ThunderbirdMboxFileIngestModule.java | 2 +- 5 files changed, 17 insertions(+), 14 deletions(-) rename Core/src/org/sleuthkit/autopsy/directorytree/{DirectoryTreeUtils.java => FilterNodeUtils.java} (83%) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index d97e980a8b..9de0e95462 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -227,6 +227,7 @@ public class ExtractedContent implements AutopsyVisitableItem { // maps the artifact type to its child node private final HashMap typeNodeList = new HashMap<>(); + @SuppressWarnings("deprecation") TypeFactory() { super(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index 1eb22316c4..ea7a3220b6 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -259,17 +259,19 @@ public class DataResultFilterNode extends FilterNode { protected Node[] createNodes(Node key) { // if displaying the results from the Data Source tree // filter out artifacts - // unless there are message artifacts with attachments as children + + // 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); if (art != null && filterArtifacts - && ((DirectoryTreeUtils.showMessagesInDirTree() == false) - || (DirectoryTreeUtils.showMessagesInDirTree() + && ((FilterNodeUtils.showMessagesInDatasourceTree() == false) + || (FilterNodeUtils.showMessagesInDatasourceTree() && 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)}; + return new Node[]{new DataResultFilterNode(key, sourceEm)}; } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java index c5d5712ec8..06a0b18c10 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java @@ -132,7 +132,7 @@ class DirectoryTreeFilterNode extends FilterNode { } } else if (child instanceof BlackboardArtifact) { - if (DirectoryTreeUtils.showMessagesInDirTree()) { + if (FilterNodeUtils.showMessagesInDatasourceTree()) { // In older versions of Autopsy, attachments were children of email/message artifacts // and hence email/messages with attachments are shown in the directory tree. BlackboardArtifact bba = (BlackboardArtifact) child; diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java b/Core/src/org/sleuthkit/autopsy/directorytree/FilterNodeUtils.java similarity index 83% rename from Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java rename to Core/src/org/sleuthkit/autopsy/directorytree/FilterNodeUtils.java index 40b3954897..ce8344862c 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeUtils.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/FilterNodeUtils.java @@ -26,7 +26,7 @@ import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber; * Utility class for Directory tree. * */ -final class DirectoryTreeUtils { +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; @@ -34,7 +34,7 @@ final class DirectoryTreeUtils { /** * Empty private constructor */ - private DirectoryTreeUtils() { + private FilterNodeUtils() { } @@ -43,8 +43,8 @@ final class DirectoryTreeUtils { * hence messages with any attachment children are shown in the directory * tree. * - * At 8.4, attachments are tracked as an attribute, and the message artifact - * don't need to be 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. @@ -52,15 +52,15 @@ final class DirectoryTreeUtils { * @return True if messages with attachment children should be shown in * directory tree. */ - static boolean showMessagesInDirTree() { - boolean showMessagesInDirTree = true; + static boolean showMessagesInDatasourceTree() { + boolean showMessagesInDatasourceTree = true; if (Case.isCaseOpen()) { CaseDbSchemaVersionNumber version = Case.getCurrentCase().getSleuthkitCase().getDBSchemaCreationVersion(); - showMessagesInDirTree + 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 showMessagesInDirTree; + return showMessagesInDatasourceTree; } } diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java index 419173fcff..983e59e6b4 100644 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java @@ -138,7 +138,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { 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 %s", abstractFile.getName()), ex); + logger.log(Level.SEVERE, String.format("Failed to create CommunicationArtifactsHelper for file with object id = %d", abstractFile.getId()), ex); return ProcessResult.ERROR; } From 366c03fccdea76f968838ebea3b2a25c5aed8910 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 13 Dec 2019 14:33:02 -0500 Subject: [PATCH 4/8] Added support for artifacts that have long and lat but are not one of the expected 6 --- .../geolocation/GeolocationTopComponent.java | 2 + .../datamodel/CustomArtifactWaypoint.java | 79 +++++++++++++++++++ .../datamodel/WaypointBuilder.java | 5 +- 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100755 Core/src/org/sleuthkit/autopsy/geolocation/datamodel/CustomArtifactWaypoint.java diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java index b1dee1cbb4..aafd468957 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java @@ -431,6 +431,8 @@ public final class GeolocationTopComponent extends TopComponent { Bundle.GeoTopComponent_filter_exception_Title(), Bundle.GeoTopComponent_filter_exception_msg(), JOptionPane.ERROR_MESSAGE); + + setWaypointLoading(false); } }); } diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/CustomArtifactWaypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/CustomArtifactWaypoint.java new file mode 100755 index 0000000000..bc3480ea40 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/CustomArtifactWaypoint.java @@ -0,0 +1,79 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 Basis Technology Corp. + * contact: carrier sleuthkit 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 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 attributeMap) { + BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME); + if (attribute != null) { + return attribute.getDisplayString(); + } + + return ""; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java index 86539412be..bccf5118a5 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java @@ -592,8 +592,11 @@ public final class WaypointBuilder { Route route = new Route(artifact); waypoints.addAll(route.getRoute()); break; + case TSK_GPS_LAST_KNOWN_LOCATION: + waypoints.add(new LastKnownWaypoint(artifact)); + break; default: - throw new GeoLocationDataException(String.format("Unable to create waypoint for artifact of type %s", type.toString())); + waypoints.add(new CustomArtifactWaypoint(artifact)); } return waypoints; From 7693255d17126fca5d281022913edf0da694f90d Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 16 Dec 2019 15:07:30 -0500 Subject: [PATCH 5/8] Fixed selection issues --- .../sleuthkit/autopsy/geolocation/KdTree.java | 2 -- .../autopsy/geolocation/MapPanel.java | 36 ++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/KdTree.java b/Core/src/org/sleuthkit/autopsy/geolocation/KdTree.java index 656abc9489..3a2f305083 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/KdTree.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/KdTree.java @@ -417,8 +417,6 @@ public class KdTree implements Iterable { } Double nodeDistance = node.id.euclideanDistance(value); if (nodeDistance.compareTo(lastDistance) < 0) { - if (results.size() == K && lastNode != null) - results.remove(lastNode); results.add(node); } else if (nodeDistance.equals(lastDistance)) { results.add(node); diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java index 7be6ac25a8..555caa781b 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java @@ -70,6 +70,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.datamodel.TskCoreException; import javax.imageio.ImageIO; +import javax.swing.SwingUtilities; import org.jxmapviewer.viewer.DefaultWaypointRenderer; /** @@ -204,13 +205,14 @@ final public class MapPanel extends javax.swing.JPanel { Iterator iterator = waypointTree.iterator(); while (iterator.hasNext()) { MapWaypoint point = iterator.next(); - if (point != currentlySelectedWaypoint) { +// if (point != currentlySelectedWaypoint) { set.add(point); - } +// } } // Add the currentlySelectedWaypoint to the end so that // it will be painted last. if (currentlySelectedWaypoint != null) { + set.remove(currentlySelectedWaypoint); set.add(currentlySelectedWaypoint); } } @@ -342,7 +344,11 @@ final public class MapPanel extends javax.swing.JPanel { */ private void showPopupMenu(Point point) { try { - MapWaypoint waypoint = findClosestWaypoint(point); + List waypoints = findClosestWaypoint(point); + MapWaypoint waypoint = null; + if(waypoints.size() > 0) { + waypoint = waypoints.get(0); + } showPopupMenu(waypoint, point); // Change the details popup to the currently selected point only if // it the popup is currently visible @@ -410,6 +416,7 @@ final public class MapPanel extends javax.swing.JPanel { currentPopup = popupFactory.getPopup(this, detailPane, popupLocation.x, popupLocation.y); currentPopup.show(); + mapViewer.revalidate(); mapViewer.repaint(); } } @@ -437,7 +444,7 @@ final public class MapPanel extends javax.swing.JPanel { * @return A waypoint that is within 10 pixels of the given point, or null * if none was found. */ - private MapWaypoint findClosestWaypoint(Point mouseClickPoint) { + private List findClosestWaypoint(Point mouseClickPoint) { if (waypointTree == null) { return null; } @@ -446,7 +453,7 @@ final public class MapPanel extends javax.swing.JPanel { GeoPosition geopos = mapViewer.getTileFactory().pixelToGeo(mouseClickPoint, mapViewer.getZoom()); // Get the 5 nearest neightbors to the point - Collection waypoints = waypointTree.nearestNeighbourSearch(20, MapWaypoint.getDummyWaypoint(geopos)); + Collection waypoints = waypointTree.nearestNeighbourSearch(10, MapWaypoint.getDummyWaypoint(geopos)); if (waypoints == null || waypoints.isEmpty()) { return null; @@ -456,6 +463,7 @@ final public class MapPanel extends javax.swing.JPanel { // These maybe the points closest to lat/log was clicked but // that doesn't mean they are close in terms of pixles. + List closestPoints = new ArrayList<>(); while (iterator.hasNext()) { MapWaypoint nextWaypoint = iterator.next(); @@ -466,11 +474,11 @@ final public class MapPanel extends javax.swing.JPanel { (int) point.getY() - rect.y); if (converted_gp_pt.distance(mouseClickPoint) < 10) { - return nextWaypoint; + closestPoints.add(nextWaypoint); } } - return null; + return closestPoints; } /** @@ -629,8 +637,14 @@ final public class MapPanel extends javax.swing.JPanel { }//GEN-LAST:event_mapViewerMouseMoved private void mapViewerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseClicked - if(!evt.isPopupTrigger() && (evt.getButton() == MouseEvent.BUTTON1)) { - currentlySelectedWaypoint = findClosestWaypoint(evt.getPoint()); + if(!evt.isPopupTrigger() && SwingUtilities.isLeftMouseButton(evt)) { + List waypoints = findClosestWaypoint(evt.getPoint()); + if(waypoints.size() > 0) { + currentlySelectedWaypoint = waypoints.get(0); + } + + +// currentlySelectedWaypoint = findClosestWaypoint(evt.getPoint()); showDetailsPopup(); } }//GEN-LAST:event_mapViewerMouseClicked @@ -667,6 +681,10 @@ final public class MapPanel extends javax.swing.JPanel { int y = (int)point.getY(); BufferedImage image = (waypoint == currentlySelectedWaypoint ? selectedWaypointImage: defaultWaypointImage); + + if(waypoint == currentlySelectedWaypoint) { + System.out.println("Paint selected waypoint"); + } (gd.create()).drawImage(image, x -image.getWidth() / 2, y -image.getHeight(), null); } From 31ce04a7920cdfdba2ad24d2593504590d64a4a0 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 16 Dec 2019 15:18:57 -0500 Subject: [PATCH 6/8] Removed print statement --- Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java index 555caa781b..c6174dac01 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java @@ -681,10 +681,6 @@ final public class MapPanel extends javax.swing.JPanel { int y = (int)point.getY(); BufferedImage image = (waypoint == currentlySelectedWaypoint ? selectedWaypointImage: defaultWaypointImage); - - if(waypoint == currentlySelectedWaypoint) { - System.out.println("Paint selected waypoint"); - } (gd.create()).drawImage(image, x -image.getWidth() / 2, y -image.getHeight(), null); } From f126cbba8fa2fef8c20d6be96ef4dbfb8a232b2a Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 16 Dec 2019 15:30:35 -0500 Subject: [PATCH 7/8] Fixed missing label value --- .../autopsy/geolocation/datamodel/LastKnownWaypoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/LastKnownWaypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/LastKnownWaypoint.java index 7bf85874ff..483dfd4689 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/LastKnownWaypoint.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/LastKnownWaypoint.java @@ -71,7 +71,7 @@ final class LastKnownWaypoint extends Waypoint { "LastKnownWaypoint_Label=Last Known Location",}) private static String getLabelFromArtifact(Map attributeMap) throws GeoLocationDataException { 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()) { label = Bundle.LastKnownWaypoint_Label(); From ef54899ac31775c2228e955c51eaff7d725a70d8 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 17 Dec 2019 11:29:22 -0500 Subject: [PATCH 8/8] Removed some commented out code --- Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java index c6174dac01..a90dac796b 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java @@ -205,9 +205,7 @@ final public class MapPanel extends javax.swing.JPanel { Iterator iterator = waypointTree.iterator(); while (iterator.hasNext()) { MapWaypoint point = iterator.next(); -// if (point != currentlySelectedWaypoint) { - set.add(point); -// } + set.add(point); } // Add the currentlySelectedWaypoint to the end so that // it will be painted last.