From 05a1046ec34df554bf718f5f38dc9c02ea8730c4 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 27 Apr 2020 11:07:57 -0400 Subject: [PATCH] Implemented data source selection and updated the HTML and KML modules to respond to these selections --- .../CheckBoxJList.java | 4 +- .../CheckBoxListPanel.form | 6 +- .../CheckBoxListPanel.java | 24 ++-- .../autopsy/geolocation/GeoFilterPanel.java | 1 + .../geolocation/datamodel/GeoPath.java | 2 +- .../autopsy/report/GeneralReportModule.java | 32 ++++- .../autopsy/report/GeneralReportSettings.java | 40 ++++++ .../infrastructure/Bundle.properties-MERGED | 1 + .../infrastructure/FileReportSettings.java | 19 ++- .../infrastructure/ReportGenerator.java | 9 +- .../infrastructure/ReportVisualPanel1.java | 8 +- .../infrastructure/ReportWizardAction.java | 23 +++- .../ReportWizardDataSourceSelectionPanel.java | 125 ++++++++++++++++++ .../infrastructure/ReportWizardIterator.java | 21 ++- .../infrastructure/ReportWizardPanel1.java | 22 ++- .../infrastructure/ReportingConfig.java | 11 +- .../infrastructure/ReportingConfigLoader.java | 18 ++- .../infrastructure/TableReportGenerator.java | 42 +++++- .../infrastructure/TableReportSettings.java | 17 ++- .../modules/html/Bundle.properties-MERGED | 8 +- .../autopsy/report/modules/kml/KMLReport.java | 68 ++++++++-- 21 files changed, 441 insertions(+), 60 deletions(-) rename Core/src/org/sleuthkit/autopsy/{geolocation => corecomponents}/CheckBoxJList.java (97%) rename Core/src/org/sleuthkit/autopsy/{geolocation => corecomponents}/CheckBoxListPanel.form (88%) rename Core/src/org/sleuthkit/autopsy/{geolocation => corecomponents}/CheckBoxListPanel.java (94%) create mode 100755 Core/src/org/sleuthkit/autopsy/report/GeneralReportSettings.java create mode 100755 Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardDataSourceSelectionPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxJList.java b/Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxJList.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxJList.java rename to Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxJList.java index 7763d1a19a..3d360bb102 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxJList.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxJList.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.geolocation; +package org.sleuthkit.autopsy.corecomponents; import java.awt.BorderLayout; import java.awt.Component; diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxListPanel.form similarity index 88% rename from Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.form rename to Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxListPanel.form index 75fb1d4c62..bd65f2c17a 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxListPanel.form @@ -19,7 +19,7 @@ - + @@ -31,7 +31,7 @@ - + @@ -46,7 +46,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxListPanel.java similarity index 94% rename from Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java rename to Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxListPanel.java index bf74ba1a56..2a87d429ef 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/CheckBoxListPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.geolocation; +package org.sleuthkit.autopsy.corecomponents; import java.util.ArrayList; import java.util.Enumeration; @@ -26,9 +26,9 @@ import javax.swing.DefaultListModel; import javax.swing.Icon; /** - * A panel for showing Content objects in a check box list. + * A panel for showing any object in a check box list. */ -final class CheckBoxListPanel extends javax.swing.JPanel { +public final class CheckBoxListPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; @@ -38,7 +38,7 @@ final class CheckBoxListPanel extends javax.swing.JPanel { /** * Creates new CheckboxFilterPanel */ - CheckBoxListPanel() { + public CheckBoxListPanel() { initComponents(); checkboxList = new CheckBoxJList<>(); @@ -52,7 +52,7 @@ final class CheckBoxListPanel extends javax.swing.JPanel { * @param displayName display name for the checkbox * @param obj Object that the checkbox represents */ - void addElement(String displayName, Icon icon, T obj) { + public void addElement(String displayName, Icon icon, T obj) { ObjectCheckBox newCheckBox = new ObjectCheckBox<>(displayName, icon, true, obj); if(!model.contains(newCheckBox)) { @@ -63,11 +63,11 @@ final class CheckBoxListPanel extends javax.swing.JPanel { /** * Remove all objects from the checkbox list. */ - void clearList() { + public void clearList() { model.removeAllElements(); } - boolean isEmpty() { + public boolean isEmpty() { return model.isEmpty(); } @@ -84,7 +84,7 @@ final class CheckBoxListPanel extends javax.swing.JPanel { * * @return List of selected elements. */ - List getSelectedElements() { + public List getSelectedElements() { List selectedElements = new ArrayList<>(); Enumeration> elements = model.elements(); @@ -103,7 +103,7 @@ final class CheckBoxListPanel extends javax.swing.JPanel { * * @param selected True to check the boxes, false to unchecked */ - void setSetAllSelected(boolean selected) { + public void setSetAllSelected(boolean selected) { Enumeration> enumeration = model.elements(); while (enumeration.hasMoreElements()) { ObjectCheckBox element = enumeration.nextElement(); @@ -119,7 +119,7 @@ final class CheckBoxListPanel extends javax.swing.JPanel { * * @param title Panel title or null for no title. */ - void setPanelTitle(String title) { + public void setPanelTitle(String title) { titleLabel.setText(title); } @@ -128,7 +128,7 @@ final class CheckBoxListPanel extends javax.swing.JPanel { * * @param icon Icon to set or null for no icon */ - void setPanelTitleIcon(Icon icon) { + public void setPanelTitleIcon(Icon icon) { titleLabel.setIcon(icon); } diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java index d8121e68a1..2641b5d4b0 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.geolocation; +import org.sleuthkit.autopsy.corecomponents.CheckBoxListPanel; import java.awt.Color; import java.awt.Graphics; import java.awt.GridBagConstraints; diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/GeoPath.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/GeoPath.java index 99b5db351f..c61dea93be 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/GeoPath.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/GeoPath.java @@ -126,7 +126,7 @@ public class GeoPath { * * @return */ - final BlackboardArtifact getArtifact() { + public final BlackboardArtifact getArtifact() { return artifact; } diff --git a/Core/src/org/sleuthkit/autopsy/report/GeneralReportModule.java b/Core/src/org/sleuthkit/autopsy/report/GeneralReportModule.java index da0541b48a..c7553c9d64 100644 --- a/Core/src/org/sleuthkit/autopsy/report/GeneralReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/GeneralReportModule.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-2018 Basis Technology Corp. + * Copyright 2012-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,10 +25,36 @@ public interface GeneralReportModule extends ReportModule { * at the path specified and updating progress via the progressPanel object. * * @param baseReportDir Base directory that reports are being stored in. - * Report should go into baseReportDir + - * getRelativeFilePath(). + * Report should go into baseReportDir + getRelativeFilePath(). * @param progressPanel panel to update the report's progress with */ public void generateReport(String baseReportDir, ReportProgressPanel progressPanel); + /** + * Determines if the module supports report generation on a subset of data + * sources in a case. Defaults to false. Modules that override this to true + * should implement all generateReport overloads. The data source selections + * are stored in the GeneralReportSettings instance. + * + * @return True if the module can be configured to run on a subset of data + * sources. + */ + default boolean supportsDataSourceSelection() { + return false; + } + + /** + * Called to generate the report. Method is responsible for saving the file + * at the path specified and updating progress via the progressPanel object. + * Configuration parameters can be passed in the settings class. Modules should + * try to respond to all configuration parameters. + * + * @param baseReportDir Base directory that reports are being stored in. + * Report should go into baseReportDir + getRelativeFilePath(). + * @param settings Configuration parameters to customize the report generation process + * @param progressPanel panel to update the report's progress with + */ + default void generateReport(String baseReportDir, GeneralReportSettings settings, ReportProgressPanel progressPanel) { + generateReport(baseReportDir, progressPanel); + } } diff --git a/Core/src/org/sleuthkit/autopsy/report/GeneralReportSettings.java b/Core/src/org/sleuthkit/autopsy/report/GeneralReportSettings.java new file mode 100755 index 0000000000..34c7b20139 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/GeneralReportSettings.java @@ -0,0 +1,40 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.report; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Configuration parameters for general report modules + */ +public class GeneralReportSettings implements Serializable { + private static final long serialVersionUID = 1L; + + private List dataSourcesToProcess; + + public List getDataSourcesToProcess() { + return dataSourcesToProcess; + } + + public void setDataSourcesToProcess(List dataSourcesToProcess) { + this.dataSourcesToProcess = new ArrayList<>(dataSourcesToProcess); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle.properties-MERGED index c3bca8db45..ef0fd25142 100755 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle.properties-MERGED @@ -15,6 +15,7 @@ ReportProgressIndicator.completedWithErrorsMessage=Report generation completed w ReportProgressIndicator.startMessage=Report generation started ReportProgressIndicator.switchToDeterminateMessage=Report generation progress switched to determinate ReportProgressIndicator.switchToIndeterminateMessage=Report generation progress switched to indeterminate +ReportWizardDataSourceSelectionPanel.title=Select which datasource(s) to include ReportWizardFileOptionsVisualPanel.jLabel1.text=Select items to include in File Report: ReportWizardFileOptionsVisualPanel.deselectAllButton.text=Deselect All ReportWizardFileOptionsVisualPanel.selectAllButton.text=Select All diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/FileReportSettings.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/FileReportSettings.java index 8cde112672..c211b02244 100755 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/FileReportSettings.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/FileReportSettings.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,9 @@ package org.sleuthkit.autopsy.report.infrastructure; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -30,6 +32,7 @@ final class FileReportSettings implements Serializable { private static final long serialVersionUID = 1L; private Map filePropertiesInfo = new HashMap<>(); + private List dataSourcesToProcess; /** * Creates FileReportSettings object. @@ -49,4 +52,18 @@ final class FileReportSettings implements Serializable { Map getFileProperties() { return filePropertiesInfo; } + + /** + * Returns the data sources to process + */ + List getDataSourcesToProcess() { + return dataSourcesToProcess; + } + + /** + * Sets the data sources to process + */ + void setDataSourcesToProcess(List dataSourcesToProcess) { + this.dataSourcesToProcess = new ArrayList<>(dataSourcesToProcess); + } } diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java index 04c5413641..022b2a8667 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2019 Basis Technology Corp. + * Copyright 2013-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -48,6 +48,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.python.FactoryClassNameNormalizer; +import org.sleuthkit.autopsy.report.GeneralReportSettings; import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; import org.sleuthkit.datamodel.AbstractFile; @@ -208,7 +209,7 @@ public class ReportGenerator { if (module instanceof GeneralReportModule) { // generate report - generateGeneralReport((GeneralReportModule) module); + generateGeneralReport((GeneralReportModule) module, config.getGeneralReportSettings()); } else if (module instanceof TableReportModule) { @@ -297,11 +298,11 @@ public class ReportGenerator { /** * Run the GeneralReportModules using a SwingWorker. */ - private void generateGeneralReport(GeneralReportModule generalReportModule) throws IOException { + private void generateGeneralReport(GeneralReportModule generalReportModule, GeneralReportSettings reportSettings) throws IOException { if (generalReportModule != null) { String reportDir = createReportDirectory(generalReportModule); setupProgressPanel(generalReportModule, reportDir); - generalReportModule.generateReport(reportDir, progressIndicator); + generalReportModule.generateReport(reportDir, reportSettings, progressIndicator); } } diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java index 7eca143b80..b9d9fc8b34 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-2019 Basis Technology Corp. + * Copyright 2012-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -368,8 +368,10 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { configurationPanel.revalidate(); configurationPanel.repaint(); - boolean generalModuleSelected = (module instanceof GeneralReportModule); - + // General modules that support data source selection will be presented + // a data source selection panel, so they should not be finished immediately. + boolean generalModuleSelected = (module instanceof GeneralReportModule) && !((GeneralReportModule)module).supportsDataSourceSelection(); + wizPanel.setNext(!generalModuleSelected); wizPanel.setFinish(generalModuleSelected); } diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java index 236263200a..28d1dfff86 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2012-2019 Basis Technology Corp. + * Copyright 2012-2020 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com @@ -31,6 +31,7 @@ import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.text.MessageFormat; import java.util.EnumSet; +import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.logging.Level; @@ -52,6 +53,7 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.report.GeneralReportSettings; import org.sleuthkit.autopsy.report.ReportModule; @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.report.infrastructure.ReportWizardAction") @@ -117,8 +119,23 @@ public final class ReportWizardAction extends CallableSystemAction implements Pr private static void saveReportingConfiguration(String configName, WizardDescriptor wiz) throws ReportConfigException { ReportingConfig reportingConfig = new ReportingConfig(configName); - reportingConfig.setFileReportSettings((FileReportSettings) wiz.getProperty("fileReportSettings")); - reportingConfig.setTableReportSettings((TableReportSettings) wiz.getProperty("tableReportSettings")); + List selectedDataSourceIds = (List) wiz.getProperty("dataSourceSelections"); + + // Set the selected data source ids. + FileReportSettings fileSettings = (FileReportSettings) wiz.getProperty("fileReportSettings"); + TableReportSettings tableSettings = (TableReportSettings) wiz.getProperty("tableReportSettings"); + GeneralReportSettings generalSettings = new GeneralReportSettings(); + generalSettings.setDataSourcesToProcess(selectedDataSourceIds); + if(fileSettings != null) { + fileSettings.setDataSourcesToProcess(selectedDataSourceIds); + } + if(tableSettings != null) { + tableSettings.setDataSourcesToProcess(selectedDataSourceIds); + } + + reportingConfig.setFileReportSettings(fileSettings); + reportingConfig.setTableReportSettings(tableSettings); + reportingConfig.setGeneralReportSettings(generalSettings); Map moduleConfigs = (Map) wiz.getProperty("moduleConfigs"); diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardDataSourceSelectionPanel.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardDataSourceSelectionPanel.java new file mode 100755 index 0000000000..5a782ecc5c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardDataSourceSelectionPanel.java @@ -0,0 +1,125 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.report.infrastructure; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.logging.Level; +import javax.swing.JButton; +import javax.swing.event.ChangeListener; +import org.openide.WizardDescriptor; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.NbPreferences; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.corecomponents.CheckBoxListPanel; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Selection panel for modules that can report on a subset of data sources in a + * case. + */ +public class ReportWizardDataSourceSelectionPanel implements WizardDescriptor.FinishablePanel { + + private static final Logger logger = Logger.getLogger(ReportWizardDataSourceSelectionPanel.class.getName()); + + private CheckBoxListPanel dataSourcesSelectionPanel; + private WizardDescriptor wiz; + + private final JButton finishButton; + + public ReportWizardDataSourceSelectionPanel() { + finishButton = new JButton( + NbBundle.getMessage(this.getClass(), "ReportWizardFileOptionsPanel.finishButton.text")); + finishButton.setEnabled(false); + + finishButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + wiz.doFinishClick(); + } + }); + } + + @NbBundle.Messages({ + "ReportWizardDataSourceSelectionPanel.title=Select which datasource(s) to include" + }) + @Override + public CheckBoxListPanel getComponent() { + if (dataSourcesSelectionPanel == null) { + dataSourcesSelectionPanel = new CheckBoxListPanel<>(); + dataSourcesSelectionPanel.setPanelTitle(""); + dataSourcesSelectionPanel.setName(Bundle.ReportWizardDataSourceSelectionPanel_title()); + try { + List dataSources = Case.getCurrentCase().getDataSources(); + for (Content dataSource : dataSources) { + String dataSourceName = dataSource.getName(); + long dataSourceId = dataSource.getId(); + dataSourcesSelectionPanel.addElement(dataSourceName, null, dataSourceId); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Unable to get list of data sources from the case", ex); + } + } + return dataSourcesSelectionPanel; + } + + @Override + public HelpCtx getHelp() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public void readSettings(WizardDescriptor data) { + this.wiz = data; + wiz.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, finishButton, WizardDescriptor.CANCEL_OPTION}); + + boolean generalModule = NbPreferences.forModule(ReportWizardPanel1.class).getBoolean("generalModule", true); //NON-NLS + finishButton.setEnabled(generalModule); + } + + @Override + public void storeSettings(WizardDescriptor data) { + List selectedDataSources = getComponent().getSelectedElements(); + data.putProperty("dataSourceSelections", selectedDataSources); + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public void addChangeListener(ChangeListener cl) { + // Nothing to do + } + + @Override + public void removeChangeListener(ChangeListener cl) { + // Nothing to do + } + + @Override + public boolean isFinishPanel() { + return true; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardIterator.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardIterator.java index d39db13392..726ce8a7a5 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardIterator.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardIterator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2012-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.report.infrastructure; import java.awt.Component; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; @@ -38,6 +39,7 @@ final class ReportWizardIterator implements WizardDescriptor.Iterator> panels; @@ -78,8 +80,10 @@ final class ReportWizardIterator implements WizardDescriptor.Iterator(panels); + panels.add(1, dataSourceSelectionPanel); + } } else if (portableCaseModule) { // Portable Case Module selected, need Portable Case Configuration Panel // (ReportWizardPortableCaseOptionsPanel) @@ -164,7 +174,8 @@ final class ReportWizardIterator implements WizardDescriptor.Iterator sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +28,8 @@ import org.openide.WizardDescriptor; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; -import org.sleuthkit.autopsy.report.ReportModule; +import org.sleuthkit.autopsy.report.GeneralReportModule; +import org.sleuthkit.autopsy.report.modules.html.HTMLReport; class ReportWizardPanel1 implements WizardDescriptor.FinishablePanel { @@ -116,8 +117,21 @@ class ReportWizardPanel1 implements WizardDescriptor.FinishablePanel sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.report.infrastructure; import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import org.sleuthkit.autopsy.report.GeneralReportSettings; /** * A bundling of all the settings objects that define a report configuration. @@ -32,6 +33,7 @@ final class ReportingConfig implements Serializable { private Map moduleConfigs = new HashMap<>(); private TableReportSettings tableReportSettings; private FileReportSettings fileReportSettings; + private GeneralReportSettings generalReportSettings; /** * Creates ReportingConfig object. @@ -74,4 +76,11 @@ final class ReportingConfig implements Serializable { return this.fileReportSettings; } + GeneralReportSettings getGeneralReportSettings() { + return this.generalReportSettings; + } + + void setGeneralReportSettings(GeneralReportSettings generalReportSettings) { + this.generalReportSettings = generalReportSettings; + } } diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportingConfigLoader.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportingConfigLoader.java index 6472105888..7f1ee8fc87 100755 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportingConfigLoader.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportingConfigLoader.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,6 +34,7 @@ import org.openide.util.io.NbObjectInputStream; import org.openide.util.io.NbObjectOutputStream; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.report.GeneralReportSettings; /** * Utility class responsible for managing serialization and deserialization of @@ -48,6 +49,7 @@ final class ReportingConfigLoader { private static final String REPORT_SETTINGS_FILE_EXTENSION = ".settings"; private static final String TABLE_REPORT_CONFIG_FILE = "TableReportSettings.settings"; private static final String FILE_REPORT_CONFIG_FILE = "FileReportSettings.settings"; + private static final String GENERAL_REPORT_CONFIG_FILE = "GeneralReportSettings.settings"; private static final String MODULE_CONFIG_FILE = "ModuleConfigs.settings"; /** @@ -96,6 +98,13 @@ final class ReportingConfigLoader { } catch (IOException | ClassNotFoundException ex) { throw new ReportConfigException("Unable to read file report settings " + filePath, ex); } + + filePath = reportDirPath.resolve(GENERAL_REPORT_CONFIG_FILE).toString(); + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePath))) { + config.setGeneralReportSettings((GeneralReportSettings) in.readObject()); + } catch (IOException | ClassNotFoundException ex) { + throw new ReportConfigException("Unable to read general report settings " + filePath, ex); + } // read map of module configuration objects Map moduleConfigs = null; @@ -173,6 +182,13 @@ final class ReportingConfigLoader { } catch (IOException ex) { throw new ReportConfigException("Unable to save file report configuration " + filePath, ex); } + + filePath = pathToConfigDir.resolve(GENERAL_REPORT_CONFIG_FILE).toString(); + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { + out.writeObject(reportConfig.getGeneralReportSettings()); + } catch (IOException ex) { + throw new ReportConfigException("Unable to save general report configuration " + filePath, ex); + } // save map of module configuration objects filePath = pathToConfigDir.toString() + File.separator + MODULE_CONFIG_FILE; diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java index aa4ceab7dc..4cd2b349cc 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2019 Basis Technology Corp. + * Copyright 2013-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -366,6 +366,18 @@ class TableReportGenerator { // Give the modules the rows for the content tags. for (ContentTag tag : tags) { + try { + long dataSourceId = tag.getContent().getDataSource().getId(); + // Skip tags that are not in the data sources list + if(!this.settings.getDataSourcesToProcess().contains(dataSourceId)) { + continue; + } + } catch (TskCoreException ex) { + errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetContentTags")); + logger.log(Level.SEVERE, "failed to get data source of content tag", ex); //NON-NLS + return; + } + // skip tags that we are not reporting on String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; if (passesTagNamesFilter(tag.getName().getDisplayName() + notableString) == false) { @@ -446,6 +458,18 @@ class TableReportGenerator { // Give the modules the rows for the content tags. for (BlackboardArtifactTag tag : tags) { + try { + long dataSourceId = tag.getContent().getDataSource().getId(); + // Skip tags that are not in the data sources list + if (!this.settings.getDataSourcesToProcess().contains(dataSourceId)) { + continue; + } + } catch (TskCoreException ex) { + errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetBBArtifactTags")); + logger.log(Level.SEVERE, "failed to get data source of blackboard artifact tag", ex); //NON-NLS + return; + } + String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; if (passesTagNamesFilter(tag.getName().getDisplayName() + notableString) == false) { continue; @@ -799,6 +823,11 @@ class TableReportGenerator { AbstractFile f = openCase.getSleuthkitCase().getAbstractFileById(objId); if (f != null) { uniquePath = openCase.getSleuthkitCase().getAbstractFileById(objId).getUniquePath(); + long dataSourceId = f.getDataSource().getId(); + // Skip files that are not in the data sources list + if(!this.settings.getDataSourcesToProcess().contains(dataSourceId)) { + continue; + } } } catch (TskCoreException ex) { errorList.add( @@ -956,6 +985,11 @@ class TableReportGenerator { AbstractFile f = openCase.getSleuthkitCase().getAbstractFileById(objId); if (f != null) { uniquePath = openCase.getSleuthkitCase().getAbstractFileById(objId).getUniquePath(); + long dataSourceId = f.getDataSource().getId(); + // Skip files that are not in the data sources list. + if(!this.settings.getDataSourcesToProcess().contains(dataSourceId)) { + continue; + } } } catch (TskCoreException ex) { errorList.add( @@ -1198,6 +1232,12 @@ class TableReportGenerator { List artifacts = new ArrayList<>(); try { for (BlackboardArtifact artifact : Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifacts(type.getTypeID())) { + long dataSourceId = artifact.getDataSource().getId(); + // Skip artifacts that are not in the data sources list + if(!this.settings.getDataSourcesToProcess().contains(dataSourceId)) { + continue; + } + List tags = Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact); HashSet uniqueTagNames = new HashSet<>(); for (BlackboardArtifactTag tag : tags) { diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportSettings.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportSettings.java index 1b482046ee..6f264ddd44 100755 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportSettings.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportSettings.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,6 +45,7 @@ final class TableReportSettings implements Serializable { private final List tagNames = new ArrayList<>(); private final boolean useStoredTagsAndArtifactsLists; private final TableReportOption reportOption; + private List dataSourcesToProcess; /** * Creates TableReportSettings object. This constructor is used when user @@ -99,4 +100,18 @@ final class TableReportSettings implements Serializable { TableReportOption getSelectedReportOption() { return reportOption; } + + /** + * Returns the data sources to process + */ + List getDataSourcesToProcess() { + return dataSourcesToProcess; + } + + /** + * Sets the data sources to process + */ + void setDataSourcesToProcess(List dataSourcesToProcess) { + this.dataSourcesToProcess = new ArrayList<>(dataSourcesToProcess); + } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED index 0be7595111..3db1b822ea 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED @@ -5,18 +5,18 @@ ReportHTML.getName.text=HTML Report ReportHTML.getDesc.text=A report about results and tagged items in HTML format. ReportHTML.writeIndex.title=for case {0} ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup. -ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, -ReportHTML.writeIndex.seeSum=and the summary page for a case summary. +ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, +ReportHTML.writeIndex.seeSum=and the summary page for a case summary. ReportHTML.writeNav.title=Report Navigation ReportHTML.writeNav.h1=Report Navigation ReportHTML.writeNav.summary=Case Summary ReportHTML.writeSum.case=Case: ReportHTML.writeSum.caseNotes=Notes: ReportHTML.writeSum.caseNumber=Case Number: -ReportHTML.writeSum.caseNumImages=Number of Images: +ReportHTML.writeSum.caseNumImages=Number of data sources in case: ReportHTML.writeSum.examiner=Examiner: ReportHTML.writeSum.title=Case Summary -ReportHTML.writeSum.warningMsg=Warning, this report was run before ingest services completed! +ReportHTML.writeSum.warningMsg=Warning, this report was run before ingest services completed\! # # autopsy/test/scripts/regression.py._html_report_diff() uses reportGenOn.text, caseName, caseNum, # examiner as a regex signature to skip report.html and summary.html diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java index c13f385ba3..3a201a3466 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java @@ -35,6 +35,7 @@ import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.List; import java.util.logging.Level; +import java.util.stream.Collectors; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.Namespace; @@ -49,9 +50,11 @@ import org.sleuthkit.autopsy.geolocation.datamodel.Waypoint; import org.sleuthkit.autopsy.geolocation.datamodel.Route; import org.sleuthkit.autopsy.geolocation.datamodel.Track; import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder; +import org.sleuthkit.autopsy.report.GeneralReportSettings; import org.sleuthkit.autopsy.report.ReportBranding; import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; import org.sleuthkit.datamodel.SleuthkitCase; @@ -80,6 +83,8 @@ public final class KMLReport implements GeneralReportModule { private Element gpsSearchesFolder; private Element gpsTrackpointsFolder; private Element gpsTracksFolder; + + private GeneralReportSettings settings; private List waypointList = null; @@ -153,15 +158,21 @@ public final class KMLReport implements GeneralReportModule { this.waypointList = waypointList; generateReport(baseReportDir, progressPanel); } - + @Override - public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) { + public boolean supportsDataSourceSelection() { + return true; + } + + @Override + public void generateReport(String baseReportDir, GeneralReportSettings settings, ReportProgressPanel progressPanel) { try { currentCase = Case.getCurrentCaseThrows(); } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS return; } + this.settings = settings; // Start the progress bar and setup the report progressPanel.setIndeterminate(true); progressPanel.start(); @@ -181,7 +192,7 @@ public final class KMLReport implements GeneralReportModule { makeRoutes(skCase); makeTracks(skCase); addLocationsToReport(skCase, baseReportDir); - } catch (GeoLocationDataException | IOException ex) { + } catch (GeoLocationDataException | IOException | TskCoreException ex) { errorMessage = "Failed to complete report."; logger.log(Level.SEVERE, errorMessage, ex); //NON-NLS result = ReportProgressPanel.ReportStatus.ERROR; @@ -225,6 +236,23 @@ public final class KMLReport implements GeneralReportModule { progressPanel.complete(result, errorMessage); } + @Override + public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) { + try { + GeneralReportSettings settings = new GeneralReportSettings(); + currentCase = Case.getCurrentCaseThrows(); + // Process all data sources if none are provided. + List selections = currentCase.getDataSources() + .stream() + .map(Content::getId) + .collect(Collectors.toList()); + settings.setDataSourcesToProcess(selections); + generateReport(baseReportDir, settings, progressPanel); + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.SEVERE, "Exception while accessing case resources.", ex); //NON-NLS + } + } + /** * Do all of the setting up of elements needed for the report. * @@ -318,8 +346,14 @@ public final class KMLReport implements GeneralReportModule { * * @throws IOException */ - void addExifMetadataContent(List points, String baseReportDirectory) throws IOException { + void addExifMetadataContent(List points, String baseReportDirectory) throws IOException, TskCoreException { for (Waypoint point : points) { + long pointDataSource = point.getArtifact().getDataSource().getId(); + // Skip this point if its not in the data sources list. + if(!settings.getDataSourcesToProcess().contains(pointDataSource)) { + continue; + } + Element mapPoint = makePoint(point); if (mapPoint == null) { return; @@ -352,7 +386,7 @@ public final class KMLReport implements GeneralReportModule { * @throws TskCoreException * @throws IOException */ - void addLocationsToReport(SleuthkitCase skCase, String baseReportDir) throws GeoLocationDataException, IOException { + void addLocationsToReport(SleuthkitCase skCase, String baseReportDir) throws GeoLocationDataException, IOException, TskCoreException { if (waypointList == null) { addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(skCase), baseReportDir); addWaypoints(WaypointBuilder.getBookmarkWaypoints(skCase), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String()); @@ -376,9 +410,13 @@ public final class KMLReport implements GeneralReportModule { * @param folder The Element folder to add the points to * @param waypointColor The color the waypoint should appear in the report */ - void addWaypoints(List points, Element folder, FeatureColor waypointColor, String headerLabel) { + void addWaypoints(List points, Element folder, FeatureColor waypointColor, String headerLabel) throws TskCoreException { for (Waypoint point : points) { - addContent(folder, point.getLabel(), waypointColor, getFormattedDetails(point, headerLabel), point.getTimestamp(), makePoint(point), point.getLatitude(), point.getLongitude()); + long pointDataSource = point.getArtifact().getDataSource().getId(); + // Only add this waypoint if its in the data sources list. + if(settings.getDataSourcesToProcess().contains(pointDataSource)) { + addContent(folder, point.getLabel(), waypointColor, getFormattedDetails(point, headerLabel), point.getTimestamp(), makePoint(point), point.getLatitude(), point.getLongitude()); + } } } @@ -408,7 +446,7 @@ public final class KMLReport implements GeneralReportModule { * * @throws TskCoreException */ - void makeRoutes(SleuthkitCase skCase) throws GeoLocationDataException { + void makeRoutes(SleuthkitCase skCase) throws GeoLocationDataException, TskCoreException { List routes = null; if (waypointList == null) { @@ -418,7 +456,11 @@ public final class KMLReport implements GeneralReportModule { } for (Route route : routes) { - addRouteToReport(route); + long routeDataSource = route.getArtifact().getDataSource().getId(); + // Only add routes that are in the data sources list + if(settings.getDataSourcesToProcess().contains(routeDataSource)) { + addRouteToReport(route); + } } } @@ -479,7 +521,7 @@ public final class KMLReport implements GeneralReportModule { * * @throws TskCoreException */ - void makeTracks(SleuthkitCase skCase) throws GeoLocationDataException { + void makeTracks(SleuthkitCase skCase) throws GeoLocationDataException, TskCoreException { List tracks = null; if (waypointList == null) { @@ -489,7 +531,11 @@ public final class KMLReport implements GeneralReportModule { } for (Track track : tracks) { - addTrackToReport(track); + long trackDataSource = track.getArtifact().getDataSource().getId(); + // Only add tracks that are in the data sources list + if(settings.getDataSourcesToProcess().contains(trackDataSource)) { + addTrackToReport(track); + } } }