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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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 9344eb4c98e1b07d548959d292acf6909783e29f Mon Sep 17 00:00:00 2001 From: Raman Date: Tue, 10 Sep 2019 08:13:48 -0400 Subject: [PATCH 24/49] Address review comments. --- .../autopsy/coreutils/AppSQLiteDB.java | 280 +++++++++--------- InternalPythonModules/android/imo.py | 6 +- 2 files changed, 136 insertions(+), 150 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java b/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java index f514072433..404936e087 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.logging.Level; +import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.services.FileManager; @@ -52,27 +53,45 @@ public final class AppSQLiteDB implements Closeable { private final AbstractFile dbAbstractFile; // AbstractFile for the DB file - private Connection connection = null; - private Statement statement = null; + private final Connection connection; + private final Statement statement; - private AppSQLiteDB(AbstractFile dbAbstractFile, File dbFileCopy) { - this.dbAbstractFile = dbAbstractFile; + + /** + * Class to abstract the abstract file for a DB file and its on disk copy + * + */ + private static final class AppSQLiteDBFileBundle { + private final AbstractFile dbAbstractFile; + private final File dbFileCopy; - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + dbFileCopy.getPath()); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database " + dbFileCopy.getPath(), e); //NON-NLS - connection = null; - statement = null; + AppSQLiteDBFileBundle(AbstractFile dbAbstractFile, File dbFileCopy) { + this.dbAbstractFile = dbAbstractFile; + this.dbFileCopy = dbFileCopy; } + + AbstractFile getAbstractFile() { + return dbAbstractFile; + } + + File getFileCopy() { + return dbFileCopy; + } + + } + + private AppSQLiteDB(AppSQLiteDBFileBundle appSQLiteDBFileBundle) throws ClassNotFoundException, SQLException { + this.dbAbstractFile = appSQLiteDBFileBundle.getAbstractFile(); + + Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + appSQLiteDBFileBundle.getFileCopy().getPath()); //NON-NLS + statement = connection.createStatement(); } /** * Looks for the given SQLIte database filename, with matching path substring. - * It looks for exact name or a pattern match based on + * It looks for exact name or a pattern match based on a input parameter. * It makes a copy of each matching file, and creates an instance of * AppSQLiteDB to help query the DB. * @@ -87,54 +106,24 @@ public final class AppSQLiteDB implements Closeable { * @return AbstractFile for the DB if the database file is found. * Returns NULL if no such database is found. */ - public static Collection findAppDatabases(DataSource dataSource, String dbName, boolean matchExactName, String parentPathSubstr) { + public static Collection findAppDatabases(DataSource dataSource, + String dbName, boolean matchExactName, String parentPathSubstr) { List appDbs = new ArrayList<> (); - Case openCase; - try { - openCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - return appDbs; - } - - List absFiles; - long fileId = 0; - String localDiskPath = ""; - try { - SleuthkitCase skCase = openCase.getSleuthkitCase(); - String parentPath = parentPathSubstr.replace("\\", "/"); - parentPath = SleuthkitCase.escapeSingleQuotes(parentPath); - String whereClause; - if (matchExactName) { - whereClause = String.format("LOWER(name) = LOWER('%s') AND LOWER(parent_path) LIKE LOWER('%%%s%%') AND data_source_obj_id = %s", dbName, parentPath, dataSource.getId()); - } else { - whereClause = String.format("LOWER(name) LIKE LOWER('%%%s%%') AND LOWER(name) NOT LIKE LOWER('%%journal%%') AND LOWER(parent_path) LIKE LOWER('%%%s%%') AND data_source_obj_id = %s", dbName, parentPath, dataSource.getId() ); - } - absFiles = skCase.findAllFilesWhere(whereClause); - for (AbstractFile absFile : absFiles) { + Collection dbFileBundles = findAndCopySQLiteDB( dataSource, dbName, matchExactName, parentPathSubstr, false); + dbFileBundles.forEach((dbFileBundle) -> { try { - localDiskPath = openCase.getTempDirectory() - + File.separator + absFile.getId() + absFile.getName(); - File jFile = new java.io.File(localDiskPath); - fileId = absFile.getId(); - ContentUtils.writeToFile(absFile, jFile); - - //Find and copy both WAL and SHM meta files - findAndCopySQLiteMetaFile(absFile, absFile.getName() + "-wal"); - findAndCopySQLiteMetaFile(absFile, absFile.getName() + "-shm"); - - appDbs.add(new AppSQLiteDB(absFile, jFile) ); - } catch (ReadContentInputStream.ReadContentInputStreamException ex) { - Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.WARNING, String.format("Error reading content from file '%s' (id=%d).", absFile.getName(), fileId), ex); //NON-NLS - } catch (IOException | NoCurrentCaseException | TskCoreException ex) { - Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format("Error writing content from file '%s' (id=%d) to '%s'.", absFile.getName(), fileId, localDiskPath), ex); //NON-NLS + AppSQLiteDB appSQLiteDB = new AppSQLiteDB(dbFileBundle); + appDbs.add(appSQLiteDB); + } catch (ClassNotFoundException | SQLException ex) { + Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format("Failed to open a DB connection for file = '%s' and path = '%s'.", dbFileBundle.dbAbstractFile.getName(), dbFileBundle.getFileCopy().getPath()), ex); //NON-NLS } - } - } catch (TskCoreException e) { - Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, "Error finding application DB file.", e); //NON-NLS + }); + } catch (TskCoreException ex) { + Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format("Error finding App database files with name = '%s' and path = '%s'.", dbName, parentPathSubstr), ex); //NON-NLS } + return appDbs; } @@ -156,66 +145,98 @@ public final class AppSQLiteDB implements Closeable { * @param dbAlias alias name to attach the database as * * @return abstract file for the matching db file. - * - * @throws TskCoreException in case of an error. + * null if no match is found. + * + * @throws SQLException in case of an SQL error */ public AbstractFile attachDatabase(DataSource dataSource, String dbName, - boolean matchExactName, String dbPath, String dbAlias) throws TskCoreException { + boolean matchExactName, String dbPath, String dbAlias) throws SQLException { + try { + Collection dbFileBundles = findAndCopySQLiteDB(dataSource, dbName, matchExactName, dbPath, true); + for (AppSQLiteDBFileBundle dbFileBundle: dbFileBundles) { + String attachDbSql = String.format("ATTACH DATABASE '%s' AS '%s'", dbFileBundle.getFileCopy().getPath(), dbAlias); //NON-NLS + statement.executeUpdate(attachDbSql); + + return dbFileBundle.getAbstractFile(); + } + } catch (TskCoreException ex) { + Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format("Error attaching to App database files with name = '%s' and path = '%s'.", dbName, dbPath), ex); //NON-NLS + } + + return null; + } + + /** + * Finds database file with the specified name, makes a copy of the file in the case directory, + * and returns the AbstractFile as well as the file copy. + * + * @param dataSource data source to search in + * @param dbName db file name to search + * @param matchExactName whether to look for exact file name or a pattern match + * @param dbPath path to match + * @param matchExactName whether to look for exact path name or a substring match + * + * @return a collection of AppSQLiteDBFileBundle + * + * @throws TskCoreException + */ + private static Collection findAndCopySQLiteDB(DataSource dataSource, String dbName, + boolean matchExactName, String dbPath, boolean matchExactPath) throws TskCoreException { + + List dbFileBundles = new ArrayList<> (); + Case openCase; - Case openCase; try { openCase = Case.getCurrentCaseThrows(); } catch (NoCurrentCaseException ex) { - throw new TskCoreException("Exception while getting open case.", ex); + throw new TskCoreException("Failed to get current case.", ex); } List absFiles; long fileId = 0; - String localFilePath = ""; - try { - SleuthkitCase skCase = openCase.getSleuthkitCase(); - String parentPath = dbPath.replace("\\", "/"); - parentPath = SleuthkitCase.escapeSingleQuotes(parentPath); - String whereClause; - if (matchExactName) { - whereClause = String.format("LOWER(name) = LOWER('%s') AND LOWER(parent_path) = LOWER('%s') AND data_source_obj_id = %s", dbName, parentPath, dataSource.getId()); //NON-NLS - } else { - whereClause = String.format("LOWER(name) LIKE LOWER('%%%s%%') AND LOWER(name) NOT LIKE LOWER('%%journal%%') AND LOWER(parent_path) = LOWER('%s') AND data_source_obj_id = %s", dbName, parentPath, dataSource.getId()); //NON-NLS - } - absFiles = skCase.findAllFilesWhere(whereClause); - for (AbstractFile absFile : absFiles) { - try { - localFilePath = openCase.getTempDirectory() - + File.separator + absFile.getId() + absFile.getName(); - File jFile = new java.io.File(localFilePath); - fileId = absFile.getId(); - ContentUtils.writeToFile(absFile, jFile); - - //Find and copy both WAL and SHM meta files - findAndCopySQLiteMetaFile(absFile, absFile.getName() + "-wal"); - findAndCopySQLiteMetaFile(absFile, absFile.getName() + "-shm"); - - //run the ATTACH DATABASE sql command - try { - String attachDbSql = String.format("ATTACH DATABASE '%s' AS '%s'", localFilePath, dbAlias); //NON-NLS - statement.executeUpdate(attachDbSql); - } - catch (SQLException ex) { - throw new TskCoreException("Error running ATTACH DATABASE SQL. " + ex.getMessage(), ex); - } + String localDiskPath = ""; - return absFile; - } catch (ReadContentInputStream.ReadContentInputStreamException ex) { - Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.WARNING, String.format("Error reading content from file '%s' (id=%d).", absFile.getName(), fileId), ex); //NON-NLS - } catch (IOException | NoCurrentCaseException ex) { - Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format("Error writing content from file '%s' (id=%d) to '%s'.", absFile.getName(), fileId, localFilePath), ex); //NON-NLS - } - } - } catch (TskCoreException e) { - Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, "Error finding application DB file.", e); //NON-NLS + SleuthkitCase skCase = openCase.getSleuthkitCase(); + String parentPath = dbPath.replace("\\", "/"); + parentPath = SleuthkitCase.escapeSingleQuotes(parentPath); + + String whereClause; + if (matchExactName) { + whereClause = String.format("LOWER(name) = LOWER('%s')", dbName); + } else { + whereClause = String.format("LOWER(name) LIKE LOWER('%%%s%%') AND LOWER(name) NOT LIKE LOWER('%%journal%%')", dbName ); + } + if (matchExactPath) { + whereClause += String.format(" AND LOWER(parent_path) = LOWER('%s')", parentPath ); + } else { + whereClause += String.format(" AND LOWER(parent_path) LIKE LOWER('%%%s%%')", parentPath ); + } + whereClause += String.format(" AND data_source_obj_id = %s", dataSource.getId()); + + absFiles = skCase.findAllFilesWhere(whereClause); + for (AbstractFile absFile : absFiles) { + try { + localDiskPath = openCase.getTempDirectory() + + File.separator + absFile.getId() + absFile.getName(); + File jFile = new java.io.File(localDiskPath); + fileId = absFile.getId(); + ContentUtils.writeToFile(absFile, jFile); + + //Find and copy both WAL and SHM meta files + findAndCopySQLiteMetaFile(absFile, absFile.getName() + "-wal"); + findAndCopySQLiteMetaFile(absFile, absFile.getName() + "-shm"); + + AppSQLiteDBFileBundle dbFileBundle = new AppSQLiteDBFileBundle(absFile, jFile); + dbFileBundles.add(dbFileBundle); + + } catch (ReadContentInputStream.ReadContentInputStreamException ex) { + Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.WARNING, String.format("Error reading content from file '%s' (id=%d).", absFile.getName(), fileId), ex); //NON-NLS + } catch (IOException | NoCurrentCaseException | TskCoreException ex) { + Logger.getLogger(AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format("Error creating AppSQLiteDB for file '%s' (id=%d) to copied to '%s'.", absFile.getName(), fileId, localDiskPath), ex); //NON-NLS + } } - return null; + return dbFileBundles; } /** @@ -223,48 +244,14 @@ public final class AppSQLiteDB implements Closeable { * * @param dbAlias alias for database to detach * - * @throws TskCoreException + * @throws SQLException */ - public void detachDatabase(String dbAlias) throws TskCoreException { - - try { - String detachDbSql = String.format("DETACH DATABASE '%s'", dbAlias); - statement.executeUpdate(detachDbSql); //NON-NLS - } - catch (SQLException ex) { - throw new TskCoreException("Error running DETACH DATABASE SQL. " + ex.getMessage(), ex); - } + public void detachDatabase(String dbAlias) throws SQLException { + String detachDbSql = String.format("DETACH DATABASE '%s'", dbAlias); + statement.executeUpdate(detachDbSql); //NON-NLS } - /** - * Checks if the specified table exists in the given database file. - * - * @param tableName table name to check - * - * @return - */ - public boolean tableExists(String tableName) { - // RAMAN TBD - return false; - - } - - /** - * Checks if the specified column exists. - * - * @param tableName table name to check - * @param columnName column name to check - * @return - */ - public boolean columnExists(String tableName, String columnName) { - // RAMAN TBD - return false; - } - - - - /** * Runs the given query on the database and returns result set. @@ -272,18 +259,15 @@ public final class AppSQLiteDB implements Closeable { * * @return ResultSet from running the query. * - * @throws TskCoreException in case of an error. + * @throws SQLException in case of an error. * */ - public ResultSet runQuery(String queryStr) throws TskCoreException { + public ResultSet runQuery(String queryStr) throws SQLException { ResultSet resultSet = null; - try { + + if (null != queryStr) { resultSet = statement.executeQuery(queryStr); //NON-NLS - } - catch (SQLException ex) { - throw new TskCoreException("Error running app SQLite query. " + ex.getMessage(), ex); - } - + } return resultSet; } diff --git a/InternalPythonModules/android/imo.py b/InternalPythonModules/android/imo.py index 2407ff552d..d887a6da53 100644 --- a/InternalPythonModules/android/imo.py +++ b/InternalPythonModules/android/imo.py @@ -129,9 +129,11 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): # TBD: parse the imdata JSON structure to figure out if there is an attachment. # If one exists, add the attachment as a derived file and a child of the message artifact. - + except SQLException as ex: - self._logger.log(Level.SEVERE, "Error processing query result for IMO friends", ex) + self._logger.log(Level.SEVERE, "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) finally: friendsDb.close() From 9b3fc008471ad0c03c9d4aee390e11baaf1dd9ec Mon Sep 17 00:00:00 2001 From: Raman Date: Tue, 10 Sep 2019 10:13:34 -0400 Subject: [PATCH 25/49] Updated javadocs. --- .../src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java b/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java index 404936e087..900e8aa45e 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.logging.Level; -import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.services.FileManager; @@ -45,8 +44,8 @@ import org.sleuthkit.datamodel.TskCoreException; /** * An abstraction around an SQLite app DB found in a data source. - * This class makes a copy of it, opens a SQLite connection to it - * and runs queries on it. + * This class makes a copy of it, along with any meta files (WAL, SHM), + * opens a SQLite connection to it, and runs queries on it. */ public final class AppSQLiteDB implements Closeable { private final Logger logger = Logger.getLogger(AppSQLiteDB.class.getName()); @@ -103,8 +102,8 @@ public final class AppSQLiteDB implements Closeable { * @param matchExactName whether to look for exact file name or a pattern match * @param parentPathSubstr path substring to match * - * @return AbstractFile for the DB if the database file is found. - * Returns NULL if no such database is found. + * @return A list of abstract files matching the specified name and path. + * Returns an empty list if no matching database is found. */ public static Collection findAppDatabases(DataSource dataSource, String dbName, boolean matchExactName, String parentPathSubstr) { From ce841f2c3b677f9250c88eba25f9081a4201b3b2 Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Tue, 10 Sep 2019 10:34:12 -0400 Subject: [PATCH 26/49] 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 27/49] 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 77f5de5a30d1c47a1b34d51d0bcd264933a6da54 Mon Sep 17 00:00:00 2001 From: Raman Date: Tue, 10 Sep 2019 15:55:37 -0400 Subject: [PATCH 28/49] attachDatabase() only takes the exact DB filename to match. --- .../autopsy/coreutils/AppSQLiteDB.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java b/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java index 900e8aa45e..6812f6daf3 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/AppSQLiteDB.java @@ -139,7 +139,6 @@ public final class AppSQLiteDB implements Closeable { * * @param dataSource data source in which to look file the db file * @param dbName name of db file to look for - * @param matchExactName specified whether the name is an exact name or a pattern * @param dbPath path in which to look for the db file * @param dbAlias alias name to attach the database as * @@ -149,12 +148,14 @@ public final class AppSQLiteDB implements Closeable { * @throws SQLException in case of an SQL error */ public AbstractFile attachDatabase(DataSource dataSource, String dbName, - boolean matchExactName, String dbPath, String dbAlias) throws SQLException { + String dbPath, String dbAlias) throws SQLException { try { - Collection dbFileBundles = findAndCopySQLiteDB(dataSource, dbName, matchExactName, dbPath, true); - for (AppSQLiteDBFileBundle dbFileBundle: dbFileBundles) { + // find and copy DB files with exact name and path. + Collection dbFileBundles = findAndCopySQLiteDB(dataSource, dbName, true, dbPath, true); + if (!dbFileBundles.isEmpty()) { + AppSQLiteDBFileBundle dbFileBundle = dbFileBundles.iterator().next(); String attachDbSql = String.format("ATTACH DATABASE '%s' AS '%s'", dbFileBundle.getFileCopy().getPath(), dbAlias); //NON-NLS - statement.executeUpdate(attachDbSql); + statement.executeUpdate(attachDbSql); return dbFileBundle.getAbstractFile(); } @@ -182,16 +183,14 @@ public final class AppSQLiteDB implements Closeable { private static Collection findAndCopySQLiteDB(DataSource dataSource, String dbName, boolean matchExactName, String dbPath, boolean matchExactPath) throws TskCoreException { - List dbFileBundles = new ArrayList<> (); Case openCase; - try { openCase = Case.getCurrentCaseThrows(); } catch (NoCurrentCaseException ex) { throw new TskCoreException("Failed to get current case.", ex); } - List absFiles; + List dbFileBundles = new ArrayList<> (); long fileId = 0; String localDiskPath = ""; @@ -212,7 +211,7 @@ public final class AppSQLiteDB implements Closeable { } whereClause += String.format(" AND data_source_obj_id = %s", dataSource.getId()); - absFiles = skCase.findAllFilesWhere(whereClause); + List absFiles = skCase.findAllFilesWhere(whereClause); for (AbstractFile absFile : absFiles) { try { localDiskPath = openCase.getTempDirectory() From 4c05fd5a219aa84fc738599cef76405433e44220 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 10 Sep 2019 17:00:41 -0400 Subject: [PATCH 29/49] 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 30/49] 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 fc137e4ab6e3f84342bca38da0fe378253608c1f Mon Sep 17 00:00:00 2001 From: Raman Date: Wed, 11 Sep 2019 10:16:16 -0400 Subject: [PATCH 31/49] Updated addCalllog() api to support group calls. --- .../autopsy/coreutils/AppDBParserHelper.java | 182 ++++++++++++------ 1 file changed, 128 insertions(+), 54 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java b/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java index 32848c6437..c7bd656b78 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java @@ -248,13 +248,15 @@ public final class AppDBParserHelper { * @param relationshipType type of relationship * @param dateTime date/time of relationship */ - private void addRelationship(AccountFileInstance selfAccount, AccountFileInstance otherAccount, + private void addRelationship(AccountFileInstance selfAccountInstance, AccountFileInstance otherAccountInstance, BlackboardArtifact sourceArtifact, Relationship.Type relationshipType, long dateTime) { try { - Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().addRelationships(selfAccount, - Collections.singletonList(otherAccount), sourceArtifact, relationshipType, dateTime); + 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", selfAccount.toString(), otherAccount.toString()), ex); //NON-NLS + logger.log(Level.SEVERE, String.format("Unable to add relationship between account %s and account %s", selfAccountInstance.toString(), otherAccountInstance.toString()), ex); //NON-NLS } } @@ -366,17 +368,6 @@ public final class AppDBParserHelper { String threadId, Collection otherAttributesList) { - - // Create a comma separated string of recipients - String toAddresses = null; - if (recipientsList != null && (!recipientsList.isEmpty())) { - StringBuilder toAddressesSb = new StringBuilder(); - for(Account.Address recipient : recipientsList) { - toAddressesSb = toAddressesSb.length() > 0 ? toAddressesSb.append(",").append(recipient.getDisplayName()) : toAddressesSb.append(recipient.getDisplayName()); - } - toAddresses = toAddressesSb.toString(); - } - // Created message artifact. BlackboardArtifact msgArtifact = null; try { @@ -399,6 +390,8 @@ public final class AppDBParserHelper { 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)); } @@ -413,7 +406,6 @@ public final class AppDBParserHelper { msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_THREAD_ID, moduleName, threadId)); } - // Add other specified attributes for (BlackboardAttribute otherAttribute: otherAttributesList) { msgArtifact.addAttribute(otherAttribute); @@ -444,8 +436,6 @@ public final class AppDBParserHelper { // 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; @@ -461,24 +451,22 @@ public final class AppDBParserHelper { /** * 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. + * Also creates an account instance for the caller/callee, and creates a + * relationship between the self account and the caller/callee account. * - * @param otherAccountUniqueID unique id for the caller/receiver account * @param direction call direction - * @param fromPhoneNumber originating phone number, may be empty - * @param toPhoneNumber recipient phone number, may be empty + * @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 contactName contact name, may be empty * * @return call log artifact */ - public BlackboardArtifact addCalllog( String otherAccountUniqueID, - String direction, String fromPhoneNumber, String toPhoneNumber, - long startDateTime, long endDateTime, String contactName) { - return addCalllog(otherAccountUniqueID, direction, fromPhoneNumber, toPhoneNumber, - startDateTime, endDateTime, contactName, + public BlackboardArtifact addCalllog( String direction, + Account.Address fromAddress, Account.Address toAddress, + long startDateTime, long endDateTime) { + return addCalllog(direction, fromAddress, toAddress, + startDateTime, endDateTime, Collections.emptyList()); } @@ -486,23 +474,74 @@ public final class AppDBParserHelper { * Adds a TSK_CALLLOG artifact. * * Also creates an account instance for the caller/receiver, and creates a - * relationship between the device owner account and the caller/receiver account. + * relationship between the self account and the caller/receiver account. * - * @param otherAccountUniqueID - * @param direction - * @param fromPhoneNumber - * @param toPhoneNumber - * @param startDateTime - * @param endDateTime - * @param contactName - * @param otherAttributesList + * @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 otherAttributesList other attributes + * + * @return call log artifact + */ + public BlackboardArtifact addCalllog( String direction, + Account.Address fromAddress, + Account.Address toAddress, + long startDateTime, long endDateTime, + Collection otherAttributesList) { + return addCalllog(direction, + fromAddress, + Arrays.asList(toAddress), + startDateTime, endDateTime, + 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( String direction, + Account.Address fromAddress, + Collection toAddressList, + long startDateTime, long endDateTime) { + + return addCalllog(direction, fromAddress, toAddressList, + startDateTime, endDateTime, + 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 otherAttributesList other attributes * * @return calllog artifact */ - public BlackboardArtifact addCalllog(String otherAccountUniqueID, - String direction, String fromPhoneNumber, String toPhoneNumber, - long startDateTime, long endDateTime, String contactName, - Collection otherAttributesList) { + public BlackboardArtifact addCalllog( String direction, + Account.Address fromAddress, + Collection toAddressList, + long startDateTime, long endDateTime, + Collection otherAttributesList) { BlackboardArtifact callLogArtifact = null; try { // Create TSK_CALLLOG artifact @@ -519,14 +558,17 @@ public final class AppDBParserHelper { if (!StringUtils.isEmpty(direction)) { callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, direction)); } - if (!StringUtils.isEmpty(fromPhoneNumber)) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, fromPhoneNumber)); + 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())); + } } - if (!StringUtils.isEmpty(toPhoneNumber)) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, toPhoneNumber)); - } - if (!StringUtils.isEmpty(contactName)) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, contactName)); + + // 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 @@ -534,13 +576,24 @@ public final class AppDBParserHelper { callLogArtifact.addAttribute(otherAttribute); } - // Find/Create an account instance for the sender/recipient - // Create a relationship between selfAccount and contactAccount - AccountFileInstance contactAccountInstance = createAccountInstance(accountsType, otherAccountUniqueID); - if (selfAccountInstance != null) { - addRelationship (selfAccountInstance, contactAccountInstance, callLogArtifact, Relationship.Type.CALL_LOG, 0 ); + // 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) { @@ -1142,4 +1195,25 @@ public final class AppDBParserHelper { 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; + } } From 77ed043911992a5c47e3af3a63e37ba958b17060 Mon Sep 17 00:00:00 2001 From: Raman Date: Wed, 11 Sep 2019 13:41:18 -0400 Subject: [PATCH 32/49] Defined enums for communication direction and call media type. --- .../autopsy/coreutils/AppDBParserHelper.java | 128 ++++++++++++++++-- InternalPythonModules/android/imo.py | 12 +- 2 files changed, 122 insertions(+), 18 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java b/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java index c7bd656b78..0b6f567b87 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java @@ -56,7 +56,48 @@ public final class AppDBParserHelper { 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; @@ -280,7 +321,8 @@ public final class AppDBParserHelper { * @return message artifact */ public BlackboardArtifact addMessage( - String messageType, String direction, + String messageType, + CommunicationDirection direction, Account.Address fromAddress, Account.Address toAddress, long dateTime, MessageReadStatusEnum readStatus, @@ -311,7 +353,8 @@ public final class AppDBParserHelper { * * @return message artifact */ - public BlackboardArtifact addMessage( String messageType, String direction, + public BlackboardArtifact addMessage( String messageType, + CommunicationDirection direction, Account.Address fromAddress, Account.Address toAddress, long dateTime, MessageReadStatusEnum readStatus, String subject, @@ -347,7 +390,8 @@ public final class AppDBParserHelper { * * @return message artifact */ - public BlackboardArtifact addMessage( String messageType, String direction, + public BlackboardArtifact addMessage( String messageType, + CommunicationDirection direction, Account.Address fromAddress, List recipientsList, long dateTime, MessageReadStatusEnum readStatus, @@ -360,7 +404,8 @@ public final class AppDBParserHelper { } - public BlackboardArtifact addMessage( String messageType, String direction, + public BlackboardArtifact addMessage( String messageType, + CommunicationDirection direction, Account.Address fromAddress, List recipientsList, long dateTime, MessageReadStatusEnum readStatus, @@ -384,8 +429,8 @@ public final class AppDBParserHelper { if (!StringUtils.isEmpty(messageType)) { msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, messageType)); } - if (!StringUtils.isEmpty(direction)) { - msgArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, direction)); + 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())); @@ -462,11 +507,34 @@ public final class AppDBParserHelper { * * @return call log artifact */ - public BlackboardArtifact addCalllog( String direction, + 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()); } @@ -481,19 +549,22 @@ public final class AppDBParserHelper { * @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( String direction, + public BlackboardArtifact addCalllog(CommunicationDirection direction, Account.Address fromAddress, Account.Address toAddress, - long startDateTime, long endDateTime, + long startDateTime, long endDateTime, + CallMediaType mediaType, Collection otherAttributesList) { return addCalllog(direction, fromAddress, Arrays.asList(toAddress), startDateTime, endDateTime, + mediaType, otherAttributesList); } @@ -512,15 +583,44 @@ public final class AppDBParserHelper { * * @return call log artifact */ - public BlackboardArtifact addCalllog( String direction, + 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. * @@ -533,14 +633,16 @@ public final class AppDBParserHelper { * @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( String direction, + public BlackboardArtifact addCalllog(CommunicationDirection direction, Account.Address fromAddress, Collection toAddressList, long startDateTime, long endDateTime, + CallMediaType mediaType, Collection otherAttributesList) { BlackboardArtifact callLogArtifact = null; try { @@ -555,8 +657,8 @@ public final class AppDBParserHelper { callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, endDateTime)); } - if (!StringUtils.isEmpty(direction)) { - callLogArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, direction)); + 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())); diff --git a/InternalPythonModules/android/imo.py b/InternalPythonModules/android/imo.py index d887a6da53..0bb1b913b2 100644 --- a/InternalPythonModules/android/imo.py +++ b/InternalPythonModules/android/imo.py @@ -33,6 +33,8 @@ 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 @@ -97,20 +99,20 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): uniqueId = messagesResultSet.getString("buid") if (messagesResultSet.getInt("message_type") == 1): - direction = "Incoming" + direction = CommunicationDirection.INCOMING fromAddress = Account.Address(uniqueId, name) else: - direction = "Outgoing" + direction = CommunicationDirection.OUTGOING toAddress = Account.Address(uniqueId, name) message_read = messagesResultSet.getInt("message_read") if (message_read == 1): - msgReadStatus = AppDBParserHelper.MessageReadStatusEnum.READ + msgReadStatus = MessageReadStatusEnum.READ elif (message_read == 0): - msgReadStatus = AppDBParserHelper.MessageReadStatusEnum.UNREAD + msgReadStatus = MessageReadStatusEnum.UNREAD else: - msgReadStatus = AppDBParserHelper.MessageReadStatusEnum.UNKNOWN + msgReadStatus = MessageReadStatusEnum.UNKNOWN timeStamp = messagesResultSet.getLong("timestamp") / 1000000000 From 97ac6821ce4a1c05f6cc7a11d3f8cafb0d05a4b2 Mon Sep 17 00:00:00 2001 From: Raman Date: Wed, 11 Sep 2019 15:49:26 -0400 Subject: [PATCH 33/49] Updated AppDBParserHelper to take in a Account.Address for self account, instead of just an account id. --- .../sleuthkit/autopsy/coreutils/AppDBParserHelper.java | 6 +++--- InternalPythonModules/android/imo.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java b/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java index 0b6f567b87..538ea07098 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/AppDBParserHelper.java @@ -142,17 +142,17 @@ public final class AppDBParserHelper { * @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 selfAccountId account unique id for the self account + * @param selfAccountAddress account unique id for the self account * * @throws TskCoreException */ - public AppDBParserHelper(String moduleName, AbstractFile dbFile, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId) 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, selfAccountId, moduleName, dbFile); + this.selfAccountInstance = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(selfAccountType, selfAccountAddress.getUniqueID(), moduleName, dbFile); } /** diff --git a/InternalPythonModules/android/imo.py b/InternalPythonModules/android/imo.py index 0bb1b913b2..9b3ec78528 100644 --- a/InternalPythonModules/android/imo.py +++ b/InternalPythonModules/android/imo.py @@ -56,7 +56,7 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): self._logger = Logger.getLogger(self.__class__.__name__) def analyze(self, dataSource, fileManager, context): - selfAccountId = None + selfAccountAddress = None accountDbs = AppSQLiteDB.findAppDatabases(dataSource, "accountdb.db", True, "com.imo.android.imous") for accountDb in accountDbs: try: @@ -65,8 +65,8 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): # We can determine the IMO user ID of the device owner. # Therefore we can create and use a app account and use that # as a 'self' account instead of a Device account - if not selfAccountId: - selfAccountId = accountResultSet.getString("name") + if not selfAccountAddress: + selfAccountAddress = Account.Address(accountResultSet.getString("uid"), accountResultSet.getString("name")) except SQLException as ex: self._logger.log(Level.SEVERE, "Error processing query result for account", ex) @@ -77,7 +77,7 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer): for friendsDb in friendsDbs: try: friendsDBHelper = AppDBParserHelper("IMO Parser", friendsDb.getDBFile(), - Account.Type.IMO, Account.Type.IMO, selfAccountId ) + Account.Type.IMO, Account.Type.IMO, selfAccountAddress ) contactsResultSet = friendsDb.runQuery("SELECT buid, name FROM friends") if contactsResultSet is not None: while contactsResultSet.next(): From f4a602cb2836bf93e49bc8636ecb65199bb427eb Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 11 Sep 2019 16:56:24 -0400 Subject: [PATCH 34/49] 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 35/49] 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 36/49] 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 37/49] 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 38/49] 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 39/49] 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 40/49] 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 41/49] 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 42/49] 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 43/49] 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 44/49] 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 45/49] 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 46/49] 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 47/49] 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 48/49] 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 49/49] 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 @@ - +