From 2cdd8f6e1a787c16cb07c90f6ba4826f217504f2 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 15 Jul 2019 17:50:00 -0400 Subject: [PATCH 01/46] Fixed position warning and demoted log messages to fine (aka DEBUG). --- Core/src/org/sleuthkit/autopsy/core/layer.xml | 2 +- .../corecomponents/DataContentTopComponent.java | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/layer.xml b/Core/src/org/sleuthkit/autopsy/core/layer.xml index 4706ea1b1d..41788864d6 100644 --- a/Core/src/org/sleuthkit/autopsy/core/layer.xml +++ b/Core/src/org/sleuthkit/autopsy/core/layer.xml @@ -436,7 +436,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java index af015d0b4a..0d41c2d748 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,9 +40,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; * startup). */ // Registered as a service provider in layer.xml -//@TopComponent.Description(preferredID = "DataContentTopComponent") -//@TopComponent.Registration(mode = "output", openAtStartup = true) -//@TopComponent.OpenActionRegistration(displayName = "#CTL_DataContentAction", preferredID = "DataContentTopComponent") @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public final class DataContentTopComponent extends TopComponent implements DataContent, ExplorerManager.Provider { @@ -125,15 +122,18 @@ public final class DataContentTopComponent extends TopComponent implements DataC public static synchronized DataContentTopComponent findInstance() { TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); if (win == null) { - logger.warning("Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); //NON-NLS + logger.log(Level.FINE, "Cannot find " + PREFERRED_ID + " component. It will " + + "not be located properly in the window system."); //NON-NLS return getDefault(); } + if (win instanceof DataContentTopComponent) { return (DataContentTopComponent) win; } - logger.warning( - "There seem to be multiple components with the '" + PREFERRED_ID //NON-NLS + + logger.log(Level.FINE, "There seem to be multiple components with the '" + PREFERRED_ID //NON-NLS + "' ID. That is a potential source of errors and unexpected behavior."); //NON-NLS + return getDefault(); } From 26221a245eedd86203c5aabd891793da98f6bfa3 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 15 Jul 2019 17:52:57 -0400 Subject: [PATCH 02/46] Upped level to INFO so it is visible --- .../autopsy/corecomponents/DataContentTopComponent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java index 0d41c2d748..e7992d6a85 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java @@ -122,7 +122,7 @@ public final class DataContentTopComponent extends TopComponent implements DataC public static synchronized DataContentTopComponent findInstance() { TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); if (win == null) { - logger.log(Level.FINE, "Cannot find " + PREFERRED_ID + " component. It will " + logger.log(Level.INFO, "Cannot find " + PREFERRED_ID + " component. It will " + "not be located properly in the window system."); //NON-NLS return getDefault(); } @@ -131,7 +131,7 @@ public final class DataContentTopComponent extends TopComponent implements DataC return (DataContentTopComponent) win; } - logger.log(Level.FINE, "There seem to be multiple components with the '" + PREFERRED_ID //NON-NLS + logger.log(Level.INFO, "There seem to be multiple components with the '" + PREFERRED_ID //NON-NLS + "' ID. That is a potential source of errors and unexpected behavior."); //NON-NLS return getDefault(); From 959511901bf926d0ff5a34b3e021e51fbdb8aa02 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 18 Jul 2019 16:09:58 -0400 Subject: [PATCH 03/46] Remove the location col from the property sheet --- .../datamodel/VirtualDirectoryNode.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java index 19e8950d33..86aedbd0af 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,8 +20,6 @@ package org.sleuthkit.autopsy.datamodel; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.logging.Level; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; @@ -119,7 +117,19 @@ public class VirtualDirectoryNode extends SpecialDirectoryNode { } //Otherwise default to the AAFN createSheet method. - return super.createSheet(); + Sheet defaultSheet = super.createSheet(); + Sheet.Set defaultSheetSet = defaultSheet.get(Sheet.PROPERTIES); + + //Pick out the location column + //This path should not show because VDs are not part of the data source + String locationCol = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.locationColLbl"); + for (Property p : defaultSheetSet.getProperties()) { + if(locationCol.equals(p.getName())) { + defaultSheetSet.remove(p.getName()); + } + } + + return defaultSheet; } @Override From e47d12a8bbacbe42f3875cc973e7c4bd8f0d2d43 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 19 Jul 2019 13:38:29 -0400 Subject: [PATCH 04/46] 5319 first pass of changing ingest listeners --- .../casemodule/CollaborationMonitor.java | 5 +- .../casemodule/IngestJobInfoPanel.java | 5 +- .../DataSourceSummaryDialog.java | 5 +- .../eventlisteners/IngestEventsListener.java | 14 +- .../optionspanel/GlobalSettingsPanel.java | 5 +- .../CommandLineIngestManager.java | 63 +++-- .../autopsy/communications/FiltersPanel.java | 264 +++++++++--------- .../datamodel/AbstractAbstractFileNode.java | 4 +- .../autopsy/datamodel/DeletedContent.java | 7 +- .../autopsy/datamodel/EmailExtracted.java | 30 +- .../autopsy/datamodel/ExtractedContent.java | 47 ++-- .../sleuthkit/autopsy/datamodel/FileSize.java | 36 +-- .../datamodel/FileTypesByExtension.java | 22 +- .../datamodel/FileTypesByMimeType.java | 10 +- .../autopsy/datamodel/HashsetHits.java | 47 ++-- .../autopsy/datamodel/ImageNode.java | 4 +- .../autopsy/datamodel/InterestingHits.java | 48 ++-- .../autopsy/datamodel/KeywordHits.java | 23 +- .../org/sleuthkit/autopsy/datamodel/Tags.java | 7 +- .../autopsy/datamodel/VolumeNode.java | 4 +- .../autopsy/datamodel/accounts/Accounts.java | 111 ++++---- .../DirectoryTreeTopComponent.java | 10 +- .../autopsy/imagewriter/ImageWriter.java | 210 +++++++------- .../autopsy/timeline/TimeLineController.java | 20 +- .../autopsy/testutils/IngestJobRunner.java | 8 +- .../autoingest/AutoIngestManager.java | 3 +- .../configuration/MultiUserTestTool.java | 45 +-- .../imagegallery/ImageGalleryController.java | 7 +- .../DropdownListSearchPanel.java | 1 + 29 files changed, 578 insertions(+), 487 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java index f99a643900..89778bb86e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java @@ -24,9 +24,11 @@ import java.beans.PropertyChangeListener; import java.io.Serializable; import java.time.Duration; import java.time.Instant; +import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -59,6 +61,7 @@ final class CollaborationMonitor { private static final String COLLABORATION_MONITOR_EVENT = "COLLABORATION_MONITOR_EVENT"; //NON-NLS private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.ADDING_DATA_SOURCE, Case.Events.DATA_SOURCE_ADDED, Case.Events.ADDING_DATA_SOURCE_FAILED); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_STARTED, IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 2; private static final String PERIODIC_TASK_THREAD_NAME = "collab-monitor-periodic-tasks-%d"; //NON-NLS private static final long HEARTBEAT_INTERVAL_MINUTES = 1; @@ -113,7 +116,7 @@ final class CollaborationMonitor { * Create a local tasks manager to track and broadcast local tasks. */ localTasksManager = new LocalTasksManager(); - IngestManager.getInstance().addIngestJobEventListener(localTasksManager); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, localTasksManager); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, localTasksManager); /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java index 7c7284d935..b1e6d83482 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java @@ -23,7 +23,9 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.event.ListSelectionEvent; @@ -44,6 +46,7 @@ import org.sleuthkit.datamodel.DataSource; public final class IngestJobInfoPanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(IngestJobInfoPanel.class.getName()); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED); private List ingestJobs; private final List ingestJobsForSelectedDataSource = new ArrayList<>(); private IngestJobTableModel ingestJobTableModel = new IngestJobTableModel(); @@ -69,7 +72,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { this.ingestModuleTable.setModel(this.ingestModuleTableModel); }); - IngestManager.getInstance().addIngestJobEventListener((PropertyChangeEvent evt) -> { + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST , (PropertyChangeEvent evt) -> { if (evt.getPropertyName().equals(IngestManager.IngestJobEvent.STARTED.toString()) || evt.getPropertyName().equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || evt.getPropertyName().equals(IngestManager.IngestJobEvent.COMPLETED.toString())) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java index 1535cbefe0..3c68b7b3ed 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java @@ -20,9 +20,11 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import java.awt.Frame; import java.beans.PropertyChangeEvent; +import java.util.EnumSet; import java.util.Map; import java.util.Observable; import java.util.Observer; +import java.util.Set; import javax.swing.event.ListSelectionEvent; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; @@ -38,6 +40,7 @@ import org.sleuthkit.datamodel.IngestJobInfo; final class DataSourceSummaryDialog extends javax.swing.JDialog implements Observer { private static final long serialVersionUID = 1L; + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); private final DataSourceSummaryCountsPanel countsPanel; private final DataSourceSummaryDetailsPanel detailsPanel; private final DataSourceBrowser dataSourcesPanel; @@ -77,7 +80,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser } }); //add listener to refresh jobs with Started status when they complete - IngestManager.getInstance().addIngestJobEventListener((PropertyChangeEvent evt) -> { + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> { if (evt instanceof DataSourceAnalysisCompletedEvent) { DataSourceAnalysisCompletedEvent dsEvent = (DataSourceAnalysisCompletedEvent) evt; if (dsEvent.getResult() == Reason.ANALYSIS_COMPLETED) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 58bf031359..6ec535a999 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -24,8 +24,10 @@ import java.beans.PropertyChangeListener; import static java.lang.Boolean.FALSE; import java.util.ArrayList; import java.util.Collection; +import java.util.EnumSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; @@ -51,6 +53,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.coreutils.ThreadUtils; +import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; @@ -63,16 +66,17 @@ import org.sleuthkit.datamodel.SleuthkitCase; public class IngestEventsListener { private static final Logger LOGGER = Logger.getLogger(CorrelationAttributeInstance.class.getName()); - - final Collection recentlyAddedCeArtifacts = new LinkedHashSet<>(); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(DATA_ADDED); private static int correlationModuleInstanceCount; private static boolean flagNotableItems; private static boolean flagSeenDevices; private static boolean createCrProperties; - private final ExecutorService jobProcessingExecutor; private static final String INGEST_EVENT_THREAD_NAME = "Ingest-Event-Listener-%d"; + private final ExecutorService jobProcessingExecutor; private final PropertyChangeListener pcl1 = new IngestModuleEventListener(); private final PropertyChangeListener pcl2 = new IngestJobEventListener(); + final Collection recentlyAddedCeArtifacts = new LinkedHashSet<>(); IngestEventsListener() { jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(INGEST_EVENT_THREAD_NAME).build()); @@ -86,8 +90,8 @@ public class IngestEventsListener { * Add all of our Ingest Event Listeners to the IngestManager Instance. */ public void installListeners() { - IngestManager.getInstance().addIngestModuleEventListener(pcl1); - IngestManager.getInstance().addIngestJobEventListener(pcl2); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl1); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl2); } /* diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index 49d80819ab..6236d3b8bd 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -24,6 +24,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.EnumSet; +import java.util.Set; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.netbeans.spi.options.OptionsPanelController; @@ -49,7 +50,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(GlobalSettingsPanel.class.getName()); - + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED); private final IngestJobEventPropertyChangeListener ingestJobEventListener; /** @@ -72,7 +73,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } private void addIngestJobEventsListener() { - IngestManager.getInstance().addIngestJobEventListener(ingestJobEventListener); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobEventListener); ingestStateUpdated(Case.isCaseOpen()); } diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java index bbe14c0020..9cc726c32e 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java @@ -27,7 +27,9 @@ import java.nio.file.Paths; import java.util.List; import java.util.UUID; import java.util.Collection; +import java.util.EnumSet; import java.util.Iterator; +import java.util.Set; import java.util.logging.Level; import org.netbeans.spi.sendopts.OptionProcessor; import org.openide.LifecycleManager; @@ -65,6 +67,7 @@ import org.sleuthkit.datamodel.Content; public class CommandLineIngestManager { private static final Logger LOGGER = Logger.getLogger(CommandLineIngestManager.class.getName()); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED); private Path rootOutputDirectory; public CommandLineIngestManager() { @@ -198,10 +201,11 @@ public class CommandLineIngestManager { System.out.println("Unable to ingest data source " + dataSourcePath + ". Exiting..."); } catch (Throwable ex) { /* - * Unexpected runtime exceptions firewall. This task is designed to - * be able to be run in an executor service thread pool without - * calling get() on the task's Future, so this ensures that - * such errors get logged. + * Unexpected runtime exceptions firewall. This task is + * designed to be able to be run in an executor service + * thread pool without calling get() on the task's + * Future, so this ensures that such errors get + * logged. */ LOGGER.log(Level.SEVERE, "Unexpected error while ingesting data source " + dataSourcePath, ex); System.out.println("Unexpected error while ingesting data source " + dataSourcePath + ". Exiting..."); @@ -229,6 +233,7 @@ public class CommandLineIngestManager { * object. * * @param dataSource DataSource object + * * @return object ID */ private Long getDataSourceId(AutoIngestDataSource dataSource) { @@ -268,12 +273,33 @@ public class CommandLineIngestManager { * @param dataSource The data source. * * @throws - * AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException - * if there was a DSP processing error + * AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException if + * there + * was + * a + * DSP + * processing + * error * - * @throws InterruptedException if the thread running the job processing - * task is interrupted while blocked, i.e., if auto ingest is shutting - * down. + * @throws InterruptedException if + * the + * thread + * running + * the + * job + * processing + * task + * is + * interrupted + * while + * blocked, + * i.e., + * if + * auto + * ingest + * is + * shutting + * down. */ private void runDataSourceProcessor(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { @@ -295,7 +321,7 @@ public class CommandLineIngestManager { LOGGER.log(Level.SEVERE, "Unsupported data source {0}", dataSource.getPath()); // NON-NLS return; } - + DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor(); synchronized (ingestLock) { // Try each DSP in decreasing order of confidence @@ -375,16 +401,17 @@ public class CommandLineIngestManager { * @param dataSource The data source to analyze. * * @throws AnalysisStartupException if there is an error analyzing the - * data source. - * @throws InterruptedException if the thread running the job processing - * task is interrupted while blocked, i.e., if auto ingest is shutting - * down. + * data source. + * @throws InterruptedException if the thread running the job + * processing task is interrupted while + * blocked, i.e., if auto ingest is + * shutting down. */ private void analyze(AutoIngestDataSource dataSource) throws AnalysisStartupException, InterruptedException { LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", dataSource.getPath()); IngestJobEventListener ingestJobEventListener = new IngestJobEventListener(); - IngestManager.getInstance().addIngestJobEventListener(ingestJobEventListener); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobEventListener); try { synchronized (ingestLock) { IngestJobSettings ingestJobSettings = new IngestJobSettings(UserPreferences.getCommandLineModeIngestModuleContextString()); @@ -447,7 +474,7 @@ public class CommandLineIngestManager { * the path. * * @param caseFoldersPath The root case folders path. - * @param caseName The name of the case. + * @param caseName The name of the case. * * @return A case folder path with a time stamp suffix. */ @@ -461,8 +488,8 @@ public class CommandLineIngestManager { * for a case. * * @param folderToSearch The folder to be searched. - * @param caseName The name of the case for which a case folder is to be - * found. + * @param caseName The name of the case for which a case folder is + * to be found. * * @return The path of the case folder, or null if it is not found. */ diff --git a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java index 445bf25c87..15e1d29b3c 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.stream.Collectors; @@ -81,7 +82,8 @@ final public class FiltersPanel extends JPanel { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(FiltersPanel.class.getName()); - + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(DATA_ADDED); /** * Map from Account.Type to the checkbox for that account type's filter. */ @@ -120,17 +122,17 @@ final public class FiltersPanel extends JPanel { * initially. */ private boolean deviceAccountTypeEnabled; - + private Case openCase = null; @NbBundle.Messages({"refreshText=Refresh Results", "applyText=Apply"}) public FiltersPanel() { initComponents(); - + CheckBoxIconPanel panel = createAccoutTypeCheckBoxPanel(Account.Type.DEVICE, true); accountTypeMap.put(Account.Type.DEVICE, panel.getCheckBox()); accountTypeListPane.add(panel); - + deviceRequiredLabel.setVisible(false); accountTypeRequiredLabel.setVisible(false); startDatePicker.setDate(LocalDate.now().minusWeeks(3)); @@ -151,8 +153,8 @@ final public class FiltersPanel extends JPanel { updateFilters(true); UserPreferences.addChangeListener(preferenceChangeEvent -> { - if (preferenceChangeEvent.getKey().equals(UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME) || - preferenceChangeEvent.getKey().equals(UserPreferences.TIME_ZONE_FOR_DISPLAYS)) { + if (preferenceChangeEvent.getKey().equals(UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME) + || preferenceChangeEvent.getKey().equals(UserPreferences.TIME_ZONE_FOR_DISPLAYS)) { updateTimeZone(); } }); @@ -166,22 +168,21 @@ final public class FiltersPanel extends JPanel { && (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() || eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID() || eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() - || eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID())) - { - updateFilters(true); - needsRefresh = true; - validateFilters(); + || eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID())) { + updateFilters(true); + needsRefresh = true; + validateFilters(); } } }; - + this.ingestJobListener = pce -> { String eventType = pce.getPropertyName(); - if (eventType.equals(COMPLETED.toString()) && - updateFilters(true)) { - - needsRefresh = true; - validateFilters(); + if (eventType.equals(COMPLETED.toString()) + && updateFilters(true)) { + + needsRefresh = true; + validateFilters(); } }; @@ -208,16 +209,16 @@ final public class FiltersPanel extends JPanel { refreshButton.setEnabled(someDevice && someAccountType && needsRefresh && validLimit); needsRefreshLabel.setVisible(needsRefresh); } - + private boolean validateLimitValue() { - String selectedValue = (String)limitComboBox.getSelectedItem(); - if(selectedValue.trim().equalsIgnoreCase("all")) { + String selectedValue = (String) limitComboBox.getSelectedItem(); + if (selectedValue.trim().equalsIgnoreCase("all")) { return true; } else { - try{ + try { int value = Integer.parseInt(selectedValue); return value > 0; - } catch( NumberFormatException ex) { + } catch (NumberFormatException ex) { return false; } } @@ -242,7 +243,7 @@ final public class FiltersPanel extends JPanel { private boolean updateFilters(boolean initialState) { boolean newAccountType = updateAccountTypeFilter(initialState); boolean newDeviceFilter = updateDeviceFilter(initialState); - + // both or either are true, return true; return newAccountType || newDeviceFilter; } @@ -250,13 +251,13 @@ final public class FiltersPanel extends JPanel { @Override public void addNotify() { super.addNotify(); - IngestManager.getInstance().addIngestModuleEventListener(ingestListener); - IngestManager.getInstance().addIngestJobEventListener(ingestJobListener); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, ingestListener); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobListener); Case.addEventTypeSubscriber(EnumSet.of(CURRENT_CASE), evt -> { //clear the device filter widget when the case changes. devicesMap.clear(); devicesListPane.removeAll(); - + accountTypeMap.clear(); accountTypeListPane.removeAll(); }); @@ -271,9 +272,9 @@ final public class FiltersPanel extends JPanel { /** * Populate the Account Types filter widgets - * + * * @param selected the initial value for the account type checkbox - * + * * @return True, if a new accountType was found */ private boolean updateAccountTypeFilter(boolean selected) { @@ -281,9 +282,9 @@ final public class FiltersPanel extends JPanel { try { final CommunicationsManager communicationsManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); List accountTypesInUse = communicationsManager.getAccountTypesInUse(); - + for (Account.Type type : accountTypesInUse) { - + if (!accountTypeMap.containsKey(type) && !type.equals(Account.Type.CREDIT_CARD)) { CheckBoxIconPanel panel = createAccoutTypeCheckBoxPanel(type, selected); accountTypeMap.put(type, panel.getCheckBox()); @@ -305,14 +306,14 @@ final public class FiltersPanel extends JPanel { return newOneFound; } - + /** * Helper function to create a new instance of the CheckBoxIconPanel base on * the Account.Type and initalState (check box state). - * - * @param type Account.Type to display on the panel + * + * @param type Account.Type to display on the panel * @param initalState initial check box state - * + * * @return instance of the CheckBoxIconPanel */ private CheckBoxIconPanel createAccoutTypeCheckBoxPanel(Account.Type type, boolean initalState) { @@ -324,12 +325,12 @@ final public class FiltersPanel extends JPanel { panel.addItemListener(validationListener); return panel; } - + /** * Populate the devices filter widgets - * + * * @param selected Sets the initial state of device check box - * + * * @return true if a new device was found */ private boolean updateDeviceFilter(boolean selected) { @@ -339,15 +340,15 @@ final public class FiltersPanel extends JPanel { for (DataSource dataSource : sleuthkitCase.getDataSources()) { String dsName = sleuthkitCase.getContentById(dataSource.getId()).getName(); - if(devicesMap.containsKey(dataSource.getDeviceId())) { + if (devicesMap.containsKey(dataSource.getDeviceId())) { continue; } - + final JCheckBox jCheckBox = new JCheckBox(dsName, selected); jCheckBox.addItemListener(validationListener); devicesListPane.add(jCheckBox); devicesMap.put(dataSource.getDeviceId(), jCheckBox); - + newOneFound = true; } @@ -356,36 +357,36 @@ final public class FiltersPanel extends JPanel { } catch (TskCoreException tskCoreException) { logger.log(Level.SEVERE, "There was a error loading the datasources for the case.", tskCoreException); } - - if(newOneFound) { + + if (newOneFound) { devicesListPane.revalidate(); } - + return newOneFound; } - + /** - * Given a list of subFilters, set the states of the panel controls + * Given a list of subFilters, set the states of the panel controls * accordingly. - * + * * @param commFilter Contains a list of subFilters */ public void setFilters(CommunicationsFilter commFilter) { List subFilters = commFilter.getAndFilters(); subFilters.forEach(subFilter -> { - if( subFilter instanceof DeviceFilter ) { - setDeviceFilter((DeviceFilter)subFilter); - } else if( subFilter instanceof AccountTypeFilter) { + if (subFilter instanceof DeviceFilter) { + setDeviceFilter((DeviceFilter) subFilter); + } else if (subFilter instanceof AccountTypeFilter) { setAccountTypeFilter((AccountTypeFilter) subFilter); - } else if (subFilter instanceof MostRecentFilter ) { - setMostRecentFilter((MostRecentFilter)subFilter); + } else if (subFilter instanceof MostRecentFilter) { + setMostRecentFilter((MostRecentFilter) subFilter); } }); } - + /** * Sets the state of the device filter check boxes - * + * * @param deviceFilter Selected devices */ private void setDeviceFilter(DeviceFilter deviceFilter) { @@ -394,23 +395,24 @@ final public class FiltersPanel extends JPanel { cb.setSelected(deviceIDs.contains(type)); }); } - - /** - * Set the state of the account type checkboxes to match the passed in filter - * + + /** + * Set the state of the account type checkboxes to match the passed in + * filter + * * @param typeFilter Account Types to be selected */ - private void setAccountTypeFilter(AccountTypeFilter typeFilter){ - + private void setAccountTypeFilter(AccountTypeFilter typeFilter) { + accountTypeMap.forEach((type, cb) -> { cb.setSelected(typeFilter.getAccountTypes().contains(type)); }); } - + /** - * Set up the startDatePicker and startCheckBox based on the passed in + * Set up the startDatePicker and startCheckBox based on the passed in * DateControlState. - * + * * @param state new control state */ private void setStartDateControlState(DateControlState state) { @@ -418,11 +420,11 @@ final public class FiltersPanel extends JPanel { startCheckBox.setSelected(state.isEnabled()); startDatePicker.setEnabled(state.isEnabled()); } - + /** - * Set up the endDatePicker and endCheckBox based on the passed in - * DateControlState. - * + * Set up the endDatePicker and endCheckBox based on the passed in + * DateControlState. + * * @param state new control state */ private void setEndDateControlState(DateControlState state) { @@ -430,25 +432,25 @@ final public class FiltersPanel extends JPanel { endCheckBox.setSelected(state.isEnabled()); endDatePicker.setEnabled(state.isEnabled()); } - + /** * Sets the state of the most recent UI controls based on the current values * in MostRecentFilter. - * + * * @param filter The MostRecentFilter state to be set */ private void setMostRecentFilter(MostRecentFilter filter) { int limit = filter.getLimit(); - if(limit > 0) { + if (limit > 0) { limitComboBox.setSelectedItem(filter.getLimit()); } else { limitComboBox.setSelectedItem("All"); } } - + @Subscribe void filtersBack(CVTEvents.StateChangeEvent event) { - if(event.getCommunicationsState().getCommunicationsFilter() != null){ + if (event.getCommunicationsState().getCommunicationsFilter() != null) { setFilters(event.getCommunicationsState().getCommunicationsFilter()); setStartDateControlState(event.getCommunicationsState().getStartControlState()); setEndDateControlState(event.getCommunicationsState().getEndControlState()); @@ -828,7 +830,7 @@ final public class FiltersPanel extends JPanel { /** * Get an instance of CommunicationsFilters base on the current panel state. - * + * * @return an instance of CommunicationsFilter */ protected CommunicationsFilter getFilter() { @@ -877,36 +879,37 @@ final public class FiltersPanel extends JPanel { */ private DateRangeFilter getDateRangeFilter() { ZoneId zone = Utils.getUserPreferredZoneId(); - - return new DateRangeFilter( startCheckBox.isSelected() ? startDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0, - endCheckBox.isSelected() ? endDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0); + + return new DateRangeFilter(startCheckBox.isSelected() ? startDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0, + endCheckBox.isSelected() ? endDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0); } - + /** - * Get a MostRecentFilter that based on the current state of the ui controls. - * - * @return A new instance of MostRecentFilter + * Get a MostRecentFilter that based on the current state of the ui + * controls. + * + * @return A new instance of MostRecentFilter */ private MostRecentFilter getMostRecentFilter() { - String value = (String)limitComboBox.getSelectedItem(); - if(value.trim().equalsIgnoreCase("all")){ + String value = (String) limitComboBox.getSelectedItem(); + if (value.trim().equalsIgnoreCase("all")) { return new MostRecentFilter(-1); - } else{ + } else { try { int count = Integer.parseInt(value); return new MostRecentFilter(count); - } catch(NumberFormatException ex) { + } catch (NumberFormatException ex) { return null; } } } - + private DateControlState getStartControlState() { - return new DateControlState (startDatePicker.getDate(), startCheckBox.isSelected()); + return new DateControlState(startDatePicker.getDate(), startCheckBox.isSelected()); } - + private DateControlState getEndControlState() { - return new DateControlState (endDatePicker.getDate(), endCheckBox.isSelected()); + return new DateControlState(endDatePicker.getDate(), endCheckBox.isSelected()); } /** @@ -940,32 +943,32 @@ final public class FiltersPanel extends JPanel { private void setAllSelected(Map map, boolean selected) { map.values().forEach(box -> box.setSelected(selected)); } - + /** * initalize the DateTimePickers by grabbing the earliest and latest time * from the autopsy db. */ private void initalizeDateTimeFilters() { Case currentCase = null; - try{ + try { currentCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.INFO, "Tried to intialize communication filters date range filters without an open case, using default values"); + } catch (NoCurrentCaseException ex) { + logger.log(Level.INFO, "Tried to intialize communication filters date range filters without an open case, using default values"); } - - if(currentCase == null) { + + if (currentCase == null) { setDateTimeFiltersToDefault(); openCase = null; return; } - - if(!currentCase.equals(openCase)) { + + if (!currentCase.equals(openCase)) { setDateTimeFiltersToDefault(); openCase = currentCase; (new DatePickerWorker()).execute(); } } - + private void setDateTimeFiltersToDefault() { startDatePicker.setDate(LocalDate.now().minusWeeks(3)); endDatePicker.setDate(LocalDate.now()); @@ -1002,46 +1005,47 @@ final public class FiltersPanel extends JPanel { }//GEN-LAST:event_limitComboBoxActionPerformed /** - * A class to wrap the state of the date controls that consist of a date picker - * and a checkbox. - * + * A class to wrap the state of the date controls that consist of a date + * picker and a checkbox. + * */ final class DateControlState { + private final LocalDate date; private final boolean enabled; - + /** * Wraps the state of the date controls that consist of a date picker * and checkbox - * - * @param date LocalDate value of the datepicker + * + * @param date LocalDate value of the datepicker * @param enabled State of the checkbox */ protected DateControlState(LocalDate date, boolean enabled) { this.date = date; this.enabled = enabled; } - + /** - * Returns the given LocalDate from the datepicker - * + * Returns the given LocalDate from the datepicker + * * @return Current state LocalDate */ - public LocalDate getDate(){ + public LocalDate getDate() { return date; } - + /** * Returns the given state of the datepicker checkbox - * + * * @return boolean, whether or not the datepicker was enabled */ public boolean isEnabled() { return enabled; } - + } - + // Variables declaration - do not modify//GEN-BEGIN:variables private final javax.swing.JPanel accountTypeListPane = new javax.swing.JPanel(); private final javax.swing.JLabel accountTypeRequiredLabel = new javax.swing.JLabel(); @@ -1078,59 +1082,59 @@ final public class FiltersPanel extends JPanel { private final javax.swing.JButton unCheckAllDevicesButton = new javax.swing.JButton(); // End of variables declaration//GEN-END:variables - /** - * This class is a small panel that appears to just be a checkbox but - * adds the functionality of being able to show an icon between the checkbox - * and label. + * This class is a small panel that appears to just be a checkbox but adds + * the functionality of being able to show an icon between the checkbox and + * label. */ - final class CheckBoxIconPanel extends JPanel{ + final class CheckBoxIconPanel extends JPanel { + private final JCheckBox checkbox; private final JLabel label; - + /** * Creates a JPanel instance with the specified label and image. - * + * * @param labelText The text to be displayed by the checkbox label. - * @param image The image to be dispayed by the label. + * @param image The image to be dispayed by the label. */ private CheckBoxIconPanel(String labelText, Icon image) { checkbox = new JCheckBox(); label = new JLabel(labelText); label.setIcon(image); setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - + add(checkbox); add(label); add(Box.createHorizontalGlue()); } - + /** * Sets the state of the checkbox. - * + * * @param selected true if the button is selected, otherwise false */ void setSelected(boolean selected) { checkbox.setSelected(selected); } - + @Override public void setEnabled(boolean enabled) { checkbox.setEnabled(enabled); } - + /** * Returns the instance of the JCheckBox. - * + * * @return JCheckbox instance */ JCheckBox getCheckBox() { return checkbox; } - + /** * Adds an ItemListener to the checkbox. - * + * * @param l the ItemListener to be added. */ void addItemListener(ItemListener l) { @@ -1139,8 +1143,8 @@ final public class FiltersPanel extends JPanel { } /** - * A simple class that implements CaseDbAccessQueryCallback. Can be used - * as an anonymous innerclass with the CaseDbAccessManager select function. + * A simple class that implements CaseDbAccessQueryCallback. Can be used as + * an anonymous innerclass with the CaseDbAccessManager select function. */ class FilterPanelQueryCallback implements CaseDbAccessQueryCallback { @@ -1149,7 +1153,7 @@ final public class FiltersPanel extends JPanel { // Subclasses can implement their own process function. } } - + final class DatePickerWorker extends SwingWorker, Void> { @Override @@ -1204,4 +1208,4 @@ final public class FiltersPanel extends JPanel { } } -} \ No newline at end of file +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index eeacf491bf..0419bc362f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -54,6 +54,7 @@ import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractF import org.sleuthkit.autopsy.datamodel.BaseChildFactory.NoSuchEventBusException; import org.sleuthkit.autopsy.datamodel.BaseChildFactory.RefreshKeysEvent; import org.sleuthkit.autopsy.ingest.IngestManager; +import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.CONTENT_CHANGED; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException; import org.sleuthkit.autopsy.texttranslation.TextTranslationService; @@ -77,6 +78,7 @@ public abstract class AbstractAbstractFileNode extends A private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE, Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_DELETED, Case.Events.CR_COMMENT_CHANGED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(CONTENT_CHANGED); /** * @param abstractFile file to wrap @@ -89,7 +91,7 @@ public abstract class AbstractAbstractFileNode extends A // If this is an archive file we will listen for ingest events // that will notify us when new content has been identified. if (FileTypeExtensions.getArchiveExtensions().contains(ext)) { - IngestManager.getInstance().addIngestModuleEventListener(weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index adc5a34fa7..5ee741a496 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; +import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.CONTENT_CHANGED; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; @@ -190,10 +191,12 @@ public class DeletedContent implements AutopsyVisitableItem { Case.Events.DATA_SOURCE_ADDED, Case.Events.CURRENT_CASE ); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(CONTENT_CHANGED); DeletedContentsChildrenObservable() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 7285b2cb8d..a6652679ec 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; +import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.CONTENT_CHANGED; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -63,6 +64,9 @@ public class EmailExtracted implements AutopsyVisitableItem { private static final String MAIL_ACCOUNT = NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.mailAccount.text"); private static final String MAIL_FOLDER = NbBundle.getMessage(EmailExtracted.class, "EmailExtracted.mailFolder.text"); private static final String MAIL_PATH_SEPARATOR = "/"; + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); + /** * Parse the path of the email msg to get the account name and folder in * which the email is contained. @@ -88,37 +92,35 @@ public class EmailExtracted implements AutopsyVisitableItem { private final EmailResults emailResults; private final long filteringDSObjId; // 0 if not filtering/grouping by data source - - /** * Constructor - * + * * @param skCase Case DB */ public EmailExtracted(SleuthkitCase skCase) { this(skCase, 0); } - + /** * Constructor - * - * @param skCase Case DB - * @param objId Object id of the data source - * - */ + * + * @param skCase Case DB + * @param objId Object id of the data source + * + */ public EmailExtracted(SleuthkitCase skCase, long objId) { this.skCase = skCase; this.filteringDSObjId = objId; emailResults = new EmailResults(); } - @Override public T accept(AutopsyItemVisitor visitor) { return visitor.visit(this); } + private final class EmailResults extends Observable { - + // NOTE: the map can be accessed by multiple worker threads and needs to be synchronized private final Map>> accounts = new LinkedHashMap<>(); @@ -161,7 +163,7 @@ public class EmailExtracted implements AutopsyVisitableItem { + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS if (filteringDSObjId > 0) { - query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; + query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; } try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { @@ -307,8 +309,8 @@ public class EmailExtracted implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); emailResults.update(); emailResults.addObserver(this); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index a51e36eb87..4ac4413e47 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -26,6 +26,7 @@ import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; import java.util.List; +import java.util.Set; import java.util.logging.Level; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; @@ -59,14 +60,16 @@ import org.sleuthkit.datamodel.TskException; */ public class ExtractedContent implements AutopsyVisitableItem { - private SleuthkitCase skCase; // set to null after case has been closed - private Blackboard blackboard; + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); public static final String NAME = NbBundle.getMessage(RootNode.class, "ExtractedContentNode.name.text"); private final long filteringDSObjId; // 0 if not filtering/grouping by data source + private SleuthkitCase skCase; // set to null after case has been closed + private Blackboard blackboard; /** - * Constructs extracted content object - * + * Constructs extracted content object + * * @param skCase Case DB */ public ExtractedContent(SleuthkitCase skCase) { @@ -74,17 +77,17 @@ public class ExtractedContent implements AutopsyVisitableItem { } /** - * Constructs extracted content object - * + * Constructs extracted content object + * * @param skCase Case DB - * @param objId Object id of the parent datasource + * @param objId Object id of the parent datasource */ public ExtractedContent(SleuthkitCase skCase, long objId) { this.skCase = skCase; this.filteringDSObjId = objId; this.blackboard = skCase.getBlackboard(); } - + @Override public T accept(AutopsyItemVisitor visitor) { return visitor.visit(this); @@ -144,8 +147,8 @@ public class ExtractedContent implements AutopsyVisitableItem { return filePath + "gps-search.png"; //NON-NLS } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID()) { return filePath + "installed.png"; //NON-NLS - } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() || - typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED.getTypeID()) { + } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() + || typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED.getTypeID()) { return filePath + "encrypted-file.png"; //NON-NLS } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) { return filePath + "mismatch-16.png"; //NON-NLS @@ -235,7 +238,7 @@ public class ExtractedContent implements AutopsyVisitableItem { doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT)); doNotShow.add(new BlackboardArtifact.Type(TSK_ACCOUNT)); doNotShow.add(new BlackboardArtifact.Type(TSK_DATA_SOURCE_USAGE)); - doNotShow.add(new BlackboardArtifact.Type(TSK_DOWNLOAD_SOURCE) ); + doNotShow.add(new BlackboardArtifact.Type(TSK_DOWNLOAD_SOURCE)); } private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { @@ -288,8 +291,8 @@ public class ExtractedContent implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); } @@ -305,10 +308,10 @@ public class ExtractedContent implements AutopsyVisitableItem { protected boolean createKeys(List list) { if (skCase != null) { try { - List types = (filteringDSObjId > 0) ? - blackboard.getArtifactTypesInUse(filteringDSObjId) : - skCase.getArtifactTypesInUse() ; - + List types = (filteringDSObjId > 0) + ? blackboard.getArtifactTypesInUse(filteringDSObjId) + : skCase.getArtifactTypesInUse(); + types.removeAll(doNotShow); Collections.sort(types, new Comparator() { @@ -370,9 +373,9 @@ public class ExtractedContent implements AutopsyVisitableItem { // a performance increase might be had by adding a // "getBlackboardArtifactCount()" method to skCase try { - this.childCount = (filteringDSObjId > 0) ? - blackboard.getArtifactsCount(type.getTypeID(), filteringDSObjId) : - skCase.getBlackboardArtifactsTypeCount(type.getTypeID()); + this.childCount = (filteringDSObjId > 0) + ? blackboard.getArtifactsCount(type.getTypeID(), filteringDSObjId) + : skCase.getBlackboardArtifactsTypeCount(type.getTypeID()); } catch (TskException ex) { Logger.getLogger(TypeNode.class.getName()) .log(Level.WARNING, "Error getting child count", ex); //NON-NLS @@ -480,8 +483,8 @@ public class ExtractedContent implements AutopsyVisitableItem { @Override protected void onAdd() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java index 9cceeb5a29..172c11c037 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2013-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. @@ -104,7 +104,7 @@ public class FileSize implements AutopsyVisitableItem { this.skCase = skCase; this.filteringDSObjId = dsObjId; } - + @Override public T accept(AutopsyItemVisitor visitor) { return visitor.visit(this); @@ -117,6 +117,7 @@ public class FileSize implements AutopsyVisitableItem { long filteringDataSourceObjId() { return this.filteringDSObjId; } + /* * Root node. Children are nodes for specific sizes. */ @@ -169,7 +170,7 @@ public class FileSize implements AutopsyVisitableItem { public static class FileSizeRootChildren extends ChildFactory { private SleuthkitCase skCase; - private final long datasourceObjId; + private final long datasourceObjId; private Observable notifier; public FileSizeRootChildren(SleuthkitCase skCase, long datasourceObjId) { @@ -185,10 +186,12 @@ public class FileSize implements AutopsyVisitableItem { private static final class FileSizeRootChildrenObservable extends Observable { private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.CURRENT_CASE); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.CONTENT_CHANGED); FileSizeRootChildrenObservable() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); } @@ -282,9 +285,10 @@ public class FileSize implements AutopsyVisitableItem { * * @param skCase * @param filter - * @param o Observable that provides updates when events are - * fired - * @param datasourceObjId filter by data source, if configured in user preferences + * @param o Observable that provides updates when + * events are fired + * @param datasourceObjId filter by data source, if configured in + * user preferences */ FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter, Observable o, long datasourceObjId) { super(Children.create(new FileSizeChildren(filter, skCase, o, datasourceObjId), true), Lookups.singleton(filter.getDisplayName())); @@ -379,7 +383,7 @@ public class FileSize implements AutopsyVisitableItem { this.filter = filter; this.notifier = o; this.datasourceObjId = dsObjId; - + } @Override @@ -429,15 +433,15 @@ public class FileSize implements AutopsyVisitableItem { default: throw new IllegalArgumentException("Unsupported filter type to get files by size: " + filter); //NON-NLS } - + // Ignore unallocated block files. query = query + " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType() + ")"; //NON-NLS - + // filter by datasource if indicated in case preferences if (filteringDSObjId > 0) { - query += " AND data_source_obj_id = " + filteringDSObjId; + query += " AND data_source_obj_id = " + filteringDSObjId; } - + return query; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java index 34ec74280a..19dac06410 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java @@ -53,6 +53,8 @@ import org.sleuthkit.datamodel.TskData; public final class FileTypesByExtension implements AutopsyVisitableItem { private final static Logger logger = Logger.getLogger(FileTypesByExtension.class.getName()); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.CONTENT_CHANGED); private final SleuthkitCase skCase; private final FileTypes typesRoot; @@ -72,8 +74,8 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { long filteringDataSourceObjId() { return typesRoot.filteringDataSourceObjId(); - } - + } + /** * Listens for case and ingest invest. Updates observers when events are * fired. FileType and FileTypes nodes are all listening to this. @@ -115,8 +117,8 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { } }; - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); } @@ -365,11 +367,11 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { ? " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")" : " ") + (filteringDataSourceObjId() > 0 - ? " AND data_source_obj_id = " + filteringDataSourceObjId() - : " ") + ? " AND data_source_obj_id = " + filteringDataSourceObjId() + : " ") + " AND (extension IN (" + filter.getFilter().stream() .map(String::toLowerCase) - .map(s -> "'"+StringUtils.substringAfter(s, ".")+"'") + .map(s -> "'" + StringUtils.substringAfter(s, ".") + "'") .collect(Collectors.joining(", ")) + "))"; } @@ -384,10 +386,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { /** * - * @param filter Extensions to display + * @param filter Extensions to display * @param skCase - * @param o Observable that will notify when there could be new - * data to display + * @param o Observable that will notify when there could be new + * data to display * @param nodeName */ private FileExtensionNodeChildren(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o, String nodeName) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 86cc42aa8c..0ac8f8e8b0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -61,7 +61,7 @@ import org.sleuthkit.datamodel.TskData; public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { private final static Logger logger = Logger.getLogger(FileTypesByMimeType.class.getName()); - + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private final SleuthkitCase skCase; /** * The nodes of this tree will be determined dynamically by the mimetypes @@ -99,9 +99,9 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() + "," + TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.ordinal() + "," + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal() - + (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal())) + + (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal())) + "))" - + ( (filteringDataSourceObjId() > 0) ? " AND data_source_obj_id = " + this.filteringDataSourceObjId() : " ") + + ((filteringDataSourceObjId() > 0) ? " AND data_source_obj_id = " + this.filteringDataSourceObjId() : " ") + (hideKnownFilesInViewsTree() ? (" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")") : ""); } @@ -180,7 +180,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi } } }; - IngestManager.getInstance().addIngestJobEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); populateHashMap(); } @@ -193,7 +193,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi long filteringDataSourceObjId() { return typesRoot.filteringDataSourceObjId(); } - + /** * Method to check if the node in question is a ByMimeTypeNode which is * empty. diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index 03c72d2d2e..3a9a87c1e4 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-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. @@ -61,28 +61,29 @@ public class HashsetHits implements AutopsyVisitableItem { private static final String HASHSET_HITS = BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getLabel(); private static final String DISPLAY_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(); private static final Logger logger = Logger.getLogger(HashsetHits.class.getName()); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); private SleuthkitCase skCase; private final HashsetResults hashsetResults; private final long filteringDSObjId; // 0 if not filtering/grouping by data source - - + /** * Constructor - * - * @param skCase Case DB - * - */ + * + * @param skCase Case DB + * + */ public HashsetHits(SleuthkitCase skCase) { this(skCase, 0); } - + /** * Constructor - * - * @param skCase Case DB - * @param objId Object id of the data source - * - */ + * + * @param skCase Case DB + * @param objId Object id of the data source + * + */ public HashsetHits(SleuthkitCase skCase, long objId) { this.skCase = skCase; this.filteringDSObjId = objId; @@ -118,7 +119,7 @@ public class HashsetHits implements AutopsyVisitableItem { } Set getArtifactIds(String hashSetName) { - synchronized (hashSetHitsMap) { + synchronized (hashSetHitsMap) { return hashSetHitsMap.get(hashSetName); } } @@ -141,9 +142,9 @@ public class HashsetHits implements AutopsyVisitableItem { + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS if (filteringDSObjId > 0) { - query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; + query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; } - + try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { ResultSet resultSet = dbQuery.getResultSet(); synchronized (hashSetHitsMap) { @@ -275,8 +276,8 @@ public class HashsetHits implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); hashsetResults.update(); hashsetResults.addObserver(this); @@ -379,7 +380,7 @@ public class HashsetHits implements AutopsyVisitableItem { private String hashsetName; private Map artifactHits = new HashMap<>(); - + private HitFactory(String hashsetName) { super(hashsetName); this.hashsetName = hashsetName; @@ -396,7 +397,7 @@ public class HashsetHits implements AutopsyVisitableItem { } @Override - protected Node createNodeForKey(BlackboardArtifact key) { + protected Node createNodeForKey(BlackboardArtifact key) { return new BlackboardArtifactNode(key); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java index da82c315b5..12f2340f33 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; import javax.swing.Action; import org.apache.commons.lang3.tuple.Pair; @@ -59,6 +60,7 @@ import org.sleuthkit.datamodel.Tag; public class ImageNode extends AbstractContentNode { private static final Logger logger = Logger.getLogger(ImageNode.class.getName()); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.CONTENT_CHANGED); /** * Helper so that the display name and the name used in building the path @@ -84,7 +86,7 @@ public class ImageNode extends AbstractContentNode { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hard-drive-icon.jpg"); //NON-NLS // Listen for ingest events so that we can detect new added files (e.g. carved) - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); // Listen for case events so that we can detect when case is closed Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index 482ebf1558..b12ceff6ae 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -57,27 +57,29 @@ public class InterestingHits implements AutopsyVisitableItem { .getMessage(InterestingHits.class, "InterestingHits.interestingItems.text"); private static final String DISPLAY_NAME = NbBundle.getMessage(InterestingHits.class, "InterestingHits.displayName.text"); private static final Logger logger = Logger.getLogger(InterestingHits.class.getName()); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); private SleuthkitCase skCase; private final InterestingResults interestingResults = new InterestingResults(); private final long filteringDSObjId; // 0 if not filtering/grouping by data source /** * Constructor - * - * @param skCase Case DB - * - */ + * + * @param skCase Case DB + * + */ public InterestingHits(SleuthkitCase skCase) { this(skCase, 0); } - + /** * Constructor - * - * @param skCase Case DB - * @param objId Object id of the data source - * - */ + * + * @param skCase Case DB + * @param objId Object id of the data source + * + */ public InterestingHits(SleuthkitCase skCase, long objId) { this.skCase = skCase; this.filteringDSObjId = objId; @@ -132,7 +134,7 @@ public class InterestingHits implements AutopsyVisitableItem { + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS if (filteringDSObjId > 0) { - query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; + query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; } try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { @@ -217,17 +219,17 @@ public class InterestingHits implements AutopsyVisitableItem { if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { /** * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked - * out. Currently, remote events may be received for a case - * that is already closed. + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. */ try { Case.getCurrentCaseThrows(); /** - * Even with the check above, it is still possible that - * the case will be closed in a different thread before - * this code executes. If that happens, it is possible - * for the event to have a null oldValue. + * Even with the check above, it is still possible that the + * case will be closed in a different thread before this + * code executes. If that happens, it is possible for the + * event to have a null oldValue. */ ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); if (null != eventData && (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() @@ -243,9 +245,9 @@ public class InterestingHits implements AutopsyVisitableItem { || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked - * out. Currently, remote events may be received for a case - * that is already closed. + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. */ try { Case.getCurrentCaseThrows(); @@ -266,8 +268,8 @@ public class InterestingHits implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); interestingResults.update(); interestingResults.addObserver(this); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index 655f0c1973..4f78a6da34 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -62,7 +62,8 @@ import org.sleuthkit.datamodel.TskCoreException; public class KeywordHits implements AutopsyVisitableItem { private static final Logger logger = Logger.getLogger(KeywordHits.class.getName()); - + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); @NbBundle.Messages("KeywordHits.kwHits.text=Keyword Hits") private static final String KEYWORD_HITS = KeywordHits_kwHits_text(); @NbBundle.Messages("KeywordHits.simpleLiteralSearch.text=Single Literal Keyword Search") @@ -155,25 +156,22 @@ public class KeywordHits implements AutopsyVisitableItem { Collections.sort(names, new Comparator() { @Override - public int compare(String o1, String o2) { + public int compare(String o1, String o2) { // ideally, they would not be hard coded, but this module // doesn't know about Keyword Search NBM if (o1.startsWith("Single Literal Keyword Search")) { return -1; - } - else if (o2.startsWith("Single Literal Keyword Search")) { + } else if (o2.startsWith("Single Literal Keyword Search")) { return 1; - } - else if (o1.startsWith("Single Regular Expression Search")) { + } else if (o1.startsWith("Single Regular Expression Search")) { return -1; - } - else if (o2.startsWith("Single Regular Expression Search")) { + } else if (o2.startsWith("Single Regular Expression Search")) { return 1; } return o1.compareTo(o2); } }); - + return names; } } @@ -501,8 +499,8 @@ public class KeywordHits implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); keywordResults.update(); super.addNotify(); @@ -529,8 +527,9 @@ public class KeywordHits implements AutopsyVisitableItem { } private abstract class KWHitsNodeBase extends DisplayableItemNode implements Observer { + private String displayName; - + private KWHitsNodeBase(Children children, Lookup lookup, String displayName) { super(children, lookup); this.displayName = displayName; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 2dfc02678b..8dd7805358 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -54,9 +54,10 @@ public class Tags implements AutopsyVisitableItem { // by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren // override of Children.Keys.createNodes(). - private final TagResults tagResults = new TagResults(); private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS + private final TagResults tagResults = new TagResults(); private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private final long filteringDSObjId; // 0 if not filtering/grouping by data source @@ -223,8 +224,7 @@ public class Tags implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); tagResults.update(); tagResults.addObserver(this); @@ -233,7 +233,6 @@ public class Tags implements AutopsyVisitableItem { @Override protected void removeNotify() { IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); tagResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java index 307013136f..0eacf5f699 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java @@ -23,6 +23,7 @@ import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; import javax.swing.Action; import org.apache.commons.lang3.tuple.Pair; @@ -52,6 +53,7 @@ import org.sleuthkit.datamodel.Tag; public class VolumeNode extends AbstractContentNode { private static final Logger logger = Logger.getLogger(VolumeNode.class.getName()); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.CONTENT_CHANGED); /** * Helper so that the display name and the name used in building the path @@ -81,7 +83,7 @@ public class VolumeNode extends AbstractContentNode { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/vol-icon.png"); //NON-NLS // Listen for ingest events so that we can detect new added files (e.g. carved) - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); // Listen for case events so that we can detect when case is closed Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java index a75bca2972..0e3a4e971d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java @@ -89,16 +89,20 @@ final public class Accounts implements AutopsyVisitableItem { private static final Logger LOGGER = Logger.getLogger(Accounts.class.getName()); private static final String ICON_BASE_PATH = "/org/sleuthkit/autopsy/images/"; //NON-NLS - + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); + @NbBundle.Messages("AccountsRootNode.name=Accounts") final public static String NAME = Bundle.AccountsRootNode_name(); private SleuthkitCase skCase; private final long filteringDSObjId; // 0 if not filtering/grouping by data source - + private final EventBus reviewStatusBus = new EventBus("ReviewStatusBus"); - /* Should rejected accounts be shown in the accounts section of the tree. */ + /* + * Should rejected accounts be shown in the accounts section of the tree. + */ private boolean showRejected = false; //NOPMD redundant initializer private final RejectAccounts rejectActionInstance; @@ -117,7 +121,7 @@ final public class Accounts implements AutopsyVisitableItem { * Constructor * * @param skCase The SleuthkitCase object to use for db queries. - * @param objId Object id of the data source + * @param objId Object id of the data source */ public Accounts(SleuthkitCase skCase, long objId) { this.skCase = skCase; @@ -126,8 +130,7 @@ final public class Accounts implements AutopsyVisitableItem { this.rejectActionInstance = new RejectAccounts(); this.approveActionInstance = new ApproveAccounts(); } - - + @Override public T accept(AutopsyItemVisitor visitor) { return visitor.visit(this); @@ -147,14 +150,14 @@ final public class Accounts implements AutopsyVisitableItem { /** * Returns the clause to filter artifacts by data source. * - * @return A clause that will or will not filter artifacts by datasource - * based on the CasePreferences groupItemsInTreeByDataSource setting + * @return A clause that will or will not filter artifacts by datasource + * based on the CasePreferences groupItemsInTreeByDataSource setting */ private String getFilterByDataSourceClause() { if (filteringDSObjId > 0) { return " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId + " "; } - + return " "; } @@ -320,14 +323,14 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected boolean createKeys(List list) { - String accountTypesInUseQuery = - "SELECT DISTINCT blackboard_attributes.value_text as account_type " + String accountTypesInUseQuery + = "SELECT DISTINCT blackboard_attributes.value_text as account_type " + " FROM blackboard_artifacts " //NON-NLS + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS + " WHERE blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() + getFilterByDataSourceClause(); - - try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery ); + + try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery); ResultSet resultSet = executeQuery.getResultSet()) { while (resultSet.next()) { String accountType = resultSet.getString("account_type"); @@ -368,8 +371,8 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); super.addNotify(); refresh(true); @@ -439,8 +442,8 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); super.addNotify(); } @@ -455,8 +458,8 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected boolean createKeys(List list) { - String query = - "SELECT blackboard_artifacts.artifact_id " //NON-NLS + String query + = "SELECT blackboard_artifacts.artifact_id " //NON-NLS + " FROM blackboard_artifacts " //NON-NLS + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS @@ -603,8 +606,8 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); super.addNotify(); } @@ -727,8 +730,8 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); super.addNotify(); } @@ -755,8 +758,8 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected boolean createKeys(List list) { - String query = - "SELECT blackboard_artifacts.obj_id," //NON-NLS + String query + = "SELECT blackboard_artifacts.obj_id," //NON-NLS + " solr_attribute.value_text AS solr_document_id, "; //NON-NLS if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) { query += " string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, " //NON-NLS @@ -833,8 +836,8 @@ final public class Accounts implements AutopsyVisitableItem { "# {0} - number of children", "Accounts.ByFileNode.displayName=By File ({0})"}) private void updateDisplayName() { - String query = - "SELECT count(*) FROM ( SELECT count(*) AS documents " + String query + = "SELECT count(*) FROM ( SELECT count(*) AS documents " + " FROM blackboard_artifacts " //NON-NLS + " LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id " //NON-NLS + " AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() //NON-NLS @@ -842,7 +845,7 @@ final public class Accounts implements AutopsyVisitableItem { + " AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() //NON-NLS + " AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() + "'" //NON-NLS + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS - + getFilterByDataSourceClause() + + getFilterByDataSourceClause() + getRejectedArtifactFilterClause() + " GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo"; try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query); @@ -941,8 +944,8 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(pcl); - IngestManager.getInstance().addIngestModuleEventListener(pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); super.addNotify(); } @@ -972,14 +975,14 @@ final public class Accounts implements AutopsyVisitableItem { RangeMap binRanges = TreeRangeMap.create(); - String query = - "SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, " //NON-NLS + String query + = "SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, " //NON-NLS + " COUNT(blackboard_artifacts.artifact_id) AS count " //NON-NLS + " FROM blackboard_artifacts " //NON-NLS + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id" //NON-NLS + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() //NON-NLS - + getFilterByDataSourceClause() + + getFilterByDataSourceClause() + getRejectedArtifactFilterClause() + " GROUP BY BIN " //NON-NLS + " ORDER BY BIN "; //NON-NLS @@ -1040,13 +1043,13 @@ final public class Accounts implements AutopsyVisitableItem { "# {0} - number of children", "Accounts.ByBINNode.displayName=By BIN ({0})"}) private void updateDisplayName() { - String query = - "SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs " //NON-NLS + String query + = "SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs " //NON-NLS + " FROM blackboard_artifacts " //NON-NLS + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id" //NON-NLS + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() //NON-NLS - + getFilterByDataSourceClause() + + getFilterByDataSourceClause() + getRejectedArtifactFilterClause(); //NON-NLS try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query); ResultSet resultSet = results.getResultSet();) { @@ -1335,14 +1338,14 @@ final public class Accounts implements AutopsyVisitableItem { @Override protected boolean createKeys(List list) { - String query = - "SELECT blackboard_artifacts.artifact_id " //NON-NLS + String query + = "SELECT blackboard_artifacts.artifact_id " //NON-NLS + " FROM blackboard_artifacts " //NON-NLS + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() //NON-NLS + " AND blackboard_attributes.value_text >= '" + bin.getBINStart() + "' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + "'" //NON-NLS - + getFilterByDataSourceClause() + + getFilterByDataSourceClause() + getRejectedArtifactFilterClause() + " ORDER BY blackboard_attributes.value_text"; //NON-NLS try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query); @@ -1383,7 +1386,9 @@ final public class Accounts implements AutopsyVisitableItem { final public class BINNode extends DisplayableItemNode { - /** Creates the nodes for the credit card numbers */ + /** + * Creates the nodes for the credit card numbers + */ private final BinResult bin; private BINNode(BinResult bin) { @@ -1407,14 +1412,14 @@ final public class Accounts implements AutopsyVisitableItem { } private void updateDisplayName() { - String query = - "SELECT count(blackboard_artifacts.artifact_id ) AS count" //NON-NLS + String query + = "SELECT count(blackboard_artifacts.artifact_id ) AS count" //NON-NLS + " FROM blackboard_artifacts " //NON-NLS + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() //NON-NLS + " AND blackboard_attributes.value_text >= '" + bin.getBINStart() + "' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + "'" //NON-NLS - + getFilterByDataSourceClause() + + getFilterByDataSourceClause() + getRejectedArtifactFilterClause(); try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query); ResultSet resultSet = results.getResultSet();) { @@ -1549,7 +1554,9 @@ final public class Accounts implements AutopsyVisitableItem { return true; } - /** The number of accounts with this BIN */ + /** + * The number of accounts with this BIN + */ private final long count; private final BINRange binRange; @@ -1702,10 +1709,10 @@ final public class Accounts implements AutopsyVisitableItem { reviewStatusBus.post(new ReviewStatusChangeEvent(Collections.emptySet(), null)); } } - + /** * Update the user interface to show or hide rejected artifacts. - * + * * @param showRejected Show rejected artifacts? Yes if true; otherwise no. */ public void setShowRejected(boolean showRejected) { @@ -1726,8 +1733,10 @@ final public class Accounts implements AutopsyVisitableItem { @Override public void actionPerformed(ActionEvent e) { - /* get paths for selected nodes to reselect after applying review - * status change */ + /* + * get paths for selected nodes to reselect after applying review + * status change + */ List selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream() .map(node -> { String[] createPath; @@ -1746,9 +1755,11 @@ final public class Accounts implements AutopsyVisitableItem { : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1)); createPath = NodeOp.createPath(sibling, null); } else { - /* if there are no other siblings to select, + /* + * if there are no other siblings to select, * just return null, but note we need to filter - * this out of stream below */ + * this out of stream below + */ return null; } } else { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 280ccd3c3a..42d285ef65 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -85,7 +85,6 @@ import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.datamodel.ViewsNode; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; import org.sleuthkit.autopsy.datamodel.accounts.BINRange; -import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -128,7 +127,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); //Hook into the JTree and pre-expand the Views Node and Results node when a user //expands an item in the tree that makes these nodes visible. - ((ExpansionBeanTreeView )getTree()).addTreeExpansionListener(new TreeExpansionListener() { + ((ExpansionBeanTreeView) getTree()).addTreeExpansionListener(new TreeExpansionListener() { @Override public void treeExpanded(TreeExpansionEvent event) { //Bail immediately if we are not in the Group By view. @@ -238,8 +237,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE, Case.Events.DATA_SOURCE_ADDED), this); this.em.addPropertyChangeListener(this); - IngestManager.getInstance().addIngestJobEventListener(this); - IngestManager.getInstance().addIngestModuleEventListener(this); } public void setDirectoryListingActive() { @@ -799,10 +796,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } // change in node selection else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) { respondSelection((Node[]) event.getOldValue(), (Node[]) event.getNewValue()); - } else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { - // nothing to do here. - // all nodes should be listening for these events and update accordingly. - } + } } } diff --git a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java index 4200620749..29ecb29844 100644 --- a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java +++ b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java @@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.imagewriter; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.EnumSet; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -44,18 +46,19 @@ import org.sleuthkit.datamodel.TskCoreException; /** * The ImageWriter class is used to complete VHD copies created from local disks - * after the ingest process completes. The AddImageTask for this data source must have included - * a non-empty imageWriterPath parameter to enable Image Writer. - * + * after the ingest process completes. The AddImageTask for this data source + * must have included a non-empty imageWriterPath parameter to enable Image + * Writer. + * * Most of the cancellation/cleanup is handled through ImageWriterService */ -class ImageWriter implements PropertyChangeListener{ - - private final Logger logger = Logger.getLogger(ImageWriter.class.getName()); - +class ImageWriter implements PropertyChangeListener { + + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); + private static final Logger logger = Logger.getLogger(ImageWriter.class.getName()); private final Long dataSourceId; private final ImageWriterSettings settings; - + private Long imageHandle = null; private Future finishTask = null; private ProgressHandle progressHandle = null; @@ -63,63 +66,65 @@ class ImageWriter implements PropertyChangeListener{ private boolean isCancelled = false; private boolean isStarted = false; private final Object currentTasksLock = new Object(); // Get this lock before accessing imageHandle, finishTask, progressHandle, progressUpdateTask, - // isCancelled, isStarted, or isFinished - + // isCancelled, isStarted, or isFinished + private ScheduledThreadPoolExecutor periodicTasksExecutor = null; private final boolean doUI; private SleuthkitCase caseDb = null; - + /** - * Create the Image Writer object. - * After creation, startListeners() should be called. - * @param dataSourceId + * Create the Image Writer object. After creation, startListeners() should + * be called. + * + * @param dataSourceId */ - ImageWriter(Long dataSourceId, ImageWriterSettings settings){ - this.dataSourceId = dataSourceId; + ImageWriter(Long dataSourceId, ImageWriterSettings settings) { + this.dataSourceId = dataSourceId; this.settings = settings; - doUI = RuntimeProperties.runningWithGUI(); - + doUI = RuntimeProperties.runningWithGUI(); + // We save the reference to the sleuthkit case here in case getOpenCase() is set to // null before Image Writer finishes. The user can still elect to wait for image writer // (in ImageWriterService.closeCaseResources) even though the case is closing. - try{ + try { caseDb = Case.getCurrentCaseThrows().getSleuthkitCase(); - } catch (NoCurrentCaseException ex){ + } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Unable to load case. Image writer will be cancelled."); this.isCancelled = true; } } - + /** * Add this ImageWriter object as a listener to the necessary events */ - void subscribeToEvents(){ - IngestManager.getInstance().addIngestJobEventListener(this); + void subscribeToEvents() { + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, this); } - + /** - * Deregister this object from the events. This is ok to call multiple times. + * Deregister this object from the events. This is ok to call multiple + * times. */ - void unsubscribeFromEvents(){ - IngestManager.getInstance().removeIngestJobEventListener(this); + void unsubscribeFromEvents() { + IngestManager.getInstance().removeIngestJobEventListener(this); } - + /** - * Handle the events: - * DATA_SOURCE_ANALYSIS_COMPLETED - start the finish image process and clean up after it is complete + * Handle the events: DATA_SOURCE_ANALYSIS_COMPLETED - start the finish + * image process and clean up after it is complete */ @Override public void propertyChange(PropertyChangeEvent evt) { - if(evt instanceof DataSourceAnalysisCompletedEvent){ - - DataSourceAnalysisCompletedEvent event = (DataSourceAnalysisCompletedEvent)evt; + if (evt instanceof DataSourceAnalysisCompletedEvent) { - if(event.getDataSource() != null){ + DataSourceAnalysisCompletedEvent event = (DataSourceAnalysisCompletedEvent) evt; + + if (event.getDataSource() != null) { long imageId = event.getDataSource().getId(); String name = event.getDataSource().getName(); - + // Check that the event corresponds to this datasource - if(imageId != dataSourceId){ + if (imageId != dataSourceId) { return; } new Thread(() -> { @@ -131,30 +136,30 @@ class ImageWriter implements PropertyChangeListener{ } } } - + @Messages({ - "# {0} - data source name", + "# {0} - data source name", "ImageWriter.progressBar.message=Finishing acquisition of {0} (unplug device to cancel)" }) - private void startFinishImage(String dataSourceName){ - - synchronized(currentTasksLock){ - if(isCancelled){ + private void startFinishImage(String dataSourceName) { + + synchronized (currentTasksLock) { + if (isCancelled) { return; } - + // If we've already started the finish process for this datasource, return. // Multiple DataSourceAnalysisCompletedEvent events can come from // the same image if more ingest modules are run later - if(isStarted){ + if (isStarted) { return; } - + Image image; - try{ + try { image = Case.getCurrentCaseThrows().getSleuthkitCase().getImageById(dataSourceId); imageHandle = image.getImageHandle(); - } catch (NoCurrentCaseException ex){ + } catch (NoCurrentCaseException ex) { // This exception means that getOpenCase() failed because no case was open. // This can happen when the user closes the case while ingest is ongoing - canceling // ingest fires off the DataSourceAnalysisCompletedEvent while the case is in the @@ -162,15 +167,15 @@ class ImageWriter implements PropertyChangeListener{ logger.log(Level.WARNING, String.format("Case closed before ImageWriter could start the finishing process for %s", dataSourceName)); return; - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error loading image", ex); return; } - logger.log(Level.INFO, String.format("Finishing VHD image for %s", + logger.log(Level.INFO, String.format("Finishing VHD image for %s", dataSourceName)); //NON-NLS - if(doUI){ + if (doUI) { periodicTasksExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("image-writer-progress-update-%d").build()); //NON-NLS progressHandle = ProgressHandle.createHandle(Bundle.ImageWriter_progressBar_message(dataSourceName)); progressHandle.start(100); @@ -181,138 +186,139 @@ class ImageWriter implements PropertyChangeListener{ // The added complexity here with the Future is because we absolutely need to make sure // the call to finishImageWriter returns before allowing the TSK data structures to be freed // during case close. - finishTask = Executors.newSingleThreadExecutor().submit(new Callable(){ + finishTask = Executors.newSingleThreadExecutor().submit(new Callable() { @Override - public Integer call() throws TskCoreException{ - try{ + public Integer call() throws TskCoreException { + try { int result = SleuthkitJNI.finishImageWriter(imageHandle); - + // We've decided to always update the path to the VHD, even if it wasn't finished. // This supports the case where an analyst has partially ingested a device // but has to stop before completion. They will at least have part of the image. - if(settings.getUpdateDatabasePath()){ + if (settings.getUpdateDatabasePath()) { caseDb.updateImagePath(settings.getPath(), dataSourceId); } return result; - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS return -1; } } }); - + // Setting this means that finishTask and all the UI updaters are initialized (if running UI) isStarted = true; } // Wait for finishImageWriter to complete int result = 0; - try{ + try { // The call to get() can happen multiple times if the user closes the case, which is ok result = finishTask.get(); - } catch (InterruptedException | ExecutionException ex){ + } catch (InterruptedException | ExecutionException ex) { logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS } - - synchronized(currentTasksLock){ - if(doUI){ + + synchronized (currentTasksLock) { + if (doUI) { // Some of these may be called twice if the user closes the case progressUpdateTask.cancel(true); progressHandle.finish(); periodicTasksExecutor.shutdown(); - } + } } - if(result == 0){ + if (result == 0) { logger.log(Level.INFO, String.format("Successfully finished writing VHD image for %s", dataSourceName)); //NON-NLS } else { logger.log(Level.INFO, String.format("Finished VHD image for %s with errors", dataSourceName)); //NON-NLS } } - + /** - * If a task hasn't been started yet, set the cancel flag so it can no longer - * start. - * This is intended to be used in case close so a job doesn't suddenly start - * up during cleanup. + * If a task hasn't been started yet, set the cancel flag so it can no + * longer start. This is intended to be used in case close so a job doesn't + * suddenly start up during cleanup. */ - void cancelIfNotStarted(){ - synchronized(currentTasksLock){ - if(! isStarted){ + void cancelIfNotStarted() { + synchronized (currentTasksLock) { + if (!isStarted) { isCancelled = true; } } } - + /** * Check if the finishTask process is running. - * @return true if the finish task is still going on, false if it is finished or - * never started + * + * @return true if the finish task is still going on, false if it is + * finished or never started */ - boolean jobIsInProgress(){ - synchronized(currentTasksLock){ - return((isStarted) && (! finishTask.isDone())); + boolean jobIsInProgress() { + synchronized (currentTasksLock) { + return ((isStarted) && (!finishTask.isDone())); } } - + /** - * Cancels a single job. - * Does not wait for the job to complete. Safe to call with Image Writer in any state. + * Cancels a single job. Does not wait for the job to complete. Safe to call + * with Image Writer in any state. */ - void cancelJob(){ - synchronized(currentTasksLock){ + void cancelJob() { + synchronized (currentTasksLock) { // All of the following is redundant but safe to call on a complete job isCancelled = true; - if(isStarted){ + if (isStarted) { SleuthkitJNI.cancelFinishImage(imageHandle); - + // Stop the progress bar update task. // The thread from startFinishImage will also stop it // once the task completes, but we don't have a guarantee on // when that happens. // Since we've stopped the update task, we'll stop the associated progress // bar now, too. - if(doUI){ + if (doUI) { progressUpdateTask.cancel(true); progressHandle.finish(); } - } + } } } - + /** - * Blocks while all finishImage tasks complete. - * Also makes sure the progressUpdateTask is canceled. + * Blocks while all finishImage tasks complete. Also makes sure the + * progressUpdateTask is canceled. */ - void waitForJobToFinish(){ - synchronized(currentTasksLock){ + void waitForJobToFinish() { + synchronized (currentTasksLock) { // Wait for the finish task to end - if(isStarted){ - try{ + if (isStarted) { + try { finishTask.get(); - } catch (InterruptedException | ExecutionException ex){ + } catch (InterruptedException | ExecutionException ex) { Logger.getLogger(ImageWriter.class.getName()).log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS } - if(doUI){ + if (doUI) { progressUpdateTask.cancel(true); } - } + } } } - + /** - * Task to query the Sleuthkit processing to get the percentage done. + * Task to query the Sleuthkit processing to get the percentage done. */ private final class ProgressUpdateTask implements Runnable { + final long imageHandle; final ProgressHandle progressHandle; - - ProgressUpdateTask(ProgressHandle progressHandle, long imageHandle){ + + ProgressUpdateTask(ProgressHandle progressHandle, long imageHandle) { this.imageHandle = imageHandle; this.progressHandle = progressHandle; } - + @Override public void run() { try { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index a230743a77..bdc5aa07a9 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -26,8 +26,10 @@ import java.time.ZoneId; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.TimeZone; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -117,7 +119,8 @@ import org.sleuthkit.datamodel.BlackboardArtifact; public class TimeLineController { private static final Logger LOGGER = Logger.getLogger(TimeLineController.class.getName()); - + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED, IngestManager.IngestModuleEvent.CONTENT_CHANGED); private static final ReadOnlyObjectWrapper timeZone = new ReadOnlyObjectWrapper<>(TimeZone.getDefault()); public static ZoneId getTimeZoneID() { @@ -454,8 +457,8 @@ public class TimeLineController { TimeLineController.this.showFullRange(); } else { //prompt user to pick specific event and time range - ShowInTimelineDialog showInTimelineDilaog = - (file == null) + ShowInTimelineDialog showInTimelineDilaog + = (file == null) ? new ShowInTimelineDialog(TimeLineController.this, artifact) : new ShowInTimelineDialog(TimeLineController.this, file); Optional dialogResult = showInTimelineDilaog.showAndWait(); @@ -571,8 +574,8 @@ public class TimeLineController { void showTimeLine(AbstractFile file, BlackboardArtifact artifact) { // listen for case changes (specifically images being added, and case changes). if (Case.isCaseOpen() && !listeningToAutopsy) { - IngestManager.getInstance().addIngestModuleEventListener(ingestModuleListener); - IngestManager.getInstance().addIngestJobEventListener(ingestJobListener); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, ingestModuleListener); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobListener); Case.addPropertyChangeListener(caseListener); listeningToAutopsy = true; } @@ -962,7 +965,7 @@ public class TimeLineController { //since black board artifacts or new derived content have been added, the DB is stale. Platform.runLater(() -> setEventsDBStale(true)); break; - case FILE_DONE: + default: /* * Do nothing, since we have captured all new results in * CONTENT_CHANGED and DATA_ADDED or the IngestJob listener, @@ -986,10 +989,7 @@ public class TimeLineController { Platform.runLater(() -> setEventsDBStale(true)); filteredEvents.postAutopsyEventLocally((AutopsyEvent) evt); break; - case DATA_SOURCE_ANALYSIS_STARTED: - case CANCELLED: - case COMPLETED: - case STARTED: + default: break; } } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java index 0abaebf48b..2f2440e2ce 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java @@ -22,7 +22,9 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.List; +import java.util.Set; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; @@ -35,6 +37,8 @@ import org.sleuthkit.datamodel.Content; */ public final class IngestJobRunner { + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + /** * Runs an ingest job, blocking until the job is completed. * @@ -51,7 +55,7 @@ public final class IngestJobRunner { Object ingestMonitor = new Object(); IngestJobCompletiontListener completiontListener = new IngestJobCompletiontListener(ingestMonitor); IngestManager ingestManager = IngestManager.getInstance(); - ingestManager.addIngestJobEventListener(completiontListener); + ingestManager.addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, completiontListener); try { synchronized (ingestMonitor) { IngestJobStartResult jobStartResult = ingestManager.beginIngestJob(dataSources, settings); @@ -111,5 +115,5 @@ public final class IngestJobRunner { } } } - + } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 4bade61c1c..48b86025af 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -142,6 +142,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen ControlEventType.SHUTDOWN.toString(), Event.CANCEL_JOB.toString(), Event.REPROCESS_JOB.toString()})); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final long JOB_STATUS_EVENT_INTERVAL_SECONDS = 10; private static final String JOB_STATUS_PUBLISHING_THREAD_NAME = "AIM-job-status-event-publisher-%d"; private static final long MAX_MISSED_JOB_STATUS_UPDATES = 10; @@ -2670,7 +2671,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); IngestJobEventListener ingestJobEventListener = new IngestJobEventListener(); - IngestManager.getInstance().addIngestJobEventListener(ingestJobEventListener); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobEventListener); try { synchronized (ingestLock) { IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString()); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java index f37c7cefa0..8504bfd7c0 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java @@ -26,7 +26,9 @@ import java.nio.charset.Charset; import java.nio.file.Paths; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.logging.Level; import org.apache.commons.io.FileUtils; @@ -68,8 +70,9 @@ class MultiUserTestTool { private static final Logger LOGGER = Logger.getLogger(MultiUserTestTool.class.getName()); private static final String TEST_FILE_NAME = "AutopsyTempFile"; private static final Object INGEST_LOCK = new Object(); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); static final String MULTI_USER_TEST_SUCCESSFUL = NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.Success"); - + private MultiUserTestTool() { } @@ -86,17 +89,17 @@ class MultiUserTestTool { "# {0} - serviceName", "MultiUserTestTool.serviceDown=Multi User service is down: {0}", "# {0} - serviceName", - "MultiUserTestTool.unableToCheckService=Unable to check Multi User service state: {0}" + "MultiUserTestTool.unableToCheckService=Unable to check Multi User service state: {0}" }) static String runTest(String rootOutputDirectory) { - + // run standard tests for all services. this detects many problems sooner. try { if (!isServiceUp(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString())) { return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.serviceDown", ServicesMonitor.Service.REMOTE_CASE_DATABASE.getDisplayName()); } } catch (ServicesMonitor.ServicesMonitorException ex) { - return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService", + return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService", ServicesMonitor.Service.REMOTE_CASE_DATABASE.getDisplayName() + ". " + ex.getMessage()); } @@ -105,7 +108,7 @@ class MultiUserTestTool { return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.serviceDown", ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.getDisplayName()); } } catch (ServicesMonitor.ServicesMonitorException ex) { - return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService", + return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService", ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.getDisplayName() + ". " + ex.getMessage()); } @@ -114,7 +117,7 @@ class MultiUserTestTool { return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.serviceDown", ServicesMonitor.Service.MESSAGING.getDisplayName()); } } catch (ServicesMonitor.ServicesMonitorException ex) { - return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService", + return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService", ServicesMonitor.Service.MESSAGING.getDisplayName() + ". " + ex.getMessage()); } @@ -225,10 +228,12 @@ class MultiUserTestTool { /** * Creates a new multi user case. * - * @param baseCaseName Case name (will get time stamp appended to it) + * @param baseCaseName Case name (will get time stamp appended to it) * @param rootOutputDirectory Full path to directory in which the case will - * be created + * be created + * * @return Case object + * * @throws CaseActionException */ private static Case createCase(String baseCaseName, String rootOutputDirectory) throws CaseActionException { @@ -251,16 +256,17 @@ class MultiUserTestTool { * @param dataSource The data source. * * @return Error String if there was an error, empty string if the data - * source was added successfully + * source was added successfully * * @throws InterruptedException if the thread running the job processing - * task is interrupted while blocked, i.e., if ingest is shutting down. + * task is interrupted while blocked, i.e., if + * ingest is shutting down. */ @NbBundle.Messages({ "MultiUserTestTool.noContent=Test data source failed to produce content", "# {0} - errorMessage", "MultiUserTestTool.criticalError=Critical error running data source processor on test data source: {0}" - }) + }) private static String runLogicalFilesDSP(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException { AutoIngestDataSourceProcessor selectedProcessor = new LocalFilesDSProcessor(); @@ -298,23 +304,24 @@ class MultiUserTestTool { * @param dataSource The data source to analyze. * * @return Error String if there was an error, empty string if the data - * source was analyzed successfully + * source was analyzed successfully * * @throws InterruptedException if the thread running the job processing - * task is interrupted while blocked, i.e., if auto ingest is shutting down. + * task is interrupted while blocked, i.e., if + * auto ingest is shutting down. */ @NbBundle.Messages({ "# {0} - cancellationReason", "MultiUserTestTool.ingestCancelled=Ingest cancelled due to {0}", "MultiUserTestTool.startupError=Failed to analyze data source due to ingest job startup error", "MultiUserTestTool.errorStartingIngestJob=Ingest manager error while starting ingest job", - "MultiUserTestTool.ingestSettingsError=Failed to analyze data source due to ingest settings errors" + "MultiUserTestTool.ingestSettingsError=Failed to analyze data source due to ingest settings errors" }) private static String analyze(AutoIngestDataSource dataSource) throws InterruptedException { LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", dataSource.getPath()); IngestJobEventListener ingestJobEventListener = new IngestJobEventListener(); - IngestManager.getInstance().addIngestJobEventListener(ingestJobEventListener); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobEventListener); try { synchronized (INGEST_LOCK) { IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString()); @@ -324,9 +331,9 @@ class MultiUserTestTool { IngestJob ingestJob = ingestJobStartResult.getJob(); if (null != ingestJob) { /* - * Block until notified by the ingest job event - * listener or until interrupted because auto ingest - * is shutting down. + * Block until notified by the ingest job event listener + * or until interrupted because auto ingest is shutting + * down. */ INGEST_LOCK.wait(); LOGGER.log(Level.INFO, "Finished ingest modules analysis for {0} ", dataSource.getPath()); @@ -381,7 +388,7 @@ class MultiUserTestTool { * @return True if the service is running, false otherwise. * * @throws ServicesMonitorException if there is an error querying the - * services monitor. + * services monitor. */ private static boolean isServiceUp(String serviceName) throws ServicesMonitor.ServicesMonitorException { return (ServicesMonitor.getInstance().getServiceStatus(serviceName).equals(ServicesMonitor.ServiceStatus.UP.toString())); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index fd365877dd..624c914d56 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -89,7 +89,8 @@ import org.sleuthkit.datamodel.TskData; public final class ImageGalleryController { private static final Logger logger = Logger.getLogger(ImageGalleryController.class.getName()); - + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_STARTED, IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED, IngestManager.IngestModuleEvent.FILE_DONE); /* * The file limit for image gallery. If the selected data source (or all * data sources, if that option is selected) has more than this many files @@ -267,8 +268,8 @@ public final class ImageGalleryController { dbTaskQueueSize.addListener(obs -> this.updateRegroupDisabled()); Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, caseEventListener); - IngestManager.getInstance().addIngestJobEventListener(ingestJobEventListener); - IngestManager.getInstance().addIngestModuleEventListener(ingestModuleEventListener); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobEventListener); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, ingestModuleEventListener); SwingUtilities.invokeLater(() -> { topComponent = ImageGalleryTopComponent.getTopComponent(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java index 089e8a0031..f5ef3f7b91 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java @@ -52,6 +52,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager; class DropdownListSearchPanel extends AdHocSearchPanel { private static final Logger logger = Logger.getLogger(DropdownListSearchPanel.class.getName()); + private static DropdownListSearchPanel instance; private XmlKeywordSearchList loader; private final KeywordListsTableModel listsTableModel; From bcdd3156582c7b27dd19a996f14ae5c9ba2f2399 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 19 Jul 2019 15:10:40 -0400 Subject: [PATCH 05/46] 5319 clean up and update copyrights --- .../autopsy/casemodule/CollaborationMonitor.java | 7 +++---- .../eventlisteners/IngestEventsListener.java | 3 ++- .../optionspanel/GlobalSettingsPanel.java | 2 +- .../commandlineingest/CommandLineIngestManager.java | 1 + .../sleuthkit/autopsy/communications/FiltersPanel.java | 6 ++++-- .../org/sleuthkit/autopsy/datamodel/EmailExtracted.java | 1 - .../sleuthkit/autopsy/datamodel/ExtractedContent.java | 9 ++++----- Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java | 4 ++-- .../autopsy/datamodel/FileTypesByExtension.java | 8 ++++---- .../sleuthkit/autopsy/datamodel/FileTypesByMimeType.java | 2 +- .../src/org/sleuthkit/autopsy/datamodel/HashsetHits.java | 9 ++++----- Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java | 2 +- Core/src/org/sleuthkit/autopsy/datamodel/Tags.java | 2 +- Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java | 2 +- .../sleuthkit/autopsy/datamodel/accounts/Accounts.java | 7 ++++--- .../org/sleuthkit/autopsy/imagewriter/ImageWriter.java | 2 +- Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java | 3 +-- .../sleuthkit/autopsy/timeline/TimeLineController.java | 5 ++--- .../org/sleuthkit/autopsy/testutils/IngestJobRunner.java | 2 +- 19 files changed, 38 insertions(+), 39 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java index 89778bb86e..e6a7772c73 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,11 +24,10 @@ import java.beans.PropertyChangeListener; import java.io.Serializable; import java.time.Duration; import java.time.Instant; -import java.util.Arrays; +import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -541,7 +540,7 @@ final class CollaborationMonitor { * @return A mapping of task IDs to current tasks */ Map getCurrentTasks() { - return currentTasks; + return Collections.unmodifiableMap(currentTasks); } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 6ec535a999..f2942dd3eb 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -55,6 +55,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.coreutils.ThreadUtils; import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; +import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisEvent; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; @@ -365,7 +366,7 @@ public class IngestEventsListener { String dataSourceName = ""; long dataSourceObjectId = -1; try { - dataSource = ((DataSourceAnalysisCompletedEvent) event).getDataSource(); + dataSource = ((DataSourceAnalysisEvent) event).getDataSource(); /* * We only care about Images for the purpose of updating hash diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index 6236d3b8bd..c388d081a9 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java index 9cc726c32e..31de1cfdfe 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java @@ -103,6 +103,7 @@ public class CommandLineIngestManager { } } + @Override public void run() { LOGGER.log(Level.INFO, "Job processing task started"); diff --git a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java index 15e1d29b3c..a804735c32 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2017-2018 Basis Technology Corp. + * Copyright 2017-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -833,7 +833,7 @@ final public class FiltersPanel extends JPanel { * * @return an instance of CommunicationsFilter */ - protected CommunicationsFilter getFilter() { + private CommunicationsFilter getFilter() { CommunicationsFilter commsFilter = new CommunicationsFilter(); commsFilter.addAndFilter(getDeviceFilter()); commsFilter.addAndFilter(getAccountTypeFilter()); @@ -1089,6 +1089,8 @@ final public class FiltersPanel extends JPanel { */ final class CheckBoxIconPanel extends JPanel { + private static final long serialVersionUID = 1L; + private final JCheckBox checkbox; private final JLabel label; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index a6652679ec..545cace37e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -42,7 +42,6 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; -import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.CONTENT_CHANGED; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index 4ac4413e47..cefd59a041 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -52,7 +52,6 @@ import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWO import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskException; /** * Parent of the "extracted content" artifacts to be displayed in the tree. @@ -226,7 +225,7 @@ public class ExtractedContent implements AutopsyVisitableItem { // maps the artifact type to its child node private final HashMap typeNodeList = new HashMap<>(); - public TypeFactory() { + TypeFactory() { super(); // these are shown in other parts of the UI tree @@ -376,7 +375,7 @@ public class ExtractedContent implements AutopsyVisitableItem { this.childCount = (filteringDSObjId > 0) ? blackboard.getArtifactsCount(type.getTypeID(), filteringDSObjId) : skCase.getBlackboardArtifactsTypeCount(type.getTypeID()); - } catch (TskException ex) { + } catch (TskCoreException ex) { Logger.getLogger(TypeNode.class.getName()) .log(Level.WARNING, "Error getting child count", ex); //NON-NLS } @@ -428,7 +427,7 @@ public class ExtractedContent implements AutopsyVisitableItem { private BlackboardArtifact.Type type; - public ArtifactFactory(BlackboardArtifact.Type type) { + ArtifactFactory(BlackboardArtifact.Type type) { super(type.getTypeName()); this.type = type; } @@ -505,7 +504,7 @@ public class ExtractedContent implements AutopsyVisitableItem { return (filteringDSObjId > 0) ? blackboard.getArtifacts(type.getTypeID(), filteringDSObjId) : skCase.getBlackboardArtifacts(type.getTypeID()); - } catch (TskException ex) { + } catch (TskCoreException ex) { Logger.getLogger(ArtifactFactory.class.getName()).log(Level.SEVERE, "Couldn't get blackboard artifacts from database", ex); //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java index 172c11c037..a29a853320 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -269,7 +269,7 @@ public class FileSize implements AutopsyVisitableItem { */ public class FileSizeNode extends DisplayableItemNode { - private FileSizeFilter filter; + private final FileSizeFilter filter; private final long datasourceObjId; // use version with observer instead so that it updates @@ -364,11 +364,11 @@ public class FileSize implements AutopsyVisitableItem { */ static class FileSizeChildren extends BaseChildFactory { + private static final Logger logger = Logger.getLogger(FileSizeChildren.class.getName()); private final SleuthkitCase skCase; private final FileSizeFilter filter; private final Observable notifier; private final long datasourceObjId; - private static final Logger logger = Logger.getLogger(FileSizeChildren.class.getName()); /** * diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java index 19dac06410..344a24cb79 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java @@ -281,7 +281,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { * Node for a specific file type / extension. Children of it will be the * files of that type. */ - class FileExtensionNode extends FileTypes.BGCountUpdatingNode { + final class FileExtensionNode extends FileTypes.BGCountUpdatingNode { private final FileTypesByExtension.SearchFilterInterface filter; @@ -495,7 +495,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { @Override public List getFilter() { - return this.filter; + return Collections.unmodifiableList(this.filter); } } @@ -552,7 +552,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { @Override public List getFilter() { - return this.filter; + return Collections.unmodifiableList(this.filter); } } @@ -599,7 +599,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { @Override public List getFilter() { - return this.filter; + return Collections.unmodifiableList(this.filter); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 0ac8f8e8b0..f1baac477a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -370,7 +370,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi * Node which represents the media sub type in the By MIME type tree, the * media subtype is the portion of the MIME type following the /. */ - class MediaSubTypeNode extends FileTypes.BGCountUpdatingNode { + final class MediaSubTypeNode extends FileTypes.BGCountUpdatingNode { @NbBundle.Messages({"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype", "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype", diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index 3a9a87c1e4..724b3563d0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -51,7 +51,6 @@ import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskException; /** * Hash set hits node support. Inner classes have all of the nodes in the tree. @@ -152,7 +151,7 @@ public class HashsetHits implements AutopsyVisitableItem { String setName = resultSet.getString("value_text"); //NON-NLS long artifactId = resultSet.getLong("artifact_id"); //NON-NLS if (!hashSetHitsMap.containsKey(setName)) { - hashSetHitsMap.put(setName, new HashSet()); + hashSetHitsMap.put(setName, new HashSet<>()); } hashSetHitsMap.get(setName).add(artifactId); } @@ -378,8 +377,8 @@ public class HashsetHits implements AutopsyVisitableItem { */ private class HitFactory extends BaseChildFactory implements Observer { - private String hashsetName; - private Map artifactHits = new HashMap<>(); + private final String hashsetName; + private final Map artifactHits = new HashMap<>(); private HitFactory(String hashsetName) { super(hashsetName); @@ -416,7 +415,7 @@ public class HashsetHits implements AutopsyVisitableItem { BlackboardArtifact art = skCase.getBlackboardArtifact(id); artifactHits.put(id, art); } - } catch (TskException ex) { + } catch (TskCoreException ex) { logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS } }); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java index 12f2340f33..b81fd6760a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java @@ -119,7 +119,7 @@ public class ImageNode extends AbstractContentNode { actionsList.add(new RunIngestModulesAction(Collections.singletonList(content))); actionsList.add(new NewWindowViewAction( NbBundle.getMessage(this.getClass(), "ImageNode.getActions.viewInNewWin.text"), this)); - return actionsList.toArray(new Action[0]); + return actionsList.toArray(new Action[actionsList.size()]); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 8dd7805358..aa47872c82 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java index 0eacf5f699..541a842ea7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java @@ -161,7 +161,7 @@ public class VolumeNode extends AbstractContentNode { NbBundle.getMessage(this.getClass(), "VolumeNode.getActions.viewInNewWin.text"), this)); actionsList.addAll(ExplorerNodeActionVisitor.getActions(content)); - return actionsList.toArray(new Action[0]); + return actionsList.toArray(new Action[actionsList.size()]); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java index 0e3a4e971d..b703867a89 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -193,6 +193,7 @@ final public class Accounts implements AutopsyVisitableItem { * Create of keys used by this Children object to represent the child * nodes. */ + @Override abstract protected boolean createKeys(List list); /** @@ -1174,7 +1175,7 @@ final public class Accounts implements AutopsyVisitableItem { * @return the artifact ids of the account artifacts from this file. */ public List getArtifactIDs() { - return artifactIDs; + return Collections.unmodifiableList(artifactIDs); } /** @@ -1192,7 +1193,7 @@ final public class Accounts implements AutopsyVisitableItem { * @return the status(s) of the account artifacts from this file. */ public Set getStatuses() { - return statuses; + return Collections.unmodifiableSet(statuses); } } diff --git a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java index 29ecb29844..3e44c4718a 100644 --- a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java +++ b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index e345db3d65..36aef30a9c 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -367,7 +367,6 @@ public class IngestManager implements IngestProgressSnapshotProvider { "IngestManager.startupErr.dlgErrorList=Errors:" }) private IngestJobStartResult startIngestJob(IngestJob job) { - List errors = null; Case openCase; try { openCase = Case.getCurrentCaseThrows(); @@ -404,7 +403,7 @@ public class IngestManager implements IngestProgressSnapshotProvider { ingestJobsById.put(job.getId(), job); } IngestManager.logger.log(Level.INFO, "Starting ingest job {0}", job.getId()); //NON-NLS - errors = job.start(); + List errors = job.start(); if (errors.isEmpty()) { this.fireIngestJobStarted(job.getId()); } else { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index bdc5aa07a9..7aa77f2c1b 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2018 Basis Technology Corp. + * Copyright 2014-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -81,7 +81,6 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.ingest.IngestManager; -import static org.sleuthkit.autopsy.ingest.IngestManager.IngestJobEvent.CANCELLED; import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; @@ -150,7 +149,7 @@ public class TimeLineController { private final ReadOnlyStringWrapper taskTitle = new ReadOnlyStringWrapper(); private final ReadOnlyStringWrapper statusMessage = new ReadOnlyStringWrapper(); - private EventBus eventbus = new EventBus("TimeLineController_EventBus"); + private final EventBus eventbus = new EventBus("TimeLineController_EventBus"); /** * Status is a string that will be displayed in the status bar as a kind of diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java index 2f2440e2ce..c424e057c2 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/testutils/IngestJobRunner.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); From a4bfdb773c3765bb944f324051355e04436753c5 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 19 Jul 2019 15:36:35 -0400 Subject: [PATCH 06/46] 5319 undo unintentially commited changes --- .../CommandLineIngestManager.java | 37 ++++--------------- .../autopsy/ingest/IngestManager.java | 3 +- .../DropdownListSearchPanel.java | 1 - 3 files changed, 9 insertions(+), 32 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java index 31de1cfdfe..29faa16356 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java @@ -275,32 +275,10 @@ public class CommandLineIngestManager { * * @throws * AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException if - * there - * was - * a - * DSP - * processing - * error + * there was a DSP processing error * - * @throws InterruptedException if - * the - * thread - * running - * the - * job - * processing - * task - * is - * interrupted - * while - * blocked, - * i.e., - * if - * auto - * ingest - * is - * shutting - * down. + * @throws InterruptedException if the thread running the job processing + * task is interrupted while blocked, i.e., if auto ingest is shutting down. */ private void runDataSourceProcessor(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException { @@ -402,11 +380,10 @@ public class CommandLineIngestManager { * @param dataSource The data source to analyze. * * @throws AnalysisStartupException if there is an error analyzing the - * data source. - * @throws InterruptedException if the thread running the job - * processing task is interrupted while - * blocked, i.e., if auto ingest is - * shutting down. + * data source. + * @throws InterruptedException if the thread running the job processing + * task is interrupted while blocked, i.e., if auto ingest is shutting + * down. */ private void analyze(AutoIngestDataSource dataSource) throws AnalysisStartupException, InterruptedException { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 36aef30a9c..e345db3d65 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -367,6 +367,7 @@ public class IngestManager implements IngestProgressSnapshotProvider { "IngestManager.startupErr.dlgErrorList=Errors:" }) private IngestJobStartResult startIngestJob(IngestJob job) { + List errors = null; Case openCase; try { openCase = Case.getCurrentCaseThrows(); @@ -403,7 +404,7 @@ public class IngestManager implements IngestProgressSnapshotProvider { ingestJobsById.put(job.getId(), job); } IngestManager.logger.log(Level.INFO, "Starting ingest job {0}", job.getId()); //NON-NLS - List errors = job.start(); + errors = job.start(); if (errors.isEmpty()) { this.fireIngestJobStarted(job.getId()); } else { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java index f5ef3f7b91..089e8a0031 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownListSearchPanel.java @@ -52,7 +52,6 @@ import org.sleuthkit.autopsy.ingest.IngestManager; class DropdownListSearchPanel extends AdHocSearchPanel { private static final Logger logger = Logger.getLogger(DropdownListSearchPanel.class.getName()); - private static DropdownListSearchPanel instance; private XmlKeywordSearchList loader; private final KeywordListsTableModel listsTableModel; From b5421a43e7a3870a2428d8812809ebeb0dfea658 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 30 Jul 2019 13:16:16 -0400 Subject: [PATCH 07/46] Changed logger class to use Autopsy version Changed logger class to use Autopsy version. --- .../datasourcesummary/DataSourceLabeledValueCallback.java | 2 +- .../datasourcesummary/DataSourceSingleValueCallback.java | 2 +- .../CommonAttributeSearchResultRootNode.java | 2 +- Core/src/org/sleuthkit/autopsy/core/AutopsyOptionProcessor.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceLabeledValueCallback.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceLabeledValueCallback.java index 3edd92c8b0..1a44e2a76b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceLabeledValueCallback.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceLabeledValueCallback.java @@ -24,7 +24,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.CaseDbAccessManager; /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSingleValueCallback.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSingleValueCallback.java index 241b74c87e..fc7eea15e5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSingleValueCallback.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSingleValueCallback.java @@ -24,7 +24,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.CaseDbAccessManager; /** diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchResultRootNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchResultRootNode.java index 27156f97fa..2c1ad550cb 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchResultRootNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchResultRootNode.java @@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.List; import java.util.Map; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; diff --git a/Core/src/org/sleuthkit/autopsy/core/AutopsyOptionProcessor.java b/Core/src/org/sleuthkit/autopsy/core/AutopsyOptionProcessor.java index dd4ba98ae6..e4cab76761 100644 --- a/Core/src/org/sleuthkit/autopsy/core/AutopsyOptionProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/core/AutopsyOptionProcessor.java @@ -22,7 +22,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.netbeans.api.sendopts.CommandException; import org.netbeans.spi.sendopts.Env; import org.netbeans.spi.sendopts.Option; From 83b9b56914aec316da85774ceda067316e09c6c1 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 30 Jul 2019 14:50:52 -0400 Subject: [PATCH 08/46] Change logger from java to Autopsy Change the logger used from java to Autopsy --- .../autopsy/casemodule/datasourcesummary/DataSourceSummary.java | 2 +- .../autopsy/commandlineingest/CommandLineOptionProcessor.java | 2 +- .../CommonAttributesSearchResultsViewerTable.java | 2 +- .../autopsy/communications/relationships/SelectionInfo.java | 2 +- Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.java | 2 +- Core/src/org/sleuthkit/autopsy/datamodel/BaseChildFactory.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java index 390dce1afe..b50c3596bd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java @@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import java.sql.ResultSet; import java.sql.SQLException; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.CaseDbAccessManager; diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java index 8b94961fa6..057ab7b840 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java @@ -23,7 +23,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.netbeans.api.sendopts.CommandException; import org.netbeans.spi.sendopts.Env; import org.netbeans.spi.sendopts.Option; diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributesSearchResultsViewerTable.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributesSearchResultsViewerTable.java index 095615af7b..f42309ba04 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributesSearchResultsViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributesSearchResultsViewerTable.java @@ -24,7 +24,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import org.openide.util.NbBundle; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SelectionInfo.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/SelectionInfo.java index 45ece0a5be..25727fa157 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/SelectionInfo.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SelectionInfo.java @@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.communications.relationships; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.Account; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.java index b53b1dc258..7a9de37fa3 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/HtmlPanel.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.io.StringReader; import java.util.List; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BaseChildFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/BaseChildFactory.java index 9727d83e39..d3a27a1eb3 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BaseChildFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BaseChildFactory.java @@ -28,7 +28,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import java.util.prefs.PreferenceChangeEvent; import java.util.stream.Collectors; import org.openide.nodes.ChildFactory; From ba611f81e639d065da76c4d57d9f3f09a8e1fe4c Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 30 Jul 2019 14:54:13 -0400 Subject: [PATCH 09/46] Change Logger from java to Autopsy Change the logger from java to Autopsy --- .../datasourcesummary/DataSourceBrowser.java | 2 +- .../DataSourceInfoUtilities.java | 2 +- .../DataSourceSummaryCountsPanel.form | 6 +- .../DataSourceSummaryCountsPanel.java | 2 +- .../DataSourceSummaryDetailsPanel.form | 68 +++++++++---------- .../DataSourceSummaryDetailsPanel.java | 2 +- 6 files changed, 41 insertions(+), 41 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java index ac09010de1..92967738b0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java @@ -30,7 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Observer; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.event.ListSelectionListener; import org.openide.nodes.Node; import org.sleuthkit.autopsy.casemodule.Case; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java index e1efb0dc50..c2d8263056 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import java.util.Collections; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form index 232c6889ba..d3a17e0205 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form @@ -81,7 +81,7 @@ - + @@ -104,14 +104,14 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java index c04926d84f..c31f89f34d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java @@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JLabel; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form index d45990f66d..80a8a890c7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form @@ -40,7 +40,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -88,10 +88,10 @@ - + - + @@ -103,7 +103,7 @@ - + @@ -115,7 +115,7 @@ - + @@ -127,7 +127,7 @@ - + @@ -139,10 +139,10 @@ - + - + @@ -179,7 +179,7 @@ - <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> @@ -196,7 +196,7 @@ - + @@ -208,7 +208,7 @@ - + @@ -220,10 +220,10 @@ - + - + @@ -235,10 +235,10 @@ - + - + @@ -250,7 +250,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -274,7 +274,7 @@ - + @@ -286,7 +286,7 @@ - + @@ -298,7 +298,7 @@ - + @@ -310,7 +310,7 @@ - + @@ -322,7 +322,7 @@ - + @@ -334,7 +334,7 @@ - + @@ -346,7 +346,7 @@ - + @@ -358,7 +358,7 @@ - + @@ -370,7 +370,7 @@ - + @@ -382,7 +382,7 @@ - + @@ -394,7 +394,7 @@ - + @@ -427,7 +427,7 @@ - + @@ -469,7 +469,7 @@ - + @@ -481,7 +481,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java index 7702a0a20b..cf06a198cb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java @@ -22,7 +22,7 @@ import java.text.DecimalFormat; import java.util.Map; import java.util.HashMap; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.table.DefaultTableModel; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.DataSource; From 79a61ba85109b8e32e340e16565b5680611b0b19 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 30 Jul 2019 15:00:06 -0400 Subject: [PATCH 10/46] Change logger from java to Autopsy Change the logger from java to Autopsy. --- Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java | 2 +- .../src/org/sleuthkit/autopsy/testing/RegressionTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java b/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java index 2a140bc84f..dd877b3a11 100644 --- a/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java +++ b/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java @@ -32,7 +32,7 @@ import java.util.Date; import java.util.List; import java.util.Random; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import javax.imageio.ImageIO; import javax.swing.JDialog; import javax.swing.text.JTextComponent; diff --git a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java index 8f1ef48a4c..0a7feaa46c 100644 --- a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java +++ b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java @@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.testing; import java.io.File; import java.io.IOException; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import junit.framework.Test; import junit.framework.TestCase; import org.netbeans.jemmy.Timeouts; From 06dc0fc5ebce24bb2cbb1c9007fa90bd533eed8b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 30 Jul 2019 15:51:11 -0400 Subject: [PATCH 11/46] 5217 provide users feed back when image gallery fails to open --- .../autopsy/imagegallery/actions/Bundle.properties-MERGED | 2 ++ .../sleuthkit/autopsy/imagegallery/actions/OpenAction.java | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle.properties-MERGED b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle.properties-MERGED index 3ac90630fa..32b96181cb 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle.properties-MERGED +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle.properties-MERGED @@ -35,6 +35,8 @@ OpenAction.multiUserDialog.Header=Multi-user Image Gallery OpenAction.noControllerDialog.header=Cannot open Image Gallery OpenAction.noControllerDialog.text=An initialization error ocurred.\nPlease see the log for details. OpenAction.notAnalyzedDlg.msg=No image/video files available to display yet.\nPlease run FileType and EXIF ingest modules. +OpenAction.openTopComponent.error.message=An error occurred while attempting to open Image Gallery. +OpenAction.openTopComponent.error.title=Failed to open Image Gallery OpenAction.stale.confDlg.msg=The image / video database may be out of date. Do you want to update and listen for further ingest results?\nChoosing 'yes' will update the database and enable listening to future ingests. OpenAction.stale.confDlg.title=Image Gallery OpenExternalViewerAction.displayName=External Viewer diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java index dec4d44c31..2df0ee2ed1 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java @@ -34,6 +34,7 @@ import javafx.stage.Modality; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; @@ -43,6 +44,7 @@ import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.actions.CallableSystemAction; +import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.core.Installer; @@ -292,13 +294,15 @@ public final class OpenAction extends CallableSystemAction { ); } + @Messages({"OpenAction.openTopComponent.error.message=An error occurred while attempting to open Image Gallery.", + "OpenAction.openTopComponent.error.title=Failed to open Image Gallery"}) private void openTopComponent() { SwingUtilities.invokeLater(() -> { try { ImageGalleryTopComponent.openTopComponent(); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Failed to open Image Gallery top component", ex); //NON-NLS} - // TODO (JIRA-5217): Give the user some feedback here + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), Bundle.OpenAction_openTopComponent_error_message(), Bundle.OpenAction_openTopComponent_error_title(), JOptionPane.PLAIN_MESSAGE); } }); } From 01bd63c29c66b5967c38e1d39cd66f6acbb12966 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 2 Aug 2019 17:14:18 -0400 Subject: [PATCH 12/46] Updated news --- NEWS.txt | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/NEWS.txt b/NEWS.txt index e9c61baf7b..b4bc6e8dbf 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,48 @@ +---------------- VERSION 4.12.0 -------------- +Collection +- Added ability to configure a USB drive to use new logical imager tool. +- Added logical imager tool that runs on a live Windows computer and saves results to a USB drive. +- Added ability to import logical imager results into Autopsy as a data source. + +Ingest Modules: +- Changed file type detection so that Tika does not rely only on extension. +- Email ingest module assigns thread IDs to messages +- Android ingest modules store thread ID from their databases. + +Content Viewers (lower right of UI): +- New “Text” viewer that consolidates previous Strings and “Indexed Text” viewers. +- New “Translation” panel was added to the new “Text” viewer. +- Added integration with Google and Bing translation (credentials required) +- Redesigned “Other Occurrences” viewer to have 4th column with details of selected item. +- Added Willi Ballentin’s “Registry Hive Viewer” panel to the “Application” viewer. +- Improved HTML viewer to use style sheets and better layout. +- Added ability to draw a box on a picture while tagging it. + +Result Table (upper right of UI) +- Added paging to all views for faster loading of large data sets. +- Improved speed of displaying results when a column was sorted. + +Reporting +- Portable cases can contain files marked as Interesting Items +- Portable cases can be compressed and chunked +- “Files - Text” report can use either tabs or commas as the delimiter +- “Files - Text” report better handles Unicode text. +- Added ability to create a CSV report for the contents of a table +- HTML report for tagged pictures includes a copy with the overlay box + +Communications: +- Added Account Summary view +- Added Contacts panel to show all contacts associated with an account. +- Added Media panel to show media attachments associated with an account +- Added filter to show accounts if they involved with the most recent messages. +- Messages can be grouped by thread. + +Auto Ingest +- New Test button was added to help diagnose permission and configuration issues. + +Documentation: +- Created new Triage Standard Operating Procedure (SOP) section to the User Docs + ---------------- VERSION 4.11.0 -------------- New Features: From dd6f0ba0a3ef6bbceefbff98013302ad1ded3049 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 26 Aug 2019 21:25:20 -0400 Subject: [PATCH 13/46] address comments Address comments, --- .../datasourcesummary/DataSourceSummaryDetailsPanel.form | 2 +- CoreLibs/src/org/sleuthkit/autopsy/corelibs/OpenCvLoader.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form index 80a8a890c7..1924193213 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.form @@ -40,7 +40,7 @@ - + diff --git a/CoreLibs/src/org/sleuthkit/autopsy/corelibs/OpenCvLoader.java b/CoreLibs/src/org/sleuthkit/autopsy/corelibs/OpenCvLoader.java index 0a46afd8f9..79e4678e91 100644 --- a/CoreLibs/src/org/sleuthkit/autopsy/corelibs/OpenCvLoader.java +++ b/CoreLibs/src/org/sleuthkit/autopsy/corelibs/OpenCvLoader.java @@ -28,6 +28,7 @@ import org.opencv.core.Core; */ public final class OpenCvLoader { + // Uses java logger since the Autopsy class logger (Autopsy-core) is not part of this module private static final Logger logger = Logger.getLogger(OpenCvLoader.class.getName()); private static boolean openCvLoaded; private static UnsatisfiedLinkError exception = null; // Deprecated From c7207f575c106f0d16685e8df7232cbd4bf4065e Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 26 Aug 2019 22:09:25 -0400 Subject: [PATCH 14/46] Update TikaTextExtractor.java Add comment why it uses java logger and not Autopsy logger --- .../org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java index 2d923cc719..a8bf0591fb 100644 --- a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java @@ -136,6 +136,7 @@ final class TikaTextExtractor implements TextExtractor { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", //NON-NLS "application/pdf"); //NON-NLS + // Used to log to the tika file that is why it uses the java.util.logging.logger class instead of the Autopsy one private static final java.util.logging.Logger TIKA_LOGGER = java.util.logging.Logger.getLogger("Tika"); //NON-NLS private static final Logger AUTOPSY_LOGGER = Logger.getLogger(TikaTextExtractor.class.getName()); From ccd387bb562fa1892a2f0f1081006b585b2b2b1b Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 27 Aug 2019 15:32:42 -0400 Subject: [PATCH 15/46] Changed logging to use Autopsy logger Changed logging to use Autopsy Logger from java logger --- .../autopsy/report/PortableCaseInterestingItemsListPanel.java | 2 +- .../org/sleuthkit/autopsy/report/PortableCaseTagsListPanel.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/PortableCaseInterestingItemsListPanel.java b/Core/src/org/sleuthkit/autopsy/report/PortableCaseInterestingItemsListPanel.java index afd49dbe33..da3a45db07 100644 --- a/Core/src/org/sleuthkit/autopsy/report/PortableCaseInterestingItemsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/PortableCaseInterestingItemsListPanel.java @@ -206,7 +206,7 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel { */ private static class GetInterestingItemSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback { - private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(GetInterestingItemSetNamesCallback.class.getName()); + private static final Logger logger = Logger.getLogger(GetInterestingItemSetNamesCallback.class.getName()); private final Map setCounts = new HashMap<>(); @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/PortableCaseTagsListPanel.java b/Core/src/org/sleuthkit/autopsy/report/PortableCaseTagsListPanel.java index db40932835..af2fc729ad 100644 --- a/Core/src/org/sleuthkit/autopsy/report/PortableCaseTagsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/PortableCaseTagsListPanel.java @@ -205,7 +205,7 @@ class PortableCaseTagsListPanel extends javax.swing.JPanel { */ static class GetTagCountsCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback { - private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(GetTagCountsCallback.class.getName()); + private static final Logger logger = Logger.getLogger(GetTagCountsCallback.class.getName()); private final Map tagCounts = new HashMap<>(); @Override From 13df8bf57c76ec752abbd64ba42e9971e58d46c1 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Thu, 29 Aug 2019 15:28:44 -0400 Subject: [PATCH 16/46] Update IngestSearchRunner.java Make it so the search status bar disapears when it is cancelled --- .../org/sleuthkit/autopsy/keywordsearch/IngestSearchRunner.java | 1 + 1 file changed, 1 insertion(+) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IngestSearchRunner.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IngestSearchRunner.java index cea9fd1a82..937c9567fd 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IngestSearchRunner.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IngestSearchRunner.java @@ -483,6 +483,7 @@ final class IngestSearchRunner { if (progressGroup != null) { progressGroup.setDisplayName(displayName + " " + NbBundle.getMessage(this.getClass(), "SearchRunner.doInBackGround.cancelMsg")); } + progressGroup.finish(); return IngestSearchRunner.Searcher.this.cancel(true); } }, null); From c0affed0735f04a3e36702099ac4da43447d4e0d Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 3 Sep 2019 15:14:53 -0400 Subject: [PATCH 17/46] Added the account user groups --- .../recentactivity/Bundle.properties-MERGED | 8 +- .../autopsy/recentactivity/Extract.java | 4 + .../recentactivity/ExtractRegistry.java | 421 +++++++++++------- 3 files changed, 272 insertions(+), 161 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 5e11018086..f27b253e16 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -2,14 +2,9 @@ cannotBuildXmlParser=Unable to build XML parser: cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml: cannotParseXml=Unable to parse XML file: ChromeCacheExtractor.moduleName=ChromeCacheExtractor -# {0} - module name -# {1} - row number -# {2} - table length -# {3} - cache path ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries from {3} DataSourceUsage_AndroidMedia=Android Media Card DataSourceUsage_FlashDrive=Flash Drive -# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.parentModuleName=Recent Activity Extract.indexError.message=Failed to index artifact for keyword search. @@ -64,7 +59,7 @@ ExtractZone_progress_Msg=Extracting :Zone.Identifer files ExtractZone_Restricted=Restricted Sites Zone ExtractZone_Trusted=Trusted Sites Zone OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. +OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome @@ -187,7 +182,6 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity RecentDocumentsByLnk.parentModuleName=Recent Activity RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. -# {0} - file name SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.engineName.none=NONE diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java index bef51a8a95..ebf483b5d0 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java @@ -235,6 +235,10 @@ abstract class Extract { protected String getName() { return moduleName; } + + protected String getRAModuleName() { + return RecentActivityExtracterModuleFactory.getModuleName(); + } /** * Returns the state of foundData diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 63ac3b6ee6..a129bea794 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -54,6 +54,7 @@ import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import java.nio.file.Path; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.List; import java.util.Collection; @@ -89,6 +90,36 @@ import org.sleuthkit.datamodel.TskCoreException; "Progress_Message_Analyze_Registry=Analyzing Registry Files" }) class ExtractRegistry extends Extract { + + private static final String USERNAME_KEY = "Username"; //NON-NLS + private static final String SID_KEY = "SID"; //NON-NLS + private static final String RID_KEY = "RID"; //NON-NLS + private static final String ACCOUNT_CREATED_KEY = "Account Created"; //NON-NLS + private static final String LAST_LOGIN_KEY = "Last Login Date"; //NON-NLS + private static final String LOGIN_COUNT_KEY = "Login Count"; //NON-NLS + private static final String FULL_NAME_KEY = "Full Name"; //NON-NLS + private static final String USER_COMMENT_KEY = "User Comment"; //NON-NLS + private static final String ACCOUNT_TYPE_KEY = "Account Type"; //NON-NLS + private static final String NAME_KEY = "Name"; //NON-NLS + private static final String PWD_RESET_KEY = "Pwd Rest Date"; //NON-NLS + private static final String PWD_FAILE_KEY = "Pwd Fail Date"; //NON-NLS + private static final String INTERNET_NAME_KEY = "InternetName"; //NON-NLS + private static final String PWD_DOES_NOT_EXPIRE_KEY = "Password does not expire"; //NON-NLS + private static final String ACCOUNT_DISABLED_KEY = "Account Disabled"; //NON-NLS + private static final String PWD_NOT_REQUIRED_KEY = "Password not required"; //NON-NLS + private static final String NORMAL_ACCOUNT_KEY = "Normal user account"; //NON-NLS + private static final String HOME_DIRECTORY_REQUIRED_KEY = "Home directory required"; + private static final String TEMPORARY_DUPLICATE_ACCOUNT = "Temporary duplicate account"; + private static final String MNS_LOGON_ACCOUNT_KEY = "MNS logon user account"; + private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY = "Interdomain trust account"; + private static final String WORKSTATION_TRUST_ACCOUNT = "Workstation trust account"; + private static final String SERVER_TRUST_ACCOUNT = "Server trust account"; + private static final String ACCOUNT_AUTO_LOCKED = "Account auto locked"; + private static final String PASSWORD_HINT = "Password Hint"; + + private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY}; + private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY}; + private static final String[] ACCOUNT_TYPE_FLAGS = {NORMAL_ACCOUNT_KEY, SERVER_TRUST_ACCOUNT, WORKSTATION_TRUST_ACCOUNT, INTERDOMAIN_TRUST_ACCOUNT_KEY, MNS_LOGON_ACCOUNT_KEY, TEMPORARY_DUPLICATE_ACCOUNT}; final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper(); final private static String RIP_EXE = "rip.exe"; @@ -852,27 +883,29 @@ class ExtractRegistry extends Extract { */ private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) { File regfile = new File(regFilePath); - String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName(); - SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'"); - regRipperTimeFormat.setTimeZone(getTimeZone("GMT")); try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) { // Read the file in and create a Document and elements String userInfoSection = "User Information"; String previousLine = null; String line = bufferedReader.readLine(); - Set userSet = new HashSet<>(); + Set> userSet = new HashSet<>(); + Map> groupMap = null; while (line != null) { if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) { readUsers(bufferedReader, userSet); - } + + if(line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains("Group Membership Information")) { + groupMap = readGroups(bufferedReader); + } + previousLine = line; line = bufferedReader.readLine(); } - Map userInfoMap = new HashMap<>(); + Map> userInfoMap = new HashMap<>(); //load all the user info which was read into a map - for (UserInfo userInfo : userSet) { - userInfoMap.put(userInfo.getUserSid(), userInfo); + for (HashMap userInfo : userSet) { + userInfoMap.put(userInfo.get(SID_KEY), userInfo); } //get all existing OS account artifacts List existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT); @@ -881,45 +914,19 @@ class ExtractRegistry extends Extract { if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) { BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); if (existingUserId != null) { - UserInfo userInfo = userInfoMap.remove(existingUserId.getValueString().trim()); + String userID = existingUserId.getValueString().trim(); + HashMap userInfo = userInfoMap.remove(userID); //if the existing user id matches a user id which we parsed information for check if that information exists and if it doesn't add it if (userInfo != null) { - Collection bbattributes = new ArrayList<>(); - if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, - parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC)); - } - if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, - parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC)); - } - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, - parentModuleName, userInfo.getLoginCount())); - osAccount.addAttributes(bbattributes); + osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID), true)); } } } } //add remaining userinfos as accounts; - for (String userId : userInfoMap.keySet()) { - UserInfo userInfo = userInfoMap.get(userId); - Collection bbattributes = new ArrayList<>(); + for (HashMap userInfo: userInfoMap.values()) { BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, - parentModuleName, userInfo.getUserName())); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, - parentModuleName, userId)); - if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, - parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC)); - } - if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, - parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC)); - } - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, - parentModuleName, userInfo.getLoginCount())); - bbart.addAttributes(bbattributes); + bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)), false)); // index the artifact for keyword search postArtifact(bbart); } @@ -936,6 +943,182 @@ class ExtractRegistry extends Extract { } return false; } + + Collection getAttributesForAccount(HashMap userInfo, List groupList, boolean existingUser) throws ParseException { + Collection bbattributes = new ArrayList<>(); + + SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'"); + regRipperTimeFormat.setTimeZone(getTimeZone("GMT")); + + if (! existingUser) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, + getRAModuleName(), userInfo.get(SID_KEY))); + + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + this.moduleName, userInfo.get(USERNAME_KEY))); + } + + String value = userInfo.get(ACCOUNT_CREATED_KEY); + if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, + getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); + } + + value = userInfo.get(LAST_LOGIN_KEY); + if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE) ) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, + getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); + } + + value = userInfo.get(LOGIN_COUNT_KEY); + if(value != null && !value.isEmpty()) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, + getRAModuleName(), Integer.parseInt(value))); + } + + value = userInfo.get(ACCOUNT_TYPE_KEY); + if(value != null && !value.isEmpty()) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE, + getRAModuleName(), value)); + } + + value = userInfo.get(USER_COMMENT_KEY); + if(value != null && !value.isEmpty()) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION, + getRAModuleName(), value)); + } + + value = userInfo.get(NAME_KEY); + if(value != null && !value.isEmpty()) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, + getRAModuleName(), value)); + } + + value = userInfo.get(INTERNET_NAME_KEY); + if(value != null && !value.isEmpty()) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL, + getRAModuleName(), value)); + } + + value = userInfo.get(FULL_NAME_KEY); + if(value != null && !value.isEmpty()) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DISPLAY_NAME, + getRAModuleName(), value)); + } + + value = userInfo.get(PWD_RESET_KEY); + if(value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET, + getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); + } + + value = userInfo.get(PASSWORD_HINT); + if(value != null && !value.isEmpty()) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT, + getRAModuleName(), value)); + } + + value = userInfo.get(PWD_FAILE_KEY); + if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL, + getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); + } + + String settingString = ""; + for (String setting: PASSWORD_SETTINGS_FLAGS) { + if (userInfo.containsKey(setting)) { + settingString += setting + ", "; + } + } + + if (!settingString.isEmpty()) { + settingString = settingString.substring(0, settingString.length() - 2); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS, + getRAModuleName(), settingString)); + } + + settingString = ""; + for (String setting: ACCOUNT_SETTINGS_FLAGS) { + if (userInfo.containsKey(setting)) { + settingString += setting + ", "; + } + } + + if (!settingString.isEmpty()) { + settingString = settingString.substring(0, settingString.length() - 2); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS, + getRAModuleName(), settingString)); + } + + settingString = ""; + for (String setting: ACCOUNT_TYPE_FLAGS) { + if (userInfo.containsKey(setting)) { + settingString += setting + ", "; + } + } + + if (!settingString.isEmpty()) { + settingString = settingString.substring(0, settingString.length() - 2); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAGS, + getRAModuleName(), settingString)); + } + + if (groupList != null && groupList.size() > 0) { + String groups = new String(); + for (String group: groupList) { + groups += group + ", "; + } + groups = groups.substring(0, groups.length() - 2); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GROUPS, + getRAModuleName(), groups)); + } + + return bbattributes; + } + + Map> readGroups(BufferedReader bufferedReader) throws IOException { + HashMap> groupMap = new HashMap<>(); + + String line = bufferedReader.readLine(); + + int userCount = 0; + String groupName = null; + + while (line != null && !line.contains(SECTION_DIVIDER)) { + + if(line.contains("Group Name")) { + String value = line.replaceAll("Group Name\\s*?:", "").trim(); + groupName = (value.replaceAll("\\[\\d*?\\]", "")).trim(); + int startIndex = value.indexOf('['); + int endIndex = value.indexOf(']'); + + if(startIndex != -1 && endIndex != -1) { + String countStr = value.substring(startIndex+1, endIndex); + userCount = Integer.parseInt(countStr); + } + } else if(line.matches("Users\\s*?:")) { + for(int i = 0; i < userCount; i++) { + line = bufferedReader.readLine(); + if(line != null) { + String sid = line.trim(); + List groupList = groupMap.get(sid); + if(groupList == null) { + groupList = new ArrayList<>(); + groupMap.put(sid, groupList); + } + + groupList.add(groupName); + } + } + + groupName = null; + } + + line = bufferedReader.readLine(); + } + + return groupMap; + } /** * Read the User Information section of the SAM regripper plugin's output @@ -948,41 +1131,68 @@ class ExtractRegistry extends Extract { * * @throws IOException */ - private void readUsers(BufferedReader bufferedReader, Set users) throws IOException { - String userNameLabel = "Username :"; - String sidLabel = "SID :"; - String accountCreatedLabel = "Account Created :"; - String loginCountLabel = "Login Count :"; - String lastLoginLabel = "Last Login Date :"; + private void readUsers(BufferedReader bufferedReader, Set> users) throws IOException { String line = bufferedReader.readLine(); //read until end of file or next section divider String userName = ""; + String user_rid = ""; while (line != null && !line.contains(SECTION_DIVIDER)) { //when a user name field exists read the name and id number - if (line.contains(userNameLabel)) { - String userNameAndIdString = line.replace(userNameLabel, ""); + if (line.contains(USERNAME_KEY)) { + String regx = USERNAME_KEY + "\\s*?:"; + String userNameAndIdString = line.replaceAll(regx, ""); userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim(); - } else if (line.contains(sidLabel) && !userName.isEmpty()) { - String sid = line.replace(sidLabel, "").trim(); - UserInfo userInfo = new UserInfo(userName, sid); + user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf('['), userNameAndIdString.lastIndexOf(']')); + } else if (line.contains(SID_KEY) && !userName.isEmpty()) { + Map.Entry entry = getSAMKeyValue(line); + + HashMap userInfo = new HashMap<>(); + userInfo.put(USERNAME_KEY, userName); + userInfo.put(RID_KEY, user_rid); + userInfo.put(entry.getKey(), entry.getValue()); + //continue reading this users information until end of file or a blank line between users line = bufferedReader.readLine(); while (line != null && !line.isEmpty()) { - if (line.contains(accountCreatedLabel)) { - userInfo.setAccountCreatedDate(line.replace(accountCreatedLabel, "").trim()); - } else if (line.contains(loginCountLabel)) { - userInfo.setLoginCount(Integer.parseInt(line.replace(loginCountLabel, "").trim())); - } else if (line.contains(lastLoginLabel)) { - userInfo.setLastLoginDate(line.replace(lastLoginLabel, "").trim()); - } + entry = getSAMKeyValue(line); + userInfo.put(entry.getKey(), entry.getValue()); line = bufferedReader.readLine(); } users.add(userInfo); + userName = ""; } line = bufferedReader.readLine(); } } + + private Map.Entry getSAMKeyValue(String line) { + int index = line.indexOf(':'); + Map.Entry returnValue = null; + String key = null; + String value = null; + + if (index != -1) { + key = line.substring(0, index).trim(); + if (index + 1 < line.length()) { + value = line.substring(index+1).trim(); + } else { + value = ""; + } + + return new AbstractMap.SimpleEntry<>(key, value); + + } else if (line.contains("-->")) { + key = line.replace("-->", "").trim(); + value = "true"; + } + + if (key != null) { + returnValue = new AbstractMap.SimpleEntry<>(key, value); + } + + return returnValue; + } @Override public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { @@ -1002,101 +1212,4 @@ class ExtractRegistry extends Extract { public String autopsyPlugins = ""; public String fullPlugins = ""; } - - /** - * Class for organizing information associated with a TSK_OS_ACCOUNT before - * the artifact is created. - */ - private class UserInfo { - - private final String userName; - private final String userSid; - private String lastLoginDate; - private String accountCreatedDate; - private int loginCount = 0; - - /** - * Create a UserInfo object - * - * @param name - the os user account name - * @param userSidString - the SID for the user account - */ - private UserInfo(String name, String userSidString) { - userName = name; - userSid = userSidString; - } - - /** - * Get the user name. - * - * @return the userName - */ - String getUserName() { - return userName; - } - - /** - * Get the user SID. - * - * @return the user SID - */ - String getUserSid() { - return userSid; - } - - /** - * Get the last login date for the user - * - * @return the lastLoginDate - */ - String getLastLoginDate() { - return lastLoginDate; - } - - /** - * Set the last login date for the users - * - * @param lastLoginDate the lastLoginDate to set - */ - void setLastLoginDate(String lastLoginDate) { - this.lastLoginDate = lastLoginDate; - } - - /** - * Get the account creation date. - * - * @return the accountCreatedDate - */ - String getAccountCreatedDate() { - return accountCreatedDate; - } - - /** - * Set the account creation date. - * - * @param accountCreatedDate the accountCreatedDate to set - */ - void setAccountCreatedDate(String accountCreatedDate) { - this.accountCreatedDate = accountCreatedDate; - } - - /** - * Get the number of times the user logged in. - * - * @return the loginCount - */ - int getLoginCount() { - return loginCount; - } - - /** - * Set the number of times the user logged in. - * - * @param loginCount the loginCount to set - */ - void setLoginCount(int loginCount) { - this.loginCount = loginCount; - } - - } } From 22d47485c9089862dea8fa0c98ccede03f951ced Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 4 Sep 2019 10:35:45 -0400 Subject: [PATCH 18/46] Changed TSK_FLAGS to TSK_FLAG --- .../recentactivity/ExtractRegistry.java | 241 ++++++++++-------- 1 file changed, 133 insertions(+), 108 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index a129bea794..be75bb7101 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -90,7 +90,7 @@ import org.sleuthkit.datamodel.TskCoreException; "Progress_Message_Analyze_Registry=Analyzing Registry Files" }) class ExtractRegistry extends Extract { - + private static final String USERNAME_KEY = "Username"; //NON-NLS private static final String SID_KEY = "SID"; //NON-NLS private static final String RID_KEY = "RID"; //NON-NLS @@ -116,7 +116,7 @@ class ExtractRegistry extends Extract { private static final String SERVER_TRUST_ACCOUNT = "Server trust account"; private static final String ACCOUNT_AUTO_LOCKED = "Account auto locked"; private static final String PASSWORD_HINT = "Password Hint"; - + private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY}; private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY}; private static final String[] ACCOUNT_TYPE_FLAGS = {NORMAL_ACCOUNT_KEY, SERVER_TRUST_ACCOUNT, WORKSTATION_TRUST_ACCOUNT, INTERDOMAIN_TRUST_ACCOUNT_KEY, MNS_LOGON_ACCOUNT_KEY, TEMPORARY_DUPLICATE_ACCOUNT}; @@ -849,7 +849,7 @@ class ExtractRegistry extends Extract { break; } } // for - + postArtifacts(usbBBartifacts); postArtifacts(wifiBBartifacts); return true; @@ -894,17 +894,17 @@ class ExtractRegistry extends Extract { if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) { readUsers(bufferedReader, userSet); } - - if(line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains("Group Membership Information")) { - groupMap = readGroups(bufferedReader); + + if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains("Group Membership Information")) { + groupMap = readGroups(bufferedReader); } - + previousLine = line; line = bufferedReader.readLine(); } - Map> userInfoMap = new HashMap<>(); + Map> userInfoMap = new HashMap<>(); //load all the user info which was read into a map - for (HashMap userInfo : userSet) { + for (HashMap userInfo : userSet) { userInfoMap.put(userInfo.get(SID_KEY), userInfo); } //get all existing OS account artifacts @@ -915,7 +915,7 @@ class ExtractRegistry extends Extract { BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); if (existingUserId != null) { String userID = existingUserId.getValueString().trim(); - HashMap userInfo = userInfoMap.remove(userID); + HashMap userInfo = userInfoMap.remove(userID); //if the existing user id matches a user id which we parsed information for check if that information exists and if it doesn't add it if (userInfo != null) { osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID), true)); @@ -924,7 +924,7 @@ class ExtractRegistry extends Extract { } } //add remaining userinfos as accounts; - for (HashMap userInfo: userInfoMap.values()) { + for (HashMap userInfo : userInfoMap.values()) { BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)), false)); // index the artifact for keyword search @@ -943,183 +943,150 @@ class ExtractRegistry extends Extract { } return false; } - - Collection getAttributesForAccount(HashMap userInfo, List groupList, boolean existingUser) throws ParseException { + + /** + * Creates the attribute list for the given user information and group list. + * + * @param userInfo Map of key\value pairs of user information + * @param groupList List of the groups that user belongs + * @param existingUser + * + * @return List + * + * @throws ParseException + */ + Collection getAttributesForAccount(HashMap userInfo, List groupList, boolean existingUser) throws ParseException { Collection bbattributes = new ArrayList<>(); SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'"); regRipperTimeFormat.setTimeZone(getTimeZone("GMT")); - - if (! existingUser) { + + if (!existingUser) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, getRAModuleName(), userInfo.get(SID_KEY))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, - this.moduleName, userInfo.get(USERNAME_KEY))); + this.moduleName, userInfo.get(USERNAME_KEY))); } - + String value = userInfo.get(ACCOUNT_CREATED_KEY); if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); } - + value = userInfo.get(LAST_LOGIN_KEY); - if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE) ) { + if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); } - + value = userInfo.get(LOGIN_COUNT_KEY); - if(value != null && !value.isEmpty()) { + if (value != null && !value.isEmpty()) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, getRAModuleName(), Integer.parseInt(value))); } - + value = userInfo.get(ACCOUNT_TYPE_KEY); - if(value != null && !value.isEmpty()) { + if (value != null && !value.isEmpty()) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE, getRAModuleName(), value)); } - + value = userInfo.get(USER_COMMENT_KEY); - if(value != null && !value.isEmpty()) { + if (value != null && !value.isEmpty()) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION, getRAModuleName(), value)); } - + value = userInfo.get(NAME_KEY); - if(value != null && !value.isEmpty()) { + if (value != null && !value.isEmpty()) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, getRAModuleName(), value)); } - + value = userInfo.get(INTERNET_NAME_KEY); - if(value != null && !value.isEmpty()) { + if (value != null && !value.isEmpty()) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL, getRAModuleName(), value)); } - + value = userInfo.get(FULL_NAME_KEY); - if(value != null && !value.isEmpty()) { + if (value != null && !value.isEmpty()) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DISPLAY_NAME, getRAModuleName(), value)); } - + value = userInfo.get(PWD_RESET_KEY); - if(value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { + if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET, getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); } - + value = userInfo.get(PASSWORD_HINT); - if(value != null && !value.isEmpty()) { + if (value != null && !value.isEmpty()) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT, getRAModuleName(), value)); } - + value = userInfo.get(PWD_FAILE_KEY); if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL, getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC)); } - + String settingString = ""; - for (String setting: PASSWORD_SETTINGS_FLAGS) { + for (String setting : PASSWORD_SETTINGS_FLAGS) { if (userInfo.containsKey(setting)) { settingString += setting + ", "; } } - + if (!settingString.isEmpty()) { settingString = settingString.substring(0, settingString.length() - 2); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS, getRAModuleName(), settingString)); } - + settingString = ""; - for (String setting: ACCOUNT_SETTINGS_FLAGS) { + for (String setting : ACCOUNT_SETTINGS_FLAGS) { if (userInfo.containsKey(setting)) { settingString += setting + ", "; } } - + if (!settingString.isEmpty()) { settingString = settingString.substring(0, settingString.length() - 2); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS, getRAModuleName(), settingString)); } - + settingString = ""; - for (String setting: ACCOUNT_TYPE_FLAGS) { + for (String setting : ACCOUNT_TYPE_FLAGS) { if (userInfo.containsKey(setting)) { settingString += setting + ", "; } } - + if (!settingString.isEmpty()) { settingString = settingString.substring(0, settingString.length() - 2); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAGS, + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAG, getRAModuleName(), settingString)); - } - + } + if (groupList != null && groupList.size() > 0) { String groups = new String(); - for (String group: groupList) { + for (String group : groupList) { groups += group + ", "; } - groups = groups.substring(0, groups.length() - 2); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GROUPS, - getRAModuleName(), groups)); + getRAModuleName(), groups.substring(0, groups.length() - 2))); } - + return bbattributes; } - Map> readGroups(BufferedReader bufferedReader) throws IOException { - HashMap> groupMap = new HashMap<>(); - - String line = bufferedReader.readLine(); - - int userCount = 0; - String groupName = null; - - while (line != null && !line.contains(SECTION_DIVIDER)) { - - if(line.contains("Group Name")) { - String value = line.replaceAll("Group Name\\s*?:", "").trim(); - groupName = (value.replaceAll("\\[\\d*?\\]", "")).trim(); - int startIndex = value.indexOf('['); - int endIndex = value.indexOf(']'); - - if(startIndex != -1 && endIndex != -1) { - String countStr = value.substring(startIndex+1, endIndex); - userCount = Integer.parseInt(countStr); - } - } else if(line.matches("Users\\s*?:")) { - for(int i = 0; i < userCount; i++) { - line = bufferedReader.readLine(); - if(line != null) { - String sid = line.trim(); - List groupList = groupMap.get(sid); - if(groupList == null) { - groupList = new ArrayList<>(); - groupMap.put(sid, groupList); - } - - groupList.add(groupName); - } - } - - groupName = null; - } - - line = bufferedReader.readLine(); - } - - return groupMap; - } - /** * Read the User Information section of the SAM regripper plugin's output * and collect user account information from the file. @@ -1131,7 +1098,7 @@ class ExtractRegistry extends Extract { * * @throws IOException */ - private void readUsers(BufferedReader bufferedReader, Set> users) throws IOException { + private void readUsers(BufferedReader bufferedReader, Set> users) throws IOException { String line = bufferedReader.readLine(); //read until end of file or next section divider String userName = ""; @@ -1145,12 +1112,12 @@ class ExtractRegistry extends Extract { user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf('['), userNameAndIdString.lastIndexOf(']')); } else if (line.contains(SID_KEY) && !userName.isEmpty()) { Map.Entry entry = getSAMKeyValue(line); - - HashMap userInfo = new HashMap<>(); + + HashMap userInfo = new HashMap<>(); userInfo.put(USERNAME_KEY, userName); userInfo.put(RID_KEY, user_rid); userInfo.put(entry.getKey(), entry.getValue()); - + //continue reading this users information until end of file or a blank line between users line = bufferedReader.readLine(); while (line != null && !line.isEmpty()) { @@ -1159,38 +1126,96 @@ class ExtractRegistry extends Extract { line = bufferedReader.readLine(); } users.add(userInfo); - + userName = ""; } line = bufferedReader.readLine(); } } + /** + * Maps the user groups to the sid that are a part of them. + * + * @param bufferedReader + * + * @return A map if sid and the groups they map too + * + * @throws IOException + */ + Map> readGroups(BufferedReader bufferedReader) throws IOException { + HashMap> groupMap = new HashMap<>(); + + String line = bufferedReader.readLine(); + + int userCount = 0; + String groupName = null; + + while (line != null && !line.contains(SECTION_DIVIDER)) { + + if (line.contains("Group Name")) { + String value = line.replaceAll("Group Name\\s*?:", "").trim(); + groupName = (value.replaceAll("\\[\\d*?\\]", "")).trim(); + int startIndex = value.indexOf('['); + int endIndex = value.indexOf(']'); + + if (startIndex != -1 && endIndex != -1) { + String countStr = value.substring(startIndex + 1, endIndex); + userCount = Integer.parseInt(countStr); + } + } else if (line.matches("Users\\s*?:")) { + for (int i = 0; i < userCount; i++) { + line = bufferedReader.readLine(); + if (line != null) { + String sid = line.trim(); + List groupList = groupMap.get(sid); + if (groupList == null) { + groupList = new ArrayList<>(); + groupMap.put(sid, groupList); + } + groupList.add(groupName); + } + } + groupName = null; + } + line = bufferedReader.readLine(); + } + return groupMap; + } + + /** + * Gets the key value from user account strings of the format + * key:value or + * --> value + * + * @param line String to parse + * + * @return key value pair + */ private Map.Entry getSAMKeyValue(String line) { int index = line.indexOf(':'); Map.Entry returnValue = null; String key = null; String value = null; - + if (index != -1) { key = line.substring(0, index).trim(); if (index + 1 < line.length()) { - value = line.substring(index+1).trim(); + value = line.substring(index + 1).trim(); } else { value = ""; } - + return new AbstractMap.SimpleEntry<>(key, value); - + } else if (line.contains("-->")) { key = line.replace("-->", "").trim(); value = "true"; } - + if (key != null) { - returnValue = new AbstractMap.SimpleEntry<>(key, value); + returnValue = new AbstractMap.SimpleEntry<>(key, value); } - + return returnValue; } From 37e1f043ed8b659c5eccb461a714edde2c2929e1 Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Fri, 6 Sep 2019 13:29:23 -0400 Subject: [PATCH 19/46] Initial check in --- .../logicalimager/dsp/AddLogicalImageTask.java | 11 ++++++++--- .../logicalimager/dsp/Bundle.properties-MERGED | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java index 72600f720c..f259b6bfb9 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -190,6 +191,7 @@ final class AddLogicalImageTask extends AddMultipleImageTask { private void addInterestingFiles(File src, Path resultsPath) throws IOException, TskCoreException { Map> imagePaths = currentCase.getSleuthkitCase().getImagePaths(); Map imagePathToObjIdMap = imagePathsToDataSourceObjId(imagePaths); + long totalFiles = Files.lines(resultsPath).count() - 1; // skip the header line try (BufferedReader br = new BufferedReader(new InputStreamReader( new FileInputStream(resultsPath.toFile()), "UTF8"))) { // NON-NLS @@ -198,9 +200,9 @@ final class AddLogicalImageTask extends AddMultipleImageTask { int lineNumber = 2; while ((line = br.readLine()) != null) { String[] fields = line.split("\t", -1); // NON-NLS - if (fields.length != 9) { - throw new IOException(Bundle.AddLogicalImageTask_notEnoughFields(lineNumber, fields.length, 9)); - } +// if (fields.length != 9) { +// throw new IOException(Bundle.AddLogicalImageTask_notEnoughFields(lineNumber, fields.length, 9)); +// } String vhdFilename = fields[0]; String targetImagePath = Paths.get(src.toString(), vhdFilename).toString(); @@ -218,6 +220,9 @@ final class AddLogicalImageTask extends AddMultipleImageTask { String filename = fields[7]; // String parentPath = fields[8]; + if (lineNumber % 100 == 0) { + progressMonitor.setProgressText(String.format("Adding interesting file %d of %d", lineNumber, totalFiles)); + } String query = String.format("data_source_obj_id = '%s' AND meta_addr = '%s' AND name = '%s'", // NON-NLS dataSourceObjId.toString(), fileMetaAddressStr, filename); List matchedFiles = Case.getCurrentCase().getSleuthkitCase().findAllFilesWhere(query); diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED index 76b82c57ad..dfcde750b9 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED @@ -5,6 +5,8 @@ AddLogicalImageTask.addingInterestingFiles=Adding search results as interesting files # {0} - file AddLogicalImageTask.addingToReport=Adding {0} to report +# {0} - target image path +AddLogicalImageTask.cannotFindDataSourceObjId=Cannot find obj_id in tsk_image_names for {0} # {0} - SearchResults.txt # {1} - directory AddLogicalImageTask.cannotFindFiles=Cannot find {0} in {1} From 892a33e942ff5d7f4d9d974f1bc4274336eef96a Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Fri, 6 Sep 2019 16:25:12 -0400 Subject: [PATCH 20/46] Update Bundle.properties-MERGED --- .../autopsy/logicalimager/dsp/Bundle.properties-MERGED | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED index fd08147b08..b5c2e7963e 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED @@ -2,7 +2,13 @@ # To change this template file, choose Tools | Templates # and open the template in the editor. +# {0} - file number +# {1} - total files +AddLogicalImageTask.addingExtractedFile=Adding extracted file {0} of {1} AddLogicalImageTask.addingExtractedFiles=Adding extracted files +# {0} - file number +# {1} - total files +AddLogicalImageTask.addingInterestingFile=Adding interesting file {0} of {1} AddLogicalImageTask.addingInterestingFiles=Adding search results as interesting files # {0} - file AddLogicalImageTask.addingToReport=Adding {0} to report @@ -21,6 +27,7 @@ AddLogicalImageTask.doneAddingInterestingFiles=Done adding search results as int # {0} - file AddLogicalImageTask.doneAddingToReport=Done adding {0} to report AddLogicalImageTask.doneCopying=Done copying +AddLogicalImageTask.errorAddingExtractedFiles=Error adding extracted files # {0} - reason AddLogicalImageTask.failedToAddInterestingFiles=Failed to add interesting files: {0} # {0} - file @@ -29,6 +36,8 @@ AddLogicalImageTask.failedToAddReport=Failed to add report {0}. Reason= {1} # {0} - src # {1} - dest AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1} +# {0} - reason +AddLogicalImageTask.failedToGetTotalFilesCount=Failed to get total files count: {0} # {0} - file AddLogicalImageTask.failToGetCanonicalPath=Fail to get canonical path for {0} AddLogicalImageTask.ingestionCancelled=Ingestion cancelled From e9fe824865ce5cbb4bf28f6520c4efae92955b7f Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Fri, 6 Sep 2019 16:27:39 -0400 Subject: [PATCH 21/46] Update AddLogicalImageTask.java --- .../logicalimager/dsp/AddLogicalImageTask.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java index 7b3fe30dd8..3112385450 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java @@ -411,14 +411,14 @@ final class AddLogicalImageTask implements Runnable { //addLocalFile here fileImporter.addLocalFile( - Paths.get(src.toString(), extractedFilePath).toFile(), - filename, - parentPath, - Long.parseLong(ctime), - Long.parseLong(crtime), - Long.parseLong(atime), - Long.parseLong(mtime), - localFilesDataSource); + Paths.get(src.toString(), extractedFilePath).toFile(), + filename, + parentPath, + Long.parseLong(ctime), + Long.parseLong(crtime), + Long.parseLong(atime), + Long.parseLong(mtime), + localFilesDataSource); lineNumber++; } // end reading file From d384937471bf32e4ec69be2d6e3c47a69351ce84 Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Fri, 6 Sep 2019 17:07:15 -0400 Subject: [PATCH 22/46] Fix codacy error --- .../dsp/AddLogicalImageTask.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java index 3112385450..e018a352cc 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java @@ -70,7 +70,6 @@ final class AddLogicalImageTask implements Runnable { private final DataSourceProcessorProgressMonitor progressMonitor; private final Blackboard blackboard; private final Case currentCase; - private Map> imagePaths; private Map imagePathToObjIdMap; private long totalFiles; @@ -176,10 +175,6 @@ final class AddLogicalImageTask implements Runnable { } } - AddMultipleImageTask addMultipleImageTask = null; - List newDataSources = new ArrayList<>(); - boolean createVHD; - Path resultsPath = Paths.get(dest.toString(), resultsFilename); try { totalFiles = Files.lines(resultsPath).count() - 1; // skip the header line @@ -189,6 +184,10 @@ final class AddLogicalImageTask implements Runnable { return; } + AddMultipleImageTask addMultipleImageTask = null; + List newDataSources = new ArrayList<>(); + boolean createVHD; + if (imagePaths.isEmpty()) { createVHD = false; // No VHD in src directory, try ingest the root directory using Logical File Set @@ -282,15 +281,15 @@ final class AddLogicalImageTask implements Runnable { } private Map imagePathsToDataSourceObjId(Map> imagePaths) { - Map imagePathToObjIdMap = new HashMap<>(); + Map imagePathToObjId = new HashMap<>(); for (Map.Entry> entry : imagePaths.entrySet()) { Long key = entry.getKey(); List names = entry.getValue(); for (String name : names) { - imagePathToObjIdMap.put(name, key); + imagePathToObjId.put(name, key); } } - return imagePathToObjIdMap; + return imagePathToObjId; } @Messages({ @@ -299,8 +298,8 @@ final class AddLogicalImageTask implements Runnable { "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingInterestingFile=Adding interesting file {0} of {1}" }) private void addInterestingFiles(Path resultsPath, boolean createVHD) throws IOException, TskCoreException { - imagePaths = currentCase.getSleuthkitCase().getImagePaths(); - imagePathToObjIdMap = imagePathsToDataSourceObjId(imagePaths); + Map> objIdToimagePathsMap = currentCase.getSleuthkitCase().getImagePaths(); + imagePathToObjIdMap = imagePathsToDataSourceObjId(objIdToimagePathsMap); try (BufferedReader br = new BufferedReader(new InputStreamReader( new FileInputStream(resultsPath.toFile()), "UTF8"))) { // NON-NLS From 042975b980e6c085b8da1d3ac5b2823e357b914a Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 9 Sep 2019 13:27:17 -0400 Subject: [PATCH 23/46] Added a utility method to utf-8 sanitize file names --- .../org/sleuthkit/autopsy/coreutils/FileUtil.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java index 5b432124ba..4a7e6da65f 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.coreutils; import java.io.File; import java.io.IOException; +import java.nio.charset.Charset; import java.util.logging.Level; import org.openide.filesystems.FileObject; import java.nio.file.Files; @@ -171,6 +172,18 @@ public class FileUtil { //with underscores. We are only keeping \ as it could be part of the path. return fileName.replaceAll("[\\p{Cntrl}/:\"*?<>|]+", "_"); } + + /** + * UTF-8 sanitize and escape special characters in a file name or a file name component + * + * @param fileName to escape + * + * @return Sanitized string + */ + public static String utf8SanitizeFileName(String fileName) { + Charset charset = Charset.forName("UTF-8"); + return charset.decode(charset.encode(escapeFileName(fileName))).toString(); + } /** * Test if the current user has read and write access to the dirPath. From ce841f2c3b677f9250c88eba25f9081a4201b3b2 Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Tue, 10 Sep 2019 10:34:12 -0400 Subject: [PATCH 24/46] Fix PR comments --- .../autopsy/logicalimager/dsp/AddLogicalImageTask.java | 7 +++---- .../autopsy/logicalimager/dsp/Bundle.properties-MERGED | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java index e018a352cc..7cce2416f9 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java @@ -295,7 +295,7 @@ final class AddLogicalImageTask implements Runnable { @Messages({ "# {0} - line number", "# {1} - fields length", "# {2} - expected length", "AddLogicalImageTask.notEnoughFields=File does not contain enough fields at line {0}, got {1}, expecting {2}", "# {0} - target image path", "AddLogicalImageTask.cannotFindDataSourceObjId=Cannot find obj_id in tsk_image_names for {0}", - "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingInterestingFile=Adding interesting file {0} of {1}" + "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingInterestingFile=Adding interesting file ({0}/{1})" }) private void addInterestingFiles(Path resultsPath, boolean createVHD) throws IOException, TskCoreException { Map> objIdToimagePathsMap = currentCase.getSleuthkitCase().getImagePaths(); @@ -361,8 +361,7 @@ final class AddLogicalImageTask implements Runnable { } @Messages({ - "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingExtractedFile=Adding extracted file {0} of {1}", - "AddLogicalImageTask.errorAddingExtractedFiles=Error adding extracted files" + "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingExtractedFile=Adding extracted file ({0}/{1})" }) private void addExtractedFiles(File src, Path resultsPath, List newDataSources) throws TskCoreException, IOException { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); @@ -428,7 +427,7 @@ final class AddLogicalImageTask implements Runnable { } catch (NumberFormatException | TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error adding extracted files", ex); // NON-NLS rollbackTransaction(trans); - throw new TskCoreException(Bundle.AddLogicalImageTask_errorAddingExtractedFiles(), ex); + throw new TskCoreException("Error adding extracted files", ex); } } diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED index b5c2e7963e..6636cdda9f 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle.properties-MERGED @@ -4,11 +4,11 @@ # {0} - file number # {1} - total files -AddLogicalImageTask.addingExtractedFile=Adding extracted file {0} of {1} +AddLogicalImageTask.addingExtractedFile=Adding extracted file ({0}/{1}) AddLogicalImageTask.addingExtractedFiles=Adding extracted files # {0} - file number # {1} - total files -AddLogicalImageTask.addingInterestingFile=Adding interesting file {0} of {1} +AddLogicalImageTask.addingInterestingFile=Adding interesting file ({0}/{1}) AddLogicalImageTask.addingInterestingFiles=Adding search results as interesting files # {0} - file AddLogicalImageTask.addingToReport=Adding {0} to report @@ -27,7 +27,6 @@ AddLogicalImageTask.doneAddingInterestingFiles=Done adding search results as int # {0} - file AddLogicalImageTask.doneAddingToReport=Done adding {0} to report AddLogicalImageTask.doneCopying=Done copying -AddLogicalImageTask.errorAddingExtractedFiles=Error adding extracted files # {0} - reason AddLogicalImageTask.failedToAddInterestingFiles=Failed to add interesting files: {0} # {0} - file From a8ad6eaa3d95078a92f8efec085fbeb4f4ead3d6 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Tue, 10 Sep 2019 12:12:51 -0400 Subject: [PATCH 25/46] Adding idea project files to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index fd160c9744..45c3b68db4 100644 --- a/.gitignore +++ b/.gitignore @@ -82,7 +82,8 @@ hs_err_pid*.log /RecentActivity/release/ /CentralRepository/release/ -/.idea/ +.idea/ +*.iml *.img *.vhd From 4c05fd5a219aa84fc738599cef76405433e44220 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 10 Sep 2019 17:00:41 -0400 Subject: [PATCH 26/46] Added utility method to UTF-8 sanitize a string --- Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java index 4a7e6da65f..6422fbcad2 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/FileUtil.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.coreutils; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.logging.Level; import org.openide.filesystems.FileObject; import java.nio.file.Files; @@ -181,7 +182,7 @@ public class FileUtil { * @return Sanitized string */ public static String utf8SanitizeFileName(String fileName) { - Charset charset = Charset.forName("UTF-8"); + Charset charset = StandardCharsets.UTF_8; return charset.decode(charset.encode(escapeFileName(fileName))).toString(); } From 2cfa83a50b09e399c071a601b4299c22b0fae698 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 10 Sep 2019 17:50:05 -0400 Subject: [PATCH 27/46] 5479 move SCO task creation inside SCO check for optimization --- .../autopsy/datamodel/AbstractAbstractFileNode.java | 7 +++---- .../autopsy/datamodel/BlackboardArtifactNode.java | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index e02a4ff776..f1573043ef 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -330,12 +330,11 @@ public abstract class AbstractAbstractFileNode extends A if (EamDb.isEnabled()) { properties.add(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), VALUE_LOADING, "")); } + // Get the SCO columns data in a background task + backgroundTasksPool.submit(new GetSCOTask( + new WeakReference<>(this), weakPcl)); } - // Get the SCO columns data in a background task - backgroundTasksPool.submit(new GetSCOTask( - new WeakReference<>(this), weakPcl)); - properties.add(new NodeProperty<>(MOD_TIME.toString(), MOD_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getMtime(), content))); properties.add(new NodeProperty<>(CHANGED_TIME.toString(), CHANGED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCtime(), content))); properties.add(new NodeProperty<>(ACCESS_TIME.toString(), ACCESS_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getAtime(), content))); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 0ea8b04660..b063a0f006 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -369,12 +369,11 @@ public class BlackboardArtifactNode extends AbstractContentNode(Bundle.BlackboardArtifactNode_createSheet_count_name(), Bundle.BlackboardArtifactNode_createSheet_count_displayName(), VALUE_LOADING, "")); } + // Get the SCO columns data in a background task + backgroundTasksPool.submit(new GetSCOTask( + new WeakReference<>(this), weakPcl)); } - // Get the SCO columns data in a background task - backgroundTasksPool.submit(new GetSCOTask( - new WeakReference<>(this), weakPcl)); - if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) { try { BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)); From f4a602cb2836bf93e49bc8636ecb65199bb427eb Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 11 Sep 2019 16:56:24 -0400 Subject: [PATCH 28/46] Bring Autopsy Travis build up to date with TSK Travis build. --- .travis.yml | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4bb150cd6b..6a8926993b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,55 @@ language: java sudo: required -dist: trusty +dist: bionic os: - linux + env: global: - TSK_HOME=$TRAVIS_BUILD_DIR/sleuthkit/sleuthkit + +addons: + apt: + update: true + packages: + - libafflib-dev + - libewf-dev + - libpq-dev + - autopoint + - libsqlite3-dev + - ant + - libcppunit-dev + - wget + - openjdk-8-jdk + - openjfx=8u161-b12-1ubuntu2 + - libopenjfx-java=8u161-b12-1ubuntu2 + - libopenjfx-jni=8u161-b12-1ubuntu2 + homebrew: + update: true + packages: + - ant + - libewf + - gettext + - cppunit + - afflib + python: - "2.7" -jdk: - - oraclejdk8 + before_install: - git clone https://github.com/sleuthkit/sleuthkit.git sleuthkit/sleuthkit - python setupSleuthkitBranch.py + install: - sudo apt-get install testdisk - - cd sleuthkit/sleuthkit - - sh travis_build.sh + - ./travis_install_libs.sh + script: - set -e + - echo "Building TSK..." + - cd sleuthkit/sleuthkit + - ./bootstrap && ./configure --prefix=/usr && make + - pushd bindings/java/ && ant -q dist-PostgreSQL && popd - echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r' - cd $TRAVIS_BUILD_DIR/ - ant build From 98e860df7ac4de5124da04bba1607cf37230f03f Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 11 Sep 2019 17:02:14 -0400 Subject: [PATCH 29/46] Shouldn't have moved the line that cd'd into sleuthkit. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6a8926993b..3b823acab7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,12 +42,12 @@ before_install: install: - sudo apt-get install testdisk + - cd sleuthkit/sleuthkit - ./travis_install_libs.sh script: - set -e - echo "Building TSK..." - - cd sleuthkit/sleuthkit - ./bootstrap && ./configure --prefix=/usr && make - pushd bindings/java/ && ant -q dist-PostgreSQL && popd - echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r' From 082718af2879ad41ee0136bb7ff6e8cab49ceca8 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 11 Sep 2019 17:13:24 -0400 Subject: [PATCH 30/46] Get the java version set up correctly. --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3b823acab7..fc6d41a895 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,14 @@ install: - cd sleuthkit/sleuthkit - ./travis_install_libs.sh +before_script: + - if [ $TRAVIS_OS_NAME = linux ]; then + sudo update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java; + sudo update-alternatives --set javac /usr/lib/jvm/java-8-openjdk-amd64/bin/javac; + export PATH=/usr/bin:$PATH; + unset JAVA_HOME; + fi + script: - set -e - echo "Building TSK..." From 6fd7a5cf61e440d95c399ca2b6a4ba9d5cca4483 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 11 Sep 2019 17:36:59 -0400 Subject: [PATCH 31/46] Add ant-optional package in an attempt to get JUnitTask --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index fc6d41a895..a3a67e2b46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,9 @@ dist: bionic os: - linux +jdk: + - openjdk8 + env: global: - TSK_HOME=$TRAVIS_BUILD_DIR/sleuthkit/sleuthkit @@ -18,6 +21,7 @@ addons: - autopoint - libsqlite3-dev - ant + - ant-optional - libcppunit-dev - wget - openjdk-8-jdk @@ -28,6 +32,7 @@ addons: update: true packages: - ant + - ant-optional - libewf - gettext - cppunit From 0437b9561a464de932db09546ef34ddfe755f9e6 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 11 Sep 2019 17:46:05 -0400 Subject: [PATCH 32/46] Remove jdk tag because it causes travis to error out. --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a3a67e2b46..7554bbc6a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,6 @@ dist: bionic os: - linux -jdk: - - openjdk8 - env: global: - TSK_HOME=$TRAVIS_BUILD_DIR/sleuthkit/sleuthkit From f40d95005974bd6d103c30db9f00a94b3f484d20 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 11 Sep 2019 18:02:26 -0400 Subject: [PATCH 33/46] Modified Image Gallery tables to store strings as TEXT instead of VARCHAR(255) --- .../autopsy/imagegallery/datamodel/DrawableDB.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index b13d6bebf5..e3310007fd 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -572,12 +572,12 @@ public final class DrawableDB { String sql = "CREATE TABLE if not exists drawable_files " //NON-NLS + "( obj_id BIGINT PRIMARY KEY, " //NON-NLS + " data_source_obj_id BIGINT NOT NULL, " - + " path VARCHAR(255), " //NON-NLS - + " name VARCHAR(255), " //NON-NLS + + " path TEXT, " //NON-NLS + + " name TEXT, " //NON-NLS + " created_time integer, " //NON-NLS + " modified_time integer, " //NON-NLS - + " make VARCHAR(255) DEFAULT NULL, " //NON-NLS - + " model VARCHAR(255) DEFAULT NULL, " //NON-NLS + + " make TEXT DEFAULT NULL, " //NON-NLS + + " model TEXT DEFAULT NULL, " //NON-NLS + " analyzed integer DEFAULT 0)"; //NON-NLS stmt.execute(sql); } catch (SQLException ex) { @@ -588,7 +588,7 @@ public final class DrawableDB { try { String sql = "CREATE TABLE if not exists hash_sets " //NON-NLS + "( hash_set_id INTEGER primary key," //NON-NLS - + " hash_set_name VARCHAR(255) UNIQUE NOT NULL)"; //NON-NLS + + " hash_set_name TEXT UNIQUE NOT NULL)"; //NON-NLS stmt.execute(sql); } catch (SQLException ex) { logger.log(Level.SEVERE, "Failed to create hash_sets table", ex); //NON-NLS @@ -692,8 +692,8 @@ public final class DrawableDB { String tableSchema = "( group_id " + autogenKeyType + " PRIMARY KEY, " //NON-NLS + " data_source_obj_id BIGINT DEFAULT 0, " - + " value VARCHAR(255) not null, " //NON-NLS - + " attribute VARCHAR(255) not null, " //NON-NLS + + " value TEXT not null, " //NON-NLS + + " attribute TEXT not null, " //NON-NLS + " is_analyzed integer DEFAULT 0, " + " UNIQUE(data_source_obj_id, value, attribute) )"; //NON-NLS From 6a64791fe589c48abf1748ab032880ce8a57091e Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 11 Sep 2019 21:31:34 -0400 Subject: [PATCH 34/46] Remove legacy artifact ID from tsk_event_descriptions --- test/script/tskdbdiff.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index a39bb9fc16..5518c97512 100644 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -322,6 +322,7 @@ class TskDbDiff(object): id_fs_info_table = build_id_fs_info_table(conn.cursor(), isMultiUser) id_objects_table = build_id_objects_table(conn.cursor(), isMultiUser) id_artifact_types_table = build_id_artifact_types_table(conn.cursor(), isMultiUser) + id_legacy_artifact_types = build_id_legacy_artifact_types_table(conn.cursor(), isMultiUser) id_reports_table = build_id_reports_table(conn.cursor(), isMultiUser) id_images_table = build_id_image_names_table(conn.cursor(), isMultiUser) id_obj_path_table = build_id_obj_path_table(id_files_table, id_objects_table, id_artifact_types_table, id_reports_table, id_images_table) @@ -347,7 +348,7 @@ class TskDbDiff(object): if 'INSERT INTO image_gallery_groups_seen' in dump_line: dump_line = '' continue; - dump_line = normalize_db_entry(dump_line, id_obj_path_table, id_vs_parts_table, id_vs_info_table, id_fs_info_table, id_objects_table, id_reports_table, id_images_table) + dump_line = normalize_db_entry(dump_line, id_obj_path_table, id_vs_parts_table, id_vs_info_table, id_fs_info_table, id_objects_table, id_reports_table, id_images_table, id_legacy_artifact_types) db_log.write('%s\n' % dump_line) dump_line = '' postgreSQL_db.close() @@ -361,7 +362,7 @@ class TskDbDiff(object): for line in conn.iterdump(): if 'INSERT INTO "image_gallery_groups_seen"' in line: continue - line = normalize_db_entry(line, id_obj_path_table, id_vs_parts_table, id_vs_info_table, id_fs_info_table, id_objects_table, id_reports_table, id_images_table) + line = normalize_db_entry(line, id_obj_path_table, id_vs_parts_table, id_vs_info_table, id_fs_info_table, id_objects_table, id_reports_table, id_images_table, id_legacy_artifact_types) db_log.write('%s\n' % line) # Now sort the file srtcmdlst = ["sort", dump_file, "-o", dump_file] @@ -414,7 +415,7 @@ class PGSettings(object): return self.password -def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info_table, objects_table, reports_table, images_table): +def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info_table, objects_table, reports_table, images_table, artifact_table): """ Make testing more consistent and reasonable by doctoring certain db entries. Args: @@ -591,10 +592,15 @@ def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info # replace object ids with information that is deterministic file_obj_id = int(fields_list[5]) object_id = int(fields_list[4]) + legacy_artifact_id = 'NULL' + if (fields_list[6] != 'NULL'): + legacy_artifact_id = int(fields_list[6]) if file_obj_id != 'NULL' and file_obj_id in files_table.keys(): fields_list[5] = files_table[file_obj_id] if object_id != 'NULL' and object_id in files_table.keys(): fields_list[4] = files_table[object_id] + if legacy_artifact_id != 'NULL' and legacy_artifact_id in artifact_table.keys(): + fields_list[6] = artifact_table[legacy_artifact_id] newLine = ('INSERT INTO "tsk_event_descriptions" VALUES(' + ','.join(fields_list[1:]) + ');') # remove report_id return newLine else: @@ -689,6 +695,17 @@ def build_id_artifact_types_table(db_cursor, isPostgreSQL): mapping = dict([(row[0], row[1]) for row in sql_select_execute(db_cursor, isPostgreSQL, "SELECT blackboard_artifacts.artifact_obj_id, blackboard_artifact_types.type_name FROM blackboard_artifacts INNER JOIN blackboard_artifact_types ON blackboard_artifact_types.artifact_type_id = blackboard_artifacts.artifact_type_id ")]) return mapping +def build_id_legacy_artifact_types_table(db_cursor, isPostgreSQL): + """Build the map of legacy artifact ids to artifact type. + + Args: + db_cursor: the database cursor + """ + # for each row in the db, take the legacy artifact id then create a tuple in the dictionary + # with the artifact id as the key and artifact type as the value + mapping = dict([(row[0], row[1]) for row in sql_select_execute(db_cursor, isPostgreSQL, "SELECT blackboard_artifacts.artifact_id, blackboard_artifact_types.type_name FROM blackboard_artifacts INNER JOIN blackboard_artifact_types ON blackboard_artifact_types.artifact_type_id = blackboard_artifacts.artifact_type_id ")]) + return mapping + def build_id_reports_table(db_cursor, isPostgreSQL): """Build the map of report object ids to report path. From e4bc470849b537c5dda56e438dd4c543f96bc96a Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Thu, 12 Sep 2019 10:04:14 -0400 Subject: [PATCH 35/46] Fix PR comments --- .../autopsy/logicalimager/dsp/AddLogicalImageTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java index 7cce2416f9..bd9c836e88 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java @@ -295,7 +295,7 @@ final class AddLogicalImageTask implements Runnable { @Messages({ "# {0} - line number", "# {1} - fields length", "# {2} - expected length", "AddLogicalImageTask.notEnoughFields=File does not contain enough fields at line {0}, got {1}, expecting {2}", "# {0} - target image path", "AddLogicalImageTask.cannotFindDataSourceObjId=Cannot find obj_id in tsk_image_names for {0}", - "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingInterestingFile=Adding interesting file ({0}/{1})" + "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingInterestingFile=Adding interesting files ({0}/{1})" }) private void addInterestingFiles(Path resultsPath, boolean createVHD) throws IOException, TskCoreException { Map> objIdToimagePathsMap = currentCase.getSleuthkitCase().getImagePaths(); @@ -361,7 +361,7 @@ final class AddLogicalImageTask implements Runnable { } @Messages({ - "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingExtractedFile=Adding extracted file ({0}/{1})" + "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingExtractedFile=Adding extracted files ({0}/{1})" }) private void addExtractedFiles(File src, Path resultsPath, List newDataSources) throws TskCoreException, IOException { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); From eb2660ec77d1cfb6db3f3be5e02ec4ddc3300823 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 12 Sep 2019 10:23:04 -0400 Subject: [PATCH 36/46] Added image tags to portable case --- .../autopsy/report/Bundle.properties-MERGED | 3 + .../report/PortableCaseReportModule.java | 107 +++++++++++++++++- 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties-MERGED index 53aa1acfbd..8978a1baf1 100755 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties-MERGED @@ -31,6 +31,9 @@ PortableCaseReportModule.generateReport.errorCopyingFiles=Error copying tagged f PortableCaseReportModule.generateReport.errorCopyingInterestingFiles=Error copying interesting files PortableCaseReportModule.generateReport.errorCopyingInterestingResults=Error copying interesting results PortableCaseReportModule.generateReport.errorCopyingTags=Error copying tags +PortableCaseReportModule.generateReport.errorCreatingImageTagTable=Error creating image tags table +PortableCaseReportModule.generateReport.errorCreatingReportFolder=Could not make report folder +PortableCaseReportModule.generateReport.errorGeneratingUCOreport=Problem while generating CASE-UCO report # {0} - attribute type name PortableCaseReportModule.generateReport.errorLookingUpAttrType=Error looking up attribute type {0} PortableCaseReportModule.generateReport.interestingItemError=Error loading intersting items diff --git a/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java b/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java index 3c712c067f..6cfad5aade 100644 --- a/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java @@ -36,6 +36,7 @@ import org.openide.modules.InstalledFileLocator; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; @@ -179,9 +180,12 @@ class PortableCaseReportModule implements ReportModule { "PortableCaseReportModule.generateReport.errorCopyingArtifacts=Error copying tagged artifacts", "PortableCaseReportModule.generateReport.errorCopyingInterestingFiles=Error copying interesting files", "PortableCaseReportModule.generateReport.errorCopyingInterestingResults=Error copying interesting results", + "PortableCaseReportModule.generateReport.errorCreatingImageTagTable=Error creating image tags table", "# {0} - attribute type name", "PortableCaseReportModule.generateReport.errorLookingUpAttrType=Error looking up attribute type {0}", "PortableCaseReportModule.generateReport.compressingCase=Compressing case...", + "PortableCaseReportModule.generateReport.errorCreatingReportFolder=Could not make report folder", + "PortableCaseReportModule.generateReport.errorGeneratingUCOreport=Problem while generating CASE-UCO report" }) void generateReport(String reportPath, PortableCaseOptions options, ReportProgressPanel progressPanel) { @@ -240,6 +244,14 @@ class PortableCaseReportModule implements ReportModule { return; } + // Set up the table for the image tags + try { + initializeImageTags(progressPanel); + } catch (TskCoreException ex) { + handleError("Error creating image tag table", Bundle.PortableCaseReportModule_generateReport_errorCreatingImageTagTable(), ex, progressPanel); // NON-NLS + return; + } + // Copy the selected tags progressPanel.updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingTags()); try { @@ -358,7 +370,7 @@ class PortableCaseReportModule implements ReportModule { File reportsFolder = Paths.get(caseFolder.toString(), "Reports").toFile(); if(!reportsFolder.mkdir()) { - handleError("Could not make report folder", "Could not make report folder", null, progressPanel); // NON-NLS + handleError("Could not make report folder", Bundle.PortableCaseReportModule_generateReport_errorCreatingReportFolder(), null, progressPanel); // NON-NLS return; } @@ -366,7 +378,7 @@ class PortableCaseReportModule implements ReportModule { CaseUcoFormatExporter.export(tagNames, setNames, reportsFolder, progressPanel); } catch (IOException | SQLException | NoCurrentCaseException | TskCoreException ex) { handleError("Problem while generating CASE-UCO report", - "Problem while generating CASE-UCO report", ex, progressPanel); // NON-NLS + Bundle.PortableCaseReportModule_generateReport_errorGeneratingUCOreport(), ex, progressPanel); // NON-NLS } // Compress the case (if desired) @@ -484,6 +496,22 @@ class PortableCaseReportModule implements ReportModule { currentCaseDbManager.select("max(examiner_id) as max_id from tsk_examiners", new StoreMaxIdCallback("tsk_examiners")); // NON-NLS } + /** + * Set up the image tag table in the portable case + * + * @param progressPanel + * + * @throws TskCoreException + */ + private void initializeImageTags(ReportProgressPanel progressPanel) throws TskCoreException { + + // Create the image tags table in the portable case + CaseDbAccessManager portableDbAccessManager = portableSkCase.getCaseDbAccessManager(); + if (! portableDbAccessManager.tableExists(ContentViewerTagManager.TABLE_NAME)) { + portableDbAccessManager.createTable(ContentViewerTagManager.TABLE_NAME, ContentViewerTagManager.TABLE_SCHEMA_SQLITE); + } + } + /** * Add all files with a given tag to the portable case. * @@ -496,7 +524,7 @@ class PortableCaseReportModule implements ReportModule { // Get all the tags in the current case List tags = currentCase.getServices().getTagsManager().getContentTagsByTagName(oldTagName); - + // Copy the files into the portable case and tag for (ContentTag tag : tags) { @@ -507,17 +535,88 @@ class PortableCaseReportModule implements ReportModule { Content content = tag.getContent(); if (content instanceof AbstractFile) { + + // Get the image tag data associated with this tag (empty string if there is none) + String appData = getImageTagDataForContentTag(tag); + long newFileId = copyContentToPortableCase(content, progressPanel); // Tag the file if (! oldTagNameToNewTagName.containsKey(tag.getName())) { throw new TskCoreException("TagName map is missing entry for ID " + tag.getName().getId() + " with display name " + tag.getName().getDisplayName()); // NON-NLS } - portableSkCase.addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset()); + ContentTag newContentTag = portableSkCase.addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset()); + if (! appData.isEmpty()) { + addImageTagToPortableCase(newContentTag, appData); + } } } } + /** + * Gets the image tag data for a given content tag + * + * @param tag The ContentTag in the current case + * + * @return The app_data string for this content tag or an empty string if there was none + * + * @throws TskCoreException + */ + private String getImageTagDataForContentTag(ContentTag tag) throws TskCoreException { + + GetImageTagCallback callback = new GetImageTagCallback(); + String query = "* FROM " + ContentViewerTagManager.TABLE_NAME + " WHERE content_tag_id = " + tag.getId(); + currentCase.getSleuthkitCase().getCaseDbAccessManager().select(query, callback); + return callback.getAppData(); + } + + /** + * CaseDbAccessManager callback to get the app_data string for the image tag + */ + private static class GetImageTagCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback { + + private static final Logger logger = Logger.getLogger(PortableCaseReportModule.class.getName()); + private String appData = ""; + + @Override + public void process(ResultSet rs) { + try { + while (rs.next()) { + try { + appData = rs.getString("app_data"); // NON-NLS + } catch (SQLException ex) { + logger.log(Level.WARNING, "Unable to get app_data from result set", ex); // NON-NLS + } + } + } catch (SQLException ex) { + logger.log(Level.WARNING, "Failed to get next result for app_data", ex); // NON-NLS + } + } + + /** + * Get the app_data string + * + * @return the app_data string + */ + String getAppData() { + return appData; + } + } + + /** + * Add an image tag to the portable case. + * + * @param newContentTag The content tag in the portable case + * @param appData The string to copy into app_data + * + * @throws TskCoreException + */ + private void addImageTagToPortableCase(ContentTag newContentTag, String appData) throws TskCoreException { + String insert = "(content_tag_id, app_data) VALUES (" + newContentTag.getId() + ", '" + appData + "')"; + portableSkCase.getCaseDbAccessManager().insert(ContentViewerTagManager.TABLE_NAME, insert); + } + + /** * Add all artifacts with a given tag to the portable case. * From 1b4a70bdeca1cdb74c0e980aae3b45d2f5ecea8d Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 12 Sep 2019 11:26:20 -0400 Subject: [PATCH 37/46] Fixed codacy issues --- .../recentactivity/ExtractRegistry.java | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 3a71680207..6e4d0fc4c7 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -67,8 +67,6 @@ import static java.util.TimeZone.getTimeZone; import org.openide.util.Lookup; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException; -import org.sleuthkit.autopsy.ingest.IngestServices; -import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -876,7 +874,7 @@ class ExtractRegistry extends Extract { String userInfoSection = "User Information"; String previousLine = null; String line = bufferedReader.readLine(); - Set> userSet = new HashSet<>(); + Set> userSet = new HashSet<>(); Map> groupMap = null; while (line != null) { if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) { @@ -890,9 +888,9 @@ class ExtractRegistry extends Extract { previousLine = line; line = bufferedReader.readLine(); } - Map> userInfoMap = new HashMap<>(); + Map> userInfoMap = new HashMap<>(); //load all the user info which was read into a map - for (HashMap userInfo : userSet) { + for (Map userInfo : userSet) { userInfoMap.put(userInfo.get(SID_KEY), userInfo); } //get all existing OS account artifacts @@ -903,7 +901,7 @@ class ExtractRegistry extends Extract { BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); if (existingUserId != null) { String userID = existingUserId.getValueString().trim(); - HashMap userInfo = userInfoMap.remove(userID); + Map userInfo = userInfoMap.remove(userID); //if the existing user id matches a user id which we parsed information for check if that information exists and if it doesn't add it if (userInfo != null) { osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID), true)); @@ -912,7 +910,7 @@ class ExtractRegistry extends Extract { } } //add remaining userinfos as accounts; - for (HashMap userInfo : userInfoMap.values()) { + for (Map userInfo : userInfoMap.values()) { BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)), false)); // index the artifact for keyword search @@ -943,7 +941,7 @@ class ExtractRegistry extends Extract { * * @throws ParseException */ - Collection getAttributesForAccount(HashMap userInfo, List groupList, boolean existingUser) throws ParseException { + Collection getAttributesForAccount(Map userInfo, List groupList, boolean existingUser) throws ParseException { Collection bbattributes = new ArrayList<>(); SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'"); @@ -1062,8 +1060,8 @@ class ExtractRegistry extends Extract { getRAModuleName(), settingString)); } - if (groupList != null && groupList.size() > 0) { - String groups = new String(); + if (groupList != null && groupList.isEmpty()) { + String groups = ""; for (String group : groupList) { groups += group + ", "; } @@ -1086,7 +1084,7 @@ class ExtractRegistry extends Extract { * * @throws IOException */ - private void readUsers(BufferedReader bufferedReader, Set> users) throws IOException { + private void readUsers(BufferedReader bufferedReader, Set> users) throws IOException { String line = bufferedReader.readLine(); //read until end of file or next section divider String userName = ""; @@ -1131,7 +1129,7 @@ class ExtractRegistry extends Extract { * @throws IOException */ Map> readGroups(BufferedReader bufferedReader) throws IOException { - HashMap> groupMap = new HashMap<>(); + Map> groupMap = new HashMap<>(); String line = bufferedReader.readLine(); @@ -1193,8 +1191,6 @@ class ExtractRegistry extends Extract { value = ""; } - return new AbstractMap.SimpleEntry<>(key, value); - } else if (line.contains("-->")) { key = line.replace("-->", "").trim(); value = "true"; From 6aa6d66d60a6d774d64b66276133bd934e1ffad1 Mon Sep 17 00:00:00 2001 From: Raman Date: Thu, 12 Sep 2019 11:55:10 -0400 Subject: [PATCH 38/46] Address log levels. --- InternalPythonModules/android/imo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InternalPythonModules/android/imo.py b/InternalPythonModules/android/imo.py index 9b3ec78528..e089248e5f 100644 --- a/InternalPythonModules/android/imo.py +++ b/InternalPythonModules/android/imo.py @@ -133,9 +133,9 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): except SQLException as ex: - self._logger.log(Level.SEVERE, "Error processing query result for IMO friends", ex) + self._logger.log(Level.WARNING, "Error processing query result for IMO friends", ex) except TskCoreException as ex: - self._logger.log(Level.SEVERE, "Failed to create AppDBParserHelper for adding artifacts.", ex) + self._logger.log(Level.WARNING, "Failed to create AppDBParserHelper for adding artifacts.", ex) finally: friendsDb.close() From b5301e689a8b6e683f9453af774db97f59c330c5 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 12 Sep 2019 15:14:24 -0400 Subject: [PATCH 39/46] Fix incorrect use of Autopsy Logger in RegressionTest class --- .../src/org/sleuthkit/autopsy/testing/RegressionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java index 0a7feaa46c..8f1ef48a4c 100644 --- a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java +++ b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java @@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.testing; import java.io.File; import java.io.IOException; -import org.sleuthkit.autopsy.coreutils.Logger; +import java.util.logging.Logger; import junit.framework.Test; import junit.framework.TestCase; import org.netbeans.jemmy.Timeouts; From 7b5ac994a70f03011e328166e9826daefc23aaed Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 12 Sep 2019 17:53:34 -0400 Subject: [PATCH 40/46] Fix incorrect use of Autopsy Logger in AutopsyTestCases class --- .../src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java | 4 ++-- .../src/org/sleuthkit/autopsy/testing/RegressionTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java b/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java index dd877b3a11..8ad09e4921 100644 --- a/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java +++ b/Testing/src/org/sleuthkit/autopsy/testing/AutopsyTestCases.java @@ -31,8 +31,8 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; +import java.util.logging.Logger; import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; import javax.imageio.ImageIO; import javax.swing.JDialog; import javax.swing.text.JTextComponent; @@ -66,7 +66,7 @@ import org.sleuthkit.datamodel.TskData; public class AutopsyTestCases { - private static final Logger logger = Logger.getLogger(AutopsyTestCases.class.getName()); + private static final Logger logger = Logger.getLogger(AutopsyTestCases.class.getName()); // DO NOT USE AUTOPSY LOGGER private long start; /** diff --git a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java index 8f1ef48a4c..6f6e04d7bd 100644 --- a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java +++ b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java @@ -40,7 +40,7 @@ import org.netbeans.junit.NbModuleSuite; */ public class RegressionTest extends TestCase { - private static final Logger logger = Logger.getLogger(RegressionTest.class.getName()); + private static final Logger logger = Logger.getLogger(RegressionTest.class.getName()); // DO NOT USE AUTOPSY LOGGER private static final AutopsyTestCases autopsyTests = new AutopsyTestCases(Boolean.parseBoolean(System.getProperty("isMultiUser"))); /** From 9a22b39a9aa3e87faf27a6747c4cc0eb402ff7ff Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 13 Sep 2019 09:59:09 -0400 Subject: [PATCH 41/46] Codacy --- .../sleuthkit/autopsy/report/PortableCaseReportModule.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java b/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java index 6cfad5aade..0910b2a2ea 100644 --- a/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/PortableCaseReportModule.java @@ -536,9 +536,6 @@ class PortableCaseReportModule implements ReportModule { Content content = tag.getContent(); if (content instanceof AbstractFile) { - // Get the image tag data associated with this tag (empty string if there is none) - String appData = getImageTagDataForContentTag(tag); - long newFileId = copyContentToPortableCase(content, progressPanel); // Tag the file @@ -546,6 +543,10 @@ class PortableCaseReportModule implements ReportModule { throw new TskCoreException("TagName map is missing entry for ID " + tag.getName().getId() + " with display name " + tag.getName().getDisplayName()); // NON-NLS } ContentTag newContentTag = portableSkCase.addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset()); + + // Get the image tag data associated with this tag (empty string if there is none) + // and save it if present + String appData = getImageTagDataForContentTag(tag); if (! appData.isEmpty()) { addImageTagToPortableCase(newContentTag, appData); } From b0238448515837fb9ab232d6617fbb4aa027f862 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 13 Sep 2019 11:10:01 -0400 Subject: [PATCH 42/46] Update Doxyfile --- docs/doxygen-dev/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/doxygen-dev/Doxyfile b/docs/doxygen-dev/Doxyfile index 231f5716fc..b8412f61ef 100755 --- a/docs/doxygen-dev/Doxyfile +++ b/docs/doxygen-dev/Doxyfile @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = dev-docs +OUTPUT_DIRECTORY = build-docs # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and From 27c4ead7ed0e4670f5c2cceb87ac08d66d491c24 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 13 Sep 2019 11:12:39 -0400 Subject: [PATCH 43/46] Update for new doxygen build folder --- build.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.xml b/build.xml index 6d7a1a0315..1f00a24f79 100644 --- a/build.xml +++ b/build.xml @@ -77,7 +77,7 @@ - + @@ -265,7 +265,7 @@ - + From c9d3b6309f21fe41410610322d8a184f444d1859 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 13 Sep 2019 13:45:15 -0400 Subject: [PATCH 44/46] 5504 add red x to carved file icon --- .../sleuthkit/autopsy/datamodel/FileNode.java | 2 +- .../autopsy/datamodel/LayoutFileNode.java | 2 +- .../autopsy/datamodel/SlackFileNode.java | 2 +- .../autopsy/images/carved-file-x-icon-16.png | Bin 0 -> 6611 bytes 4 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/images/carved-file-x-icon-16.png diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java index 7b3a55c20b..c194268d9f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java @@ -128,7 +128,7 @@ public class FileNode extends AbstractFsContentNode { private void setIcon(AbstractFile file) { if (file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) { if (file.getType().equals(TSK_DB_FILES_TYPE_ENUM.CARVED)) { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png"); //NON-NLS + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-x-icon-16.png"); //NON-NLS } else { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java index 8f7f753db2..c33fdc59c4 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java @@ -73,7 +73,7 @@ public class LayoutFileNode extends AbstractAbstractFileNode { this.setDisplayName(nameForLayoutFile(lf)); if (lf.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED)) { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png"); //NON-NLS + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-x-icon-16.png"); //NON-NLS } else if (lf.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE)) { if (lf.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java index 0e7bce56cc..791b586404 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java @@ -63,7 +63,7 @@ public class SlackFileNode extends AbstractFsContentNode { // set name, display name, and icon if (file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) { if (file.getType().equals(TSK_DB_FILES_TYPE_ENUM.CARVED)) { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png"); //NON-NLS + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-x-icon-16.png"); //NON-NLS } else { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS } diff --git a/Core/src/org/sleuthkit/autopsy/images/carved-file-x-icon-16.png b/Core/src/org/sleuthkit/autopsy/images/carved-file-x-icon-16.png new file mode 100644 index 0000000000000000000000000000000000000000..75a935bf9e30136c5e4f8707f6facbc5b75d822c GIT binary patch literal 6611 zcmeHLdpy(o|DXFM<<|XjTH}PY%V!(2WrPirMXc!FY@c1qE`2sObkS9gI65kqRC0== zq;jItjnMr>Nx6hXNs3A?Mf^S+r}X=F`hI&nzTf}CZ130m`Fg(J@8|3C-WKgU-($4l zWJ3f3F`D5?^MjvFR1bY!`2Y0IK{f)RQxnb#l>4z2NGT-Y34=kTJWL8AL8Xv~KqzaD z2dshKSsV42*>vmcYnWYYT%1R$YLaxGx zYMIr|+Z(9GE&Y@FQi~I{>yIS%SKHz@9Of9ynYNdjTdQm?RJ{*va-z}NyI&r#xXCSb zTIutC%I~cc*Oy`X1o1h_nITMYPx(pY{tE^4N1F#DbF=3(F4`y3Sv}exeRVv`jNBX^ zpXr{g+troBGEG<18Pwldc+u=oq-DCesvkS{=1l498Cxe>3Or|c z#5rxB_==-z;s9Jxp6bUzqT$+05qKXhM8y>3usgsZ+ZIL?K+yM<*|QThDBs z$+IWh``ScV7i(wUr5Wjen2#|kI2D2H`B|)6{n19;J`Liz_E^Oe%nPiVotnCJ^Y$h_ zdaEhOacv%Jcq4FwVE6tfWq4Z0*p2V(ou3y@o0M8=R(<#NCdYhpn@7I5u|#lx{<+GJ zZ%2owbkriQEH={dejXcuJdpleaO)@P?V{Nca-hPXD^bEZ^?qZe`{Y+a*=combh^*Z zEifPZTf+UsO3v{aInE|~$(P#BG;W=f3T-oQin|L~6^|;<7POstPqNOiO}8~tuq$UA zw4GX-atm^_NKMe~+8sLTL|$JuPj`2;Zq%Fu+6T@Y+|KRqiw`dFJMuJrS4NH~dD@jj z$5>ss+Bxl~g4;Q@VY7FvJ#o3_!|dkvbH_TUIZKWeyV&g)i;kFRfXH<-S2T^G&)aqHK+_{bzgqLG z(8G@se|q|2-^v>|I?sL_px%5QuqzZZidScv+qSgI3yrvb1`;mXRLw`%Dcy@uab(1TSI;M$M`juSJ0pR8NWW=E^fE{?T+1< zJBpv@_)Wg#wM;qju-)iI=W6ByanPa~_WZiGX|`i*&Low+VYMv!^Zk{KYyHvp8#*)- zoTtY=3ma_Qo39u7m#0O=e4no3hO=Y-DAILR&fS{ts$1cI<=kYwmcLA5sJNDjj}eO; z>z|o3#bqC8>C&tD7KQ$`F`?pY^n<#ax0iRLm^wmy+YCl=Hk~B7Y+T;I(y3wQ9LzJb zmf|33%{#xfCX|rFWo>&t*v76XjGR#x6R^4}B-QSuHtE+5mwLRrly+HnLr1kPkh$!z zXz~o`&RlYYX5--!o|&ape%h^@;kAwsLCU4d=DeT2z(dC=oSS2n^JZyI3hD5AyH@h; z#}75)R$p7{>cnXoZ#>TXwbo_p4~u`&$+~9T8*zW#1D|a-$LSYUYiVB5BgJ9zjDDFi zSkYO1KIvF72Fjo0nY7|&VxeZ)(px4WGq=y$&{WvpUecS}5es_b)HS4abOz} zfza3{baV4%xVa&H{e0XR-gLOPr>@^c^(>w{wRENbky&U|sEO$f-~F?9c&*(%YkZNb z(Dw9;RZ!~$qR`WC*;Ji}o3~7lS*SOGzkJ#<9hcWyC8d>&yL7MqmHqq=C zE^2KJPtM{!v`kyQch^pOsdwnYcNfzqXc(;;YZ{##?wFUfy{)$(D(ZxSecdn-O(J{&`4!OeC)Sl=q+155CEhXl<%j0`@wdEE|Qb#ezD|zLfRxQz6N`ek; zc{+wicl-Ikj4?Jx-QT-jWpC>o&(B*19*=lC;e)Kk>z6j7he@&76VJI@ch2&%E_O{? z6g$?OQS)m-Z`8g4?Q>jcPvP}bk%lZ!rgQJ~{`LpAeSFA_0qgRQLABF4k&+35`@wyE zRryn_B6}vCy;n2fH7)6*<;4dNTs`Iv+Dq5gJ!qyrhV&+e-}~8ZwbzOiS102O2k(-= zO+`!7B!9IY&-=AP56N7PZb0Zo6)HF7K3ra3S5aMinZM-YM?}FLsKmP3%NxFeQ9}6I z4P<&#I1&+t&6Na!7^O%GU&{!Dqq9=V=Bxqb$RLm}6jMLM{~*V8_HUrEZ`= z=ot=y{^9dkobWXqG8g6SWay}*zyu;t&PFOl!D1OjNkyr7De!BR8H+-yA@Vg;R3OtA z=_Y|dBoRZz;LvoXFcgn+GDJE;Tpq=b<~~dTkEketTrQ zJ@oT>U-gi&;CDY*KTswKfjA&N6co!XMlLFo`+=V|`41>y_!k7y;1Jo!O^3)pl}UZ@ zU@i{}pGv*;k&AjTn7*HURB_-7MN+kg3Oy3Z<$S_PL!e+ahReZ%!Jr5}i40~2zQDu& zpB%n=7&WukTO}1>XYW8D+v6Mn5Y zmqT%fIoWX12}Nu^h?R=@>IqmsiW>y7u9p#~HzR7-_Ks*9e&=BQMpqGaq)kgE;> ztmDuWN5B^ILAbjPSH|CV;a3vYp6dYOKpcQ}u;&rcL;xV7gLqs!G=adeBaz4iGMD7= zCA&<*lPlN|=)#9f2aYpbx#~D0t%vi>=1aUn0IHG*2awS?G8!PT00Mw|5(KU{hL(`s|EKm%GXpG>H+}m zAN_|DRn_Py3{@fche)NtLJ;~get+llKj0ic+lOoC-?@*34SBmsq+xIu5y*WM;%_eh z72ptqw~zyhWs+}geI#TkTqCYSc+W#N_?m@pZS1FOdpLVl1^z$$8Lo=|;R-PIk43&q z-yd@Qkn6h?_%85|?D`?scPa2);2+ubUz5x5^9O%W48I>$z#r?6(+u~*UkT_2&GVok z235al7c&!Ji-FX0u?&I0Sg0Nv$|KI9uu)IWVAA!P3`U!xY?h{oZQ(C|&NFB(EQecr z5{l+kuqR$~?rS{~v-vruzDI9|vZL9gB0^CYXC9eG~ zYSG=pX*F!xRU|H?VtPt`c!MPB;6Pz@>V`)0g{Y2}uuC0%7d)R_n7nUiTT#VU%SMFf z(ZHvZ&kfQZeh3GyYAPfDd=YASv@HPJX?J;y@^wvTlB9cOW8bgLUzSeM){MGn8!J9u zx+DhJo>k4Cbv7b=5M;*Kb`UA16L2pZT+YSiPA@WS$Gq=C)h?Z~u6H;1+Pwk&c+A{a z&u;IWT-=B#O5@{ogMh3f+dPuXrtThqvMg@LG;78+O(kfpTC@7_GoDT2dBO2gOEa_U zr_Z$Uiz=@zTk*R&pivwZvhLoK@_6msL-9M?f@*6leT70s^2?O*0rfBHn-(wJIm@87 zqRFM8;6nTH<2SjNTf?BmoP@P|6iyn5lZWCJ+I!L$TwK@njMZsS*dedcduf$0;J-hA ziqqrvVw*h~nd>7(f^sosc~?Sj#AAmscOFeWdaNm6*0#~Q=gO;Z-05G}b#P|%{kBTy z{7WnPnwkcxB6jTiq-nm8?g|MEP_FwPs?##wfX-5 D>kTha literal 0 HcmV?d00001 From 1289c5577268d40d67da6b106f7a3b66af932113 Mon Sep 17 00:00:00 2001 From: Raman Date: Mon, 16 Sep 2019 14:14:00 -0400 Subject: [PATCH 45/46] 5492: Refactor AppDBParserHelper - moved to Sleuthkit/datamodel --- .../autopsy/coreutils/AppDBParserHelper.java | 1321 ----------------- InternalPythonModules/android/imo.py | 10 +- 2 files changed, 6 insertions(+), 1325 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java b/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java deleted file mode 100644 index 538ea07098..0000000000 --- a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * 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.coreutils; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import org.apache.commons.lang3.StringUtils; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.AccountFileInstance; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; -import org.sleuthkit.datamodel.Account; -import org.sleuthkit.datamodel.Blackboard; -import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.datamodel.Relationship; -import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskDataException; - - -/** - * A helper class to support modules that parse SQLite databases from mobile - * apps and create artifacts. - */ -public final class AppDBParserHelper { - - private static final Logger logger = Logger.getLogger(AppDBParserHelper.class.getName()); - - /** - * Enum for message read status - */ - public enum MessageReadStatusEnum { - - UNKNOWN, /// read status is unknown - UNREAD, /// message has not been read - READ /// message has been read - } - - /** - * Enum for call/message direction - */ - public enum CommunicationDirection - { - UNKNOWN("Unknown"), - INCOMING("Incoming"), - OUTGOING("Outgoing"); - - private final String dirStr; - - CommunicationDirection(String dir) { - this.dirStr = dir; - } - - public String getString() { - return dirStr; - } - } - - /** - * Enum for call media type - */ - public enum CallMediaType - { - UNKNOWN("Unknown"), - AUDIO("Audio"), - VIDEO("Video"); - - private final String typeStr; - - CallMediaType(String type) { - this.typeStr = type; - } - - public String getString() { - return typeStr; - } - } - - - private final AbstractFile dbAbstractFile; - private final String moduleName; - - // 'self' account for the application. - private final AccountFileInstance selfAccountInstance; - - // type of accounts to be created for the Application using this helper - private final Account.Type accountsType; - - /** - * Constructs a AppDB parser helper for the given DB file. - * - * This is a constructor for Apps that that do not have any app specific account information - * for device owner and will use a 'Device' account in lieu. - * - * It creates a DeviceAccount instance to use as a self account. - * - * @param moduleName name module using the helper - * @param dbFile database file being parsed by the module - * @param accountsType account types created by this module - * - * @throws TskCoreException - */ - public AppDBParserHelper(String moduleName, AbstractFile dbFile, Account.Type accountsType) throws TskCoreException { - - this.moduleName = moduleName; - this.dbAbstractFile = dbFile; - this.accountsType = accountsType; - this.selfAccountInstance = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.DEVICE, ((DataSource)dbFile.getDataSource()).getDeviceId(), moduleName, dbFile); - } - - /** - * Constructs a AppDB parser helper for the given DB file. - * - * This constructor is for Apps that do have app specific account information - * for the device owner to create a 'self' account. - * - * It creates a an account instance with specified type & id and uses it as - * a self account. - * - * @param moduleName name module using the helper - * @param dbFile database file being parsed by the module - * @param accountsType account types created by this module - * @param selfAccountType self account type to be created for this module - * @param selfAccountAddress account unique id for the self account - * - * @throws TskCoreException - */ - public AppDBParserHelper(String moduleName, AbstractFile dbFile, Account.Type accountsType, Account.Type selfAccountType, Account.Address selfAccountAddress) throws TskCoreException { - - this.moduleName = moduleName; - this.dbAbstractFile = dbFile; - this.accountsType = accountsType; - - this.selfAccountInstance = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(selfAccountType, selfAccountAddress.getUniqueID(), moduleName, dbFile); - } - - /** - * Constructs a AppDB parser helper for the given DB file. - * - * This is a constructor for Apps that do not need to create any - * accounts/relationships. - * - * @param moduleName name of module parsing the DB - * @param dbFile db file - * - */ - public AppDBParserHelper(String moduleName, AbstractFile dbFile) { - this.moduleName = moduleName; - this.dbAbstractFile = dbFile; - this.selfAccountInstance = null; - this.accountsType = null; - } - - - /** - * Creates and adds a TSK_CONTACT artifact to the case, with specified - * attributes. - * Also creates an account instance of specified type for the contact with the - * specified ID. - * - * @param contactAccountUniqueID unique id for the contact's account - * @param contactName Name of contact - * @param phoneNumber primary phone number for contact - * @param homePhoneNumber home phone number - * @param mobilePhoneNumber mobile phone number, - * @param emailAddr Email address for contact - * - * @return artifact created - * - */ - public BlackboardArtifact addContact(String contactAccountUniqueID, String contactName, - String phoneNumber, String homePhoneNumber, - String mobilePhoneNumber, String emailAddr) { - return addContact(contactAccountUniqueID, contactName,phoneNumber, - homePhoneNumber,mobilePhoneNumber, emailAddr, - Collections.emptyList() ); - } - - - /** - * Creates and adds a TSK_CONTACT artifact to the case, with specified - * attributes. - * Also creates an account instance for the contact with the - * specified ID. - * - * @param contactAccountUniqueID unique id for contact account - * @param contactName Name of contact - * @param phoneNumber primary phone number for contact - * @param homePhoneNumber home phone number - * @param mobilePhoneNumber mobile phone number, - * @param emailAddr Email address for contact - * - * @param additionalAttributes additional attributes for contact - * - * @return contact artifact created - * - */ - public BlackboardArtifact addContact(String contactAccountUniqueID, String contactName, - String phoneNumber, String homePhoneNumber, - String mobilePhoneNumber, String emailAddr, - Collection additionalAttributes) { - - BlackboardArtifact contactArtifact = null; - try { - // Create TSK_CONTACT artifact - contactArtifact = this.dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_CONTACT); - - // Add basic attributes for name phonenumber email, if specified - contactArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, contactName)); - - if (!StringUtils.isEmpty(phoneNumber)) { - contactArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, phoneNumber)); - } - if (!StringUtils.isEmpty(homePhoneNumber)) { - contactArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME, moduleName, homePhoneNumber)); - } - if (!StringUtils.isEmpty(mobilePhoneNumber)) { - contactArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE, moduleName, mobilePhoneNumber)); - } - if (!StringUtils.isEmpty(emailAddr)) { - contactArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, emailAddr)); - } - - // Add additional specified attributes - for (BlackboardAttribute additionalAttribute: additionalAttributes) { - contactArtifact.addAttribute(additionalAttribute); - } - - // Find/Create an account instance for the contact - // Create a relationship between selfAccount and contactAccount - AccountFileInstance contactAccountInstance = createAccountInstance(accountsType, contactAccountUniqueID); - if (selfAccountInstance != null) { - addRelationship (selfAccountInstance, contactAccountInstance, contactArtifact, Relationship.Type.CONTACT, 0 ); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(contactArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add contact artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((contactArtifact != null)? contactArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - return contactArtifact; - } - - - /** - * Creates an account file instance associated with the DB file. - * @param accountType - * @param accountUniqueID - * @return - * @throws TskCoreException - */ - private AccountFileInstance createAccountInstance(Account.Type accountType, String accountUniqueID ) throws TskCoreException { - return Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(accountType, accountUniqueID, moduleName, this.dbAbstractFile); - } - - - /** - * Adds a relations between the two specified account instances. - * - * @param selfAccount device owner account - * @param otherAccount other account - * @param sourceArtifact artifact from which relationship is derived. - * @param relationshipType type of relationship - * @param dateTime date/time of relationship - */ - private void addRelationship(AccountFileInstance selfAccountInstance, AccountFileInstance otherAccountInstance, - BlackboardArtifact sourceArtifact, Relationship.Type relationshipType, long dateTime) { - try { - if (selfAccountInstance.getAccount() != otherAccountInstance.getAccount()) { - Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().addRelationships(selfAccountInstance, - Collections.singletonList(otherAccountInstance), sourceArtifact, relationshipType, dateTime); - } - } catch (TskCoreException | TskDataException ex) { - logger.log(Level.SEVERE, String.format("Unable to add relationship between account %s and account %s", selfAccountInstance.toString(), otherAccountInstance.toString()), ex); //NON-NLS - } - } - - - /** - * Adds a TSK_MESSAGE artifact. - * - * Also creates an account instance for the sender/receiver, and creates a - * relationship between the self account and the sender/receiver account. - * - * @param messageType message type - * @param direction message direction - * @param fromAddress sender address, may be null - * @param toAddress recipient address, may be null - * @param dateTime date/time of message, - * @param readStatus message read or not - * @param subject message subject, may be empty - * @param messageText message body, may be empty - * @param threadId, message thread id - * - * @return message artifact - */ - public BlackboardArtifact addMessage( - String messageType, - CommunicationDirection direction, - Account.Address fromAddress, - Account.Address toAddress, - long dateTime, MessageReadStatusEnum readStatus, - String subject, String messageText, String threadId) { - return addMessage(messageType, direction, - fromAddress, toAddress, dateTime, readStatus, - subject, messageText, threadId, - Collections.emptyList()); - } - - /** - * Adds a TSK_MESSAGE artifact. - * - * Also creates an account instance for the sender/receiver, and creates a - * relationship between the self account and the sender/receiver account. - * - * @param messageType message type - * @param direction message direction - * @param fromAddress sender address, may be empty - * @param toAddress recipient address, may be empty - * @param dateTime date/time of message, - * @param readStatus message read or not - * @param subject message subject, may be empty - * @param messageText message body, may be empty - * @param threadId, message thread id - * - * @param otherAttributesList additional attributes - * - * @return message artifact - */ - public BlackboardArtifact addMessage( String messageType, - CommunicationDirection direction, - Account.Address fromAddress, - Account.Address toAddress, - long dateTime, MessageReadStatusEnum readStatus, String subject, - String messageText, String threadId, - Collection otherAttributesList) { - - return addMessage(messageType, direction, - fromAddress, - Arrays.asList(toAddress), - dateTime, readStatus, - subject, messageText, threadId, - otherAttributesList); - } - - /** - * Adds a TSK_MESSAGE artifact. - * - * Also creates an account instance for the sender/receiver, and creates a - * relationship between the self account and the sender/receiver account. - * - * This method is for messages with a multiple recipients. - * - * @param messageType message type - * @param direction message direction - * @param fromAddress sender address, may be null - * @param recipientsList recipient address list, may be null or empty list - * @param dateTime date/time of message, - * @param readStatus message read or not - * @param subject message subject, may be empty - * @param messageText message body, may be empty - * @param threadId, message thread id - * - * - * @return message artifact - */ - public BlackboardArtifact addMessage( String messageType, - CommunicationDirection direction, - Account.Address fromAddress, - List recipientsList, - long dateTime, MessageReadStatusEnum readStatus, - String subject, String messageText, String threadId) { - return addMessage( messageType, direction, - fromAddress, recipientsList, - dateTime, readStatus, - subject, messageText, threadId, - Collections.emptyList()); - } - - - public BlackboardArtifact addMessage( String messageType, - CommunicationDirection direction, - Account.Address fromAddress, - List recipientsList, - long dateTime, MessageReadStatusEnum readStatus, - String subject, String messageText, - String threadId, - Collection otherAttributesList) { - - // Created message artifact. - BlackboardArtifact msgArtifact = null; - try { - // Create TSK_MESSAGE artifact - msgArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_MESSAGE); - if (dateTime > 0) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, dateTime)); - } - if (readStatus != MessageReadStatusEnum.UNKNOWN) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_READ_STATUS, moduleName, (readStatus == MessageReadStatusEnum.READ) ? 1 : 0)); - } - - // Add basic attribute, if the correspond value is specified - if (!StringUtils.isEmpty(messageType)) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, messageType)); - } - if (direction != CommunicationDirection.UNKNOWN) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, direction.getString())); - } - if (fromAddress != null && !StringUtils.isEmpty(fromAddress.getDisplayName())) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, fromAddress.getDisplayName())); - } - // Create a comma separated string of recipients - String toAddresses = addressListToString(recipientsList); - if (toAddresses != null && !StringUtils.isEmpty(toAddresses)) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, toAddresses)); - } - - if (!StringUtils.isEmpty(subject)) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject)); - } - if (!StringUtils.isEmpty(messageText)) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEXT, moduleName, messageText)); - } - if (!StringUtils.isEmpty(threadId)) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_THREAD_ID, moduleName, threadId)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - msgArtifact.addAttribute(otherAttribute); - } - - // Find/create an account instance for sender - if (fromAddress != null) { - AccountFileInstance senderAccountInstance = createAccountInstance(accountsType, fromAddress.getUniqueID()); - - // Create a relationship between selfAccount and sender account - if (selfAccountInstance != null) { - addRelationship (selfAccountInstance, senderAccountInstance, msgArtifact, Relationship.Type.MESSAGE, dateTime ); - } - } - - // Find/create an account instance for each recipient - if (recipientsList != null) { - for(Account.Address recipient : recipientsList) { - - AccountFileInstance recipientAccountInstance = createAccountInstance(accountsType, recipient.getUniqueID()); - - // Create a relationship between selfAccount and recipient account - if (selfAccountInstance != null) { - addRelationship (selfAccountInstance, recipientAccountInstance, msgArtifact, Relationship.Type.MESSAGE, dateTime ); - } - } - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(msgArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add message artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((msgArtifact != null)? msgArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return msgArtifact; - } - - /** - * Adds a TSK_CALLLOG artifact. - * - * Also creates an account instance for the caller/callee, and creates a - * relationship between the self account and the caller/callee account. - * - * @param direction call direction - * @param fromAddress caller address, may be empty - * @param toAddress callee address, may be empty - * @param startDateTime start date/time - * @param endDateTime end date/time - * - * @return call log artifact - */ - public BlackboardArtifact addCalllog(CommunicationDirection direction, - Account.Address fromAddress, Account.Address toAddress, - long startDateTime, long endDateTime) { - return addCalllog(direction, fromAddress, toAddress, - startDateTime, endDateTime, - CallMediaType.UNKNOWN); - } - - /** - * Adds a TSK_CALLLOG artifact. - * - * Also creates an account instance for the caller/callee, and creates a - * relationship between the self account and the caller/callee account. - * - * @param direction call direction - * @param fromAddress caller address, may be empty - * @param toAddress callee address, may be empty - * @param startDateTime start date/time - * @param endDateTime end date/time - * @param mediaType media type - * - * @return call log artifact - */ - public BlackboardArtifact addCalllog(CommunicationDirection direction, - Account.Address fromAddress, Account.Address toAddress, - long startDateTime, long endDateTime, CallMediaType mediaType) { - return addCalllog(direction, fromAddress, toAddress, - startDateTime, endDateTime, mediaType, - Collections.emptyList()); - } - - /** - * Adds a TSK_CALLLOG artifact. - * - * Also creates an account instance for the caller/receiver, and creates a - * relationship between the self account and the caller/receiver account. - * - * @param direction call direction - * @param fromAddress caller address, may be empty - * @param toAddress callee address, may be empty - * @param startDateTime start date/time - * @param endDateTime end date/time - * @param mediaType media type - * @param otherAttributesList other attributes - * - * @return call log artifact - */ - public BlackboardArtifact addCalllog(CommunicationDirection direction, - Account.Address fromAddress, - Account.Address toAddress, - long startDateTime, long endDateTime, - CallMediaType mediaType, - Collection otherAttributesList) { - return addCalllog(direction, - fromAddress, - Arrays.asList(toAddress), - startDateTime, endDateTime, - mediaType, - otherAttributesList); - } - - /** - * Adds a TSK_CALLLOG artifact. - * - * Also creates an account instance for the caller/callees, - * and creates a relationship between the device owner account and the caller account - * as well between the device owner account and each callee account - * - * @param direction call direction - * @param fromAddress caller address, may be empty - * @param toAddressList callee address list, may be empty - * @param startDateTime start date/time - * @param endDateTime end date/time - * - * @return call log artifact - */ - public BlackboardArtifact addCalllog(CommunicationDirection direction, - Account.Address fromAddress, - Collection toAddressList, - long startDateTime, long endDateTime) { - - return addCalllog(direction, fromAddress, toAddressList, - startDateTime, endDateTime, - CallMediaType.UNKNOWN); - } - - /** - * Adds a TSK_CALLLOG artifact. - * - * Also creates an account instance for the caller/callees, - * and creates a relationship between the device owner account and the caller account - * as well between the device owner account and each callee account - * - * @param direction call direction - * @param fromAddress caller address, may be empty - * @param toAddressList callee address list, may be empty - * @param startDateTime start date/time - * @param endDateTime end date/time - * @param mediaType call media type - * - * @return call log artifact - */ - public BlackboardArtifact addCalllog(CommunicationDirection direction, - Account.Address fromAddress, - Collection toAddressList, - long startDateTime, long endDateTime, - CallMediaType mediaType) { - - return addCalllog(direction, fromAddress, toAddressList, - startDateTime, endDateTime, - mediaType, - Collections.emptyList()); - } - - /** - * Adds a TSK_CALLLOG artifact. - * - * Also creates an account instance for the caller/callees, - * and creates a relationship between the device owner account and the caller account - * as well between the device owner account and each callee account - * - * @param direction call direction - * @param fromAddress caller address, may be empty - * @param toAddressList callee address list, may be empty - * @param startDateTime start date/time - * @param endDateTime end date/time - * @param mediaType called media type - * @param otherAttributesList other attributes - * - * @return calllog artifact - */ - public BlackboardArtifact addCalllog(CommunicationDirection direction, - Account.Address fromAddress, - Collection toAddressList, - long startDateTime, long endDateTime, - CallMediaType mediaType, - Collection otherAttributesList) { - BlackboardArtifact callLogArtifact = null; - try { - // Create TSK_CALLLOG artifact - callLogArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_CALLLOG); - - // Add basic attributes - if (startDateTime > 0) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_START, moduleName, startDateTime)); - } - if (endDateTime > 0) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, endDateTime)); - } - - if (direction != CommunicationDirection.UNKNOWN) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, direction.getString())); - } - if (fromAddress != null) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, fromAddress.getUniqueID())); - if (!StringUtils.isEmpty(fromAddress.getDisplayName())) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, fromAddress.getDisplayName())); - } - } - - // Create a comma separated string of recipients - String toAddresses = addressListToString(toAddressList); - if (!StringUtils.isEmpty(toAddresses)) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, toAddresses)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - callLogArtifact.addAttribute(otherAttribute); - } - - // Create a relationship between selfAccount and caller - if (fromAddress != null) { - AccountFileInstance callerAccountInstance = createAccountInstance(accountsType, fromAddress.getUniqueID()); - if (selfAccountInstance != null) { - addRelationship (selfAccountInstance, callerAccountInstance, callLogArtifact, Relationship.Type.CALL_LOG, (startDateTime > 0) ? startDateTime : 0 ); - } - } - - // Create a relationship between selfAccount and each callee - if (toAddressList != null) { - for(Account.Address callee : toAddressList) { - AccountFileInstance calleeAccountInstance = createAccountInstance(accountsType, callee.getUniqueID()); - if (selfAccountInstance != null) { - addRelationship (selfAccountInstance, calleeAccountInstance, callLogArtifact, Relationship.Type.CALL_LOG, (startDateTime > 0) ? startDateTime : 0 ); - } - } - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(callLogArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add calllog artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((callLogArtifact != null)? callLogArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return callLogArtifact; - } - - - /** - * Adds a TSK_WEB_BOOKMARK artifact. - * - * @param url bookmark URL - * @param title bookmark title, may be empty - * @param creationTime date/time created - * @param progName application/program that created bookmark - * - * @return bookmark artifact - */ - public BlackboardArtifact addWebBookmark(String url, String title, long creationTime, String progName) { - return addWebBookmark(url, title, creationTime, progName, - Collections.emptyList()); - } - - /** - * Adds a TSK_WEB_BOOKMARK artifact. - * - * @param url bookmark URL - * @param title bookmark title, may be empty - * @param creationTime date/time created - * @param progName application/program that created bookmark - * @param otherAttributesList other attributes - - * @return bookmark artifact - */ - public BlackboardArtifact addWebBookmark(String url, String title, long creationTime, String progName, - Collection otherAttributesList) { - - BlackboardArtifact bookMarkArtifact = null; - try { - // Create artifact - bookMarkArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK); - - // Add basic attributes - bookMarkArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, moduleName, url)); - if (creationTime > 0) { - bookMarkArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, moduleName, creationTime)); - } - - if (!StringUtils.isEmpty(title)) { - bookMarkArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE, moduleName, title)); - } - if (!StringUtils.isEmpty(url)) { - bookMarkArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, moduleName, NetworkUtils.extractDomain(url))); - } - if (!StringUtils.isEmpty(progName)) { - bookMarkArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, progName)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - bookMarkArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(bookMarkArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add bookmark artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((bookMarkArtifact != null)? bookMarkArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return bookMarkArtifact; - } - - - /** - * Adds a TSK_WEB_COOKIE artifact - * - * @param url url of the site that created the cookie - * @param creationTime create time of cookie - * @param name cookie name - * @param value cookie value - * @param programName name of the application that created the cookie - * - * @return WebCookie artifact - */ - public BlackboardArtifact addWebCookie(String url, long creationTime, - String name, String value, String programName) { - - return addWebCookie(url, creationTime, name, value, programName, - Collections.emptyList()); - } - - /** - * Adds a TSK_WEB_COOKIE artifact - * - * @param url url of the site that created the cookie - * @param creationTime create time of cookie - * @param name cookie name - * @param value cookie value - * @param programName name of the application that created the cookie - * - * @param otherAttributesList other attributes - * - * @return WebCookie artifact - */ - public BlackboardArtifact addWebCookie(String url, - long creationTime, String name, String value, String programName, - Collection otherAttributesList) { - - - BlackboardArtifact cookieArtifact = null; - try { - // Create artifact - cookieArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE); - - // Add basic attributes - cookieArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, moduleName, url)); - if (creationTime > 0) { - cookieArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, creationTime)); - } - - if (!StringUtils.isEmpty(name)) { - cookieArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - } - if (!StringUtils.isEmpty(value)) { - cookieArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, moduleName, value)); - } - if (!StringUtils.isEmpty(url)) { - cookieArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, moduleName, NetworkUtils.extractDomain(url))); - } - if (!StringUtils.isEmpty(programName)) { - cookieArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, programName)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - cookieArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(cookieArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add bookmark artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((cookieArtifact != null)? cookieArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return cookieArtifact; - } - - /** - * Adds a Web History artifact - * - * @param url url visited - * @param accessTime last access time - * @param referrer referrer, may be empty - * @param title website title, may be empty - * @param programName, application recording the history - * - * @return artifact created - */ - public BlackboardArtifact addWebHistory(String url, long accessTime, - String referrer, String title, String programName) { - return addWebHistory(url, accessTime, referrer, title, programName, - Collections.emptyList()); - } - - /** - * Adds a Web History artifact - * - * @param url url visited - * @param accessTime last access time - * @param referrer referrer, may be empty - * @param title website title, may be empty - * @param programName, application recording the history - * @param otherAttributesList other attributes - * - * - * - * @return artifact created - */ - public BlackboardArtifact addWebHistory(String url, long accessTime, - String referrer, String title, String programName, - Collection otherAttributesList) { - - BlackboardArtifact webHistoryArtifact = null; - try { - // Create artifact - webHistoryArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY); - - // Add basic attributes - webHistoryArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, moduleName, url)); - if (accessTime > 0) { - webHistoryArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, moduleName, accessTime)); - } - - if (!StringUtils.isEmpty(title)) { - webHistoryArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE, moduleName, title)); - } - if (!StringUtils.isEmpty(referrer)) { - webHistoryArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER, moduleName, referrer)); - } - - if (!StringUtils.isEmpty(programName)) { - webHistoryArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, programName)); - } - if (!StringUtils.isEmpty(url)) { - webHistoryArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, moduleName, NetworkUtils.extractDomain(url))); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - webHistoryArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(webHistoryArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add bookmark artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((webHistoryArtifact != null)? webHistoryArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return webHistoryArtifact; - } - - /** - * Created a TSK_WEB_DOWNNLOAD artifact - * - * @param path path of downloaded file - * @param startTime date/time downloaded - * @param url URL downloaded from - * @param progName program that initiated download - * - * @return artifact created - */ - public BlackboardArtifact addWebDownload(String path, long startTime, String url, String progName) { - return addWebDownload(path, startTime, url, progName, Collections.emptyList() ); - } - - /** - * Created a TSK_WEB_DOWNNLOAD artifact - * - * @param path path of downloaded file - * @param startTime date/time downloaded - * @param url URL downloaded from - * @param programName program that initiated download - * @param otherAttributesList other attributes - * - * - * @return artifact created - */ - public BlackboardArtifact addWebDownload(String path, long startTime, String url, String programName, - Collection otherAttributesList ) { - - BlackboardArtifact webDownloadArtifact = null; - try { - // Create artifact - webDownloadArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); - - // Add basic attributes - webDownloadArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, moduleName, url)); - if (startTime > 0) { - webDownloadArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, moduleName, startTime)); - } - webDownloadArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, moduleName, path)); - - /** Convert path to pathID ****/ -// long pathID = Util.findID(dataSource, downloadedFilePath); -// if (pathID != -1) { -// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID, moduleName, pathID)); -// } - - if (!StringUtils.isEmpty(programName)) { - webDownloadArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, programName)); - } - if (!StringUtils.isEmpty(url)) { - webDownloadArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, moduleName, NetworkUtils.extractDomain(url))); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - webDownloadArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(webDownloadArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add web download artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((webDownloadArtifact != null)? webDownloadArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return webDownloadArtifact; - } - - - /** - * Adds a TSK_WEB_FORM_AUTOFILL artifact - * - * @param name name of autofill field - * @param value value of autofill field - * @param creationTime create date/time - * @param accessTime last access date/time - * @param count count of times used - * - * @return artifact created - */ - public BlackboardArtifact addWebFormAutofill(String name, String value, - long creationTime, long accessTime, int count) { - return addWebFormAutofill(name, value, creationTime, accessTime, count, - Collections.emptyList() ); - } - - /** - * Adds a TSK_WEB_FORM_AUTOFILL artifact - * - * @param name name of autofill field - * @param value value of autofill field - * @param creationTime create date/time - * @param accessTime last access date/time - * @param count count of times used - * @param otherAttributesList additional attributes - * - * @return artifact created - */ - public BlackboardArtifact addWebFormAutofill(String name, String value, - long creationTime, long accessTime, int count, - Collection otherAttributesList ) { - BlackboardArtifact webFormAutofillArtifact = null; - try { - // Create artifact - webFormAutofillArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL); - - // Add basic attributes - webFormAutofillArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - webFormAutofillArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, moduleName, value)); - if (creationTime > 0) { - webFormAutofillArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, moduleName, creationTime)); - } - if (accessTime > 0) { - webFormAutofillArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, moduleName, accessTime)); - } - if (count > 0) { - webFormAutofillArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, moduleName, count)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - webFormAutofillArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(webFormAutofillArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add web form autofill artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((webFormAutofillArtifact != null)? webFormAutofillArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return webFormAutofillArtifact; - } - - - /** - * Adds a TSK_WEB_FORM_AUTOFILL artifact. - * - * @param personName person name - * @param email email address - * @param phoneNumber phone number - * @param mailingAddress mailing address - * @param creationTime creation time - * @param accessTime last access time - * @param count use count - * - * @return artifact created - */ - public BlackboardArtifact addWebFormAddress(String personName, String email, - String phoneNumber, String mailingAddress, - long creationTime, long accessTime, int count ) { - return addWebFormAddress(personName, email, phoneNumber, - mailingAddress, creationTime, accessTime, count, - Collections.emptyList() ); - } - - /** - * Adds a TSK_WEB_FORM_AUTOFILL artifact. - * - * @param personName person name - * @param email email address - * @param phoneNumber phone number - * @param mailingAddress mailing address - * @param creationTime creation time - * @param accessTime last access time - * @param count use count - * @param otherAttributesList other attributes - * - * @return artifact created - */ - public BlackboardArtifact addWebFormAddress(String personName, String email, - String phoneNumber, String mailingAddress, - long creationTime, long accessTime, int count, - Collection otherAttributesList ) { - - BlackboardArtifact webFormAddressArtifact = null; - try { - // Create artifact - webFormAddressArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL); - - // Add basic attributes - webFormAddressArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, personName)); - if (creationTime > 0) { - webFormAddressArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, moduleName, creationTime)); - } - if (accessTime > 0) { - webFormAddressArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, moduleName, accessTime)); - } - if (count > 0) { - webFormAddressArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, moduleName, count)); - } - - if (!StringUtils.isEmpty(email)) { - webFormAddressArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, email)); - } - if (!StringUtils.isEmpty(phoneNumber)) { - webFormAddressArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, phoneNumber)); - } - if (!StringUtils.isEmpty(mailingAddress)) { - webFormAddressArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCATION, moduleName, mailingAddress)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - webFormAddressArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(webFormAddressArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add web form address artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((webFormAddressArtifact != null)? webFormAddressArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return webFormAddressArtifact; - } - - /** - * Adds a TSK_INSTALLED_PROGRAM artifact - * - * @param programName name of program - * @param dateInstalled date of install - * - * @return artifact added - */ - public BlackboardArtifact addInstalledProgram(String programName, long dateInstalled) { - return addInstalledProgram(programName, dateInstalled, - Collections.emptyList() ); - } - - /** - * Adds a TSK_INSTALLED_PROGRAM artifact - * - * @param programName name of program - * @param dateInstalled date of install - * @param otherAttributesList additional attributes - * - * @return artifact added - */ - public BlackboardArtifact addInstalledProgram(String programName, long dateInstalled, - Collection otherAttributesList ) { - - BlackboardArtifact installedProgramArtifact = null; - try { - // Create artifact - installedProgramArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG); - - // Add basic attributes - installedProgramArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, programName)); - if (dateInstalled > 0) { - installedProgramArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, dateInstalled)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - installedProgramArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(installedProgramArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add installed program artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((installedProgramArtifact != null)? installedProgramArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return installedProgramArtifact; - } - - - /** - * Adds a TSK_GPS_TRACKPOINT artifact - * - * @param latitude location latitude - * @param longitude location longitude - * @param timeStamp date/time trackpoint recoded - * @param poiName trackpoint name - * @param programName name of program that recorded trackpoint - * - * @return artifact added - */ - public BlackboardArtifact addGPSLocation(double latitude, double longitude, - long timeStamp, String poiName, String programName) { - - return addGPSLocation(latitude, longitude, timeStamp, poiName, programName, - Collections.emptyList()); - } - - /** - * Adds a TSK_GPS_TRACKPOINT artifact - * - * @param latitude location latitude - * @param longitude location longitude - * @param timeStamp date/time trackpoint recorded - * @param name trackpoint name - * @param programName name of program that recorded trackpoint - * @param otherAttributesList other attributes - * - * @return artifact added - */ - public BlackboardArtifact addGPSLocation(double latitude, double longitude, long timeStamp, String name, String programName, - Collection otherAttributesList) { - - BlackboardArtifact gpsTrackpointArtifact = null; - try { - // Create artifact - gpsTrackpointArtifact = dbAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); - - // Add basic attributes - gpsTrackpointArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, moduleName, latitude)); - gpsTrackpointArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, moduleName, longitude)); - if (timeStamp > 0) { - gpsTrackpointArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, timeStamp)); - } - - if (!StringUtils.isEmpty(name)) { - gpsTrackpointArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - } - - if (!StringUtils.isEmpty(programName)) { - gpsTrackpointArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, programName)); - } - - // Add other specified attributes - for (BlackboardAttribute otherAttribute: otherAttributesList) { - gpsTrackpointArtifact.addAttribute(otherAttribute); - } - - // post artifact - Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifact(gpsTrackpointArtifact, this.moduleName); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to add GPS trackpoint artifact", ex); //NON-NLS - return null; - } - catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, String.format("Unable to post artifact %s", ((gpsTrackpointArtifact != null)? gpsTrackpointArtifact.getArtifactID() : "")), ex); //NON-NLS - } - - // return the artifact - return gpsTrackpointArtifact; - } - - /** - * Converts a list of addresses into a single comma separated string of - * addresses. - * - * @param addressList - * @return comma separated string of addresses - */ - private String addressListToString(Collection addressList) { - - String toAddresses = ""; - if (addressList != null && (!addressList.isEmpty())) { - StringBuilder toAddressesSb = new StringBuilder(); - for(Account.Address address : addressList) { - String displayAddress = !StringUtils.isEmpty(address.getDisplayName()) ? address.getDisplayName() : address.getUniqueID(); - toAddressesSb = toAddressesSb.length() > 0 ? toAddressesSb.append(",").append(displayAddress) : toAddressesSb.append(displayAddress); - } - toAddresses = toAddressesSb.toString(); - } - - return toAddresses; - } -} diff --git a/InternalPythonModules/android/imo.py b/InternalPythonModules/android/imo.py index e089248e5f..56bf46126e 100644 --- a/InternalPythonModules/android/imo.py +++ b/InternalPythonModules/android/imo.py @@ -32,9 +32,7 @@ from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil from org.sleuthkit.autopsy.coreutils import AppSQLiteDB -from org.sleuthkit.autopsy.coreutils import AppDBParserHelper -from org.sleuthkit.autopsy.coreutils.AppDBParserHelper import MessageReadStatusEnum -from org.sleuthkit.autopsy.coreutils.AppDBParserHelper import CommunicationDirection + from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.ingest import IngestJobContext from org.sleuthkit.datamodel import AbstractFile @@ -43,6 +41,9 @@ from org.sleuthkit.datamodel import BlackboardAttribute from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel import Account +from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper +from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatusEnum +from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection import traceback import general @@ -76,7 +77,8 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): friendsDbs = AppSQLiteDB.findAppDatabases(dataSource, "imofriends.db", True, "com.imo.android.imous") for friendsDb in friendsDbs: try: - friendsDBHelper = AppDBParserHelper("IMO Parser", friendsDb.getDBFile(), + friendsDBHelper = CommunicationArtifactsHelper(Case.getCurrentCase().getSleuthkitCase(), + "IMO Parser", friendsDb.getDBFile(), Account.Type.IMO, Account.Type.IMO, selfAccountAddress ) contactsResultSet = friendsDb.runQuery("SELECT buid, name FROM friends") if contactsResultSet is not None: From 6b3a7a6bcbb9049fe07664bb3a1c08a84bea964a Mon Sep 17 00:00:00 2001 From: Raman Date: Mon, 16 Sep 2019 17:39:51 -0400 Subject: [PATCH 46/46] Address review comments. --- InternalPythonModules/android/imo.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/InternalPythonModules/android/imo.py b/InternalPythonModules/android/imo.py index 56bf46126e..9062f71f58 100644 --- a/InternalPythonModules/android/imo.py +++ b/InternalPythonModules/android/imo.py @@ -42,7 +42,7 @@ from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel import Account from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper -from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatusEnum +from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatus from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection import traceback @@ -110,11 +110,11 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): message_read = messagesResultSet.getInt("message_read") if (message_read == 1): - msgReadStatus = MessageReadStatusEnum.READ + msgReadStatus = MessageReadStatus.READ elif (message_read == 0): - msgReadStatus = MessageReadStatusEnum.UNREAD + msgReadStatus = MessageReadStatus.UNREAD else: - msgReadStatus = MessageReadStatusEnum.UNKNOWN + msgReadStatus = MessageReadStatus.UNKNOWN timeStamp = messagesResultSet.getLong("timestamp") / 1000000000