From 4a2308b9b0af8714bd0234caf8e62adb8c2d3383 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 23 Jul 2020 10:09:29 -0400 Subject: [PATCH 01/19] summarizer start --- .../DataSourceSummaryResultViewer.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java diff --git a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java new file mode 100644 index 0000000000..90c53e6217 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java @@ -0,0 +1,83 @@ +/* + * 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.resultviewers.summary; + +import org.openide.explorer.ExplorerManager; +import org.openide.nodes.Node; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; +import org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.DataSource; + + + +/** + * + * @author gregd + */ +public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { + private final String title; + + public DataSourceSummaryResultViewer() { + this(null); + } + + @Messages({ + "DataSourceSummaryResultViewer_title=Summary" + }) + public DataSourceSummaryResultViewer(ExplorerManager explorerManager) { + this(explorerManager, Bundle.DataSourceSummaryResultViewer_title()); + } + + public DataSourceSummaryResultViewer(ExplorerManager explorerManager, String title) { + super(explorerManager); + this.title = title; + } + + @Override + public DataResultViewer createInstance() { + return new DataSourceSummaryResultViewer(); + } + + @Override + public boolean isSupported(Node node) { + if (node == null) { + return false; + } + + DataSource contentItem = node.getLookup().lookup(DataSource.class); + if (contentItem == null) { + return false; + } + + Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId); + } + + @Override + public void setNode(Node node) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public String getTitle() { + return title; + } +} From 1ca277aae8be3115ede39dbe596ea4d6335fbec0 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 23 Jul 2020 15:32:09 -0400 Subject: [PATCH 02/19] panel integration and refactoring --- .../DataSourceSummaryDetailsPanel.java | 165 ++++++++++-------- .../DataSourceSummaryDialog.form | 5 + .../DataSourceSummaryDialog.java | 19 +- .../DataSourceSummaryResultViewer.java | 64 +++++-- 4 files changed, 154 insertions(+), 99 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java index 1b898f4995..61667dbb42 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.table.DefaultTableModel; +import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Image; @@ -36,23 +37,48 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel { //Because this panel was made using the gridbaglayout and netbean's Customize Layout tool it will be best to continue to modify it through that private static final long serialVersionUID = 1L; - private Map osDetailMap = new HashMap<>(); private static final Integer SIZE_COVERSION_CONSTANT = 1000; private static final DecimalFormat APPROXIMATE_SIZE_FORMAT = new DecimalFormat("#.##"); - private final Map unallocatedFilesSizeMap; - private final Map usageMap; private static final Logger logger = Logger.getLogger(DataSourceSummaryDetailsPanel.class.getName()); + private DataSource dataSource; + /** * Creates new form DataSourceSummaryDetailsPanel */ @Messages({"DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case.", "DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure"}) - DataSourceSummaryDetailsPanel(Map usageMap) { + DataSourceSummaryDetailsPanel() { initComponents(); - this.usageMap = usageMap; - this.unallocatedFilesSizeMap = DataSourceInfoUtilities.getSizeOfUnallocatedFiles(); - osDetailMap = DataSourceInfoUtilities.getOperatingSystems(); + setDataSource(null); + } + + /** + * The datasource currently used as the model in this panel. + * + * @return The datasource currently being used as the model in this panel. + */ + public DataSource getDataSource() { + return dataSource; + } + + /** + * Sets datasource to visualize in the panel. + * + * @param dataSource The datasource to use in this panel. + */ + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + + if (dataSource == null) { + updateDetailsPanelData(null, null, null, null); + } else { + long id = dataSource.getId(); + updateDetailsPanelData(dataSource, + DataSourceInfoUtilities.getSizeOfUnallocatedFiles().get(id), + DataSourceInfoUtilities.getOperatingSystems().get(id), + DataSourceInfoUtilities.getDataSourceTypes().get(id)); + } } /** @@ -60,77 +86,80 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel { * * @param selectedDataSource the DataSource to display details about. */ - void updateDetailsPanelData(DataSource selectedDataSource) { + private void updateDetailsPanelData(DataSource selectedDataSource, Long unallocatedFilesSize, String osDetails, String usage) { clearTableValues(); if (selectedDataSource != null) { - String sizeString = ""; - String sectorSizeString = ""; - String md5String = ""; - String sha1String = ""; - String sha256String = ""; - String acquisitionDetailsString = ""; - String imageTypeString = ""; - String[] filePaths = new String[0]; - String osDetailString = osDetailMap.get(selectedDataSource.getId()) == null ? "" : osDetailMap.get(selectedDataSource.getId()); - String dataSourceTypeString = usageMap.get(selectedDataSource.getId()) == null ? "" : usageMap.get(selectedDataSource.getId()); - try { - acquisitionDetailsString = selectedDataSource.getAcquisitionDetails(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex); - } - if (selectedDataSource instanceof Image) { - imageTypeString = ((Image) selectedDataSource).getType().getName(); - filePaths = ((Image) selectedDataSource).getPaths(); - sizeString = getSizeString(selectedDataSource.getSize()); - sectorSizeString = getSizeString(((Image) selectedDataSource).getSsize()); - try { - //older databases may have null as the hash values - md5String = ((Image) selectedDataSource).getMd5(); - if (md5String == null) { - md5String = ""; - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get MD5 for selected data source", ex); - } - try { - sha1String = ((Image) selectedDataSource).getSha1(); - if (sha1String == null) { - sha1String = ""; - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get SHA1 for selected data source", ex); - } - try { - sha256String = ((Image) selectedDataSource).getSha256(); - if (sha256String == null) { - sha256String = ""; - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get SHA256 for selected data source", ex); - } - } + unallocatedSizeValue.setText(getSizeString(unallocatedFilesSize)); + operatingSystemValue.setText(StringUtils.isBlank(osDetails) ? "" : osDetails); + dataSourceUsageValue.setText(StringUtils.isBlank(usage) ? "" : usage); + + timeZoneValue.setText(selectedDataSource.getTimeZone()); displayNameValue.setText(selectedDataSource.getName()); originalNameValue.setText(selectedDataSource.getName()); deviceIdValue.setText(selectedDataSource.getDeviceId()); - dataSourceUsageValue.setText(dataSourceTypeString); - operatingSystemValue.setText(osDetailString); - timeZoneValue.setText(selectedDataSource.getTimeZone()); - acquisitionDetailsTextArea.setText(acquisitionDetailsString); - imageTypeValue.setText(imageTypeString); - sizeValue.setText(sizeString); - unallocatedSizeValue.setText(getSizeString(unallocatedFilesSizeMap.get(selectedDataSource.getId()))); - sectorSizeValue.setText(sectorSizeString); - md5HashValue.setText(md5String); - sha1HashValue.setText(sha1String); - sha256HashValue.setText(sha256String); - for (String path : filePaths) { - ((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path}); + + try { + acquisitionDetailsTextArea.setText(selectedDataSource.getAcquisitionDetails()); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex); + } + + if (selectedDataSource instanceof Image) { + setFieldsForImage((Image) selectedDataSource); } } updateFieldVisibility(); this.repaint(); } + /** + * Sets text fields for an image. This should be called after + * clearTableValues and before updateFieldVisibility to ensure the proper + * rendering. + * + * @param selectedImage The selected image. + */ + private void setFieldsForImage(Image selectedImage) { + imageTypeValue.setText(selectedImage.getType().getName()); + sizeValue.setText(getSizeString(selectedImage.getSize())); + sectorSizeValue.setText(getSizeString(selectedImage.getSsize())); + + for (String path : selectedImage.getPaths()) { + ((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path}); + } + + try { + //older databases may have null as the hash values + String md5String = selectedImage.getMd5(); + if (md5String == null) { + md5String = ""; + } + md5HashValue.setText(md5String); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get MD5 for selected data source", ex); + } + + try { + String sha1String = selectedImage.getSha1(); + if (sha1String == null) { + sha1String = ""; + } + sha1HashValue.setText(sha1String); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get SHA1 for selected data source", ex); + } + + try { + String sha256String = selectedImage.getSha256(); + if (sha256String == null) { + sha256String = ""; + } + sha256HashValue.setText(sha256String); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get SHA256 for selected data source", ex); + } + } + /** * Get a long size in bytes as a string formated to be read by users. * @@ -147,7 +176,7 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel { "DataSourceSummaryDetailsPanel.units.terabytes= TB", "DataSourceSummaryDetailsPanel.units.petabytes= PB" }) - private String getSizeString(Long size) { + private static String getSizeString(Long size) { if (size == null) { return ""; } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.form index 72c45cb5a7..272fc9b041 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.form @@ -68,6 +68,11 @@ + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java index 3c68b7b3ed..e1197fa83a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java @@ -27,7 +27,6 @@ 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; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason; @@ -41,10 +40,8 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser 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; - private final IngestJobInfoPanel ingestHistoryPanel; + private final DataSourceSummaryTabbedPane dataSourceSummaryTabbedPane; /** * Creates new form DataSourceSummaryDialog for displaying a summary of the @@ -61,21 +58,14 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser super(owner, Bundle.DataSourceSummaryDialog_window_title(), true); Map usageMap = DataSourceInfoUtilities.getDataSourceTypes(); Map fileCountsMap = DataSourceInfoUtilities.getCountsOfFiles(); - countsPanel = new DataSourceSummaryCountsPanel(fileCountsMap); - detailsPanel = new DataSourceSummaryDetailsPanel(usageMap); dataSourcesPanel = new DataSourceBrowser(usageMap, fileCountsMap); - ingestHistoryPanel = new IngestJobInfoPanel(); + dataSourceSummaryTabbedPane = new DataSourceSummaryTabbedPane(); initComponents(); dataSourceSummarySplitPane.setLeftComponent(dataSourcesPanel); - dataSourceTabbedPane.addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); - dataSourceTabbedPane.addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); - dataSourceTabbedPane.addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); dataSourcesPanel.addListSelectionListener((ListSelectionEvent e) -> { if (!e.getValueIsAdjusting()) { DataSource selectedDataSource = dataSourcesPanel.getSelectedDataSource(); - countsPanel.updateCountsTableData(selectedDataSource); - detailsPanel.updateDetailsPanelData(selectedDataSource); - ingestHistoryPanel.setDataSource(selectedDataSource); + dataSourceSummaryTabbedPane.setDataSource(selectedDataSource); this.repaint(); } }); @@ -116,7 +106,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser closeButton = new javax.swing.JButton(); dataSourceSummarySplitPane = new javax.swing.JSplitPane(); - dataSourceTabbedPane = new javax.swing.JTabbedPane(); + javax.swing.JTabbedPane dataSourceTabbedPane = dataSourceSummaryTabbedPane; org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(DataSourceSummaryDialog.class, "DataSourceSummaryDialog.closeButton.text")); // NOI18N closeButton.addActionListener(new java.awt.event.ActionListener() { @@ -173,6 +163,5 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton closeButton; private javax.swing.JSplitPane dataSourceSummarySplitPane; - private javax.swing.JTabbedPane dataSourceTabbedPane; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java index 90c53e6217..4a528c06d2 100644 --- a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java @@ -18,22 +18,31 @@ */ package org.sleuthkit.autopsy.resultviewers.summary; +import java.awt.BorderLayout; +import java.awt.Cursor; +import java.util.logging.Level; +import javax.swing.SwingUtilities; import org.openide.explorer.ExplorerManager; import org.openide.nodes.Node; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryTabbedPane; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer; -import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; - +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** - * - * @author gregd + * A tabular result viewer that displays a summary of the selected Data Source. */ +@ServiceProvider(service = DataResultViewer.class) +@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(DataSourceSummaryResultViewer.class.getName()); + private final String title; public DataSourceSummaryResultViewer() { @@ -50,6 +59,7 @@ public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { public DataSourceSummaryResultViewer(ExplorerManager explorerManager, String title) { super(explorerManager); this.title = title; + initComponents(); } @Override @@ -59,25 +69,47 @@ public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { @Override public boolean isSupported(Node node) { - if (node == null) { - return false; - } - - DataSource contentItem = node.getLookup().lookup(DataSource.class); - if (contentItem == null) { - return false; - } - - Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId); + return getDataSource(node) != null; + } + + private DataSource getDataSource(Node node) { + return node == null ? null: node.getLookup().lookup(DataSource.class); } @Override + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public void setNode(Node node) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + if (!SwingUtilities.isEventDispatchThread()) { + LOGGER.log(Level.SEVERE, "Attempting to run setNode() from non-EDT thread."); + return; + } + + DataSource dataSource = getDataSource(node); + + if (dataSource == null) { + LOGGER.log(Level.SEVERE, "No datasource for node found."); + return; + } + + this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + try { + summaryPanel.setDataSource(dataSource); + } + finally { + this.setCursor(null); + } } @Override public String getTitle() { return title; } + + private void initComponents() { + summaryPanel = new DataSourceSummaryTabbedPane(); + setLayout(new BorderLayout()); + add(summaryPanel, BorderLayout.CENTER); + } + + private DataSourceSummaryTabbedPane summaryPanel; } From d519a9d896bac02bc1b2b6a401f9d656a840d58e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 23 Jul 2020 15:32:19 -0400 Subject: [PATCH 03/19] panel integration and refactoring --- .../DataSourceSummaryTabbedPane.java | 64 +++++++++++++++++++ .../summary/Bundle.properties-MERGED | 2 + 2 files changed, 66 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java create mode 100644 Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java new file mode 100644 index 0000000000..50b78eced9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java @@ -0,0 +1,64 @@ +/* + * 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.casemodule.datasourcesummary; + +import java.util.Map; +import javax.swing.JTabbedPane; +import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; +import org.sleuthkit.datamodel.DataSource; + +/** + * A tabbed pane showing the summary of a data source including tabs of: + * DataSourceSummaryCountsPanel, DataSourceSummaryDetailsPanel, and + * IngestJobInfoPanel. + */ +public class DataSourceSummaryTabbedPane extends JTabbedPane { + private final DataSourceSummaryCountsPanel countsPanel; + private final DataSourceSummaryDetailsPanel detailsPanel; + private final IngestJobInfoPanel ingestHistoryPanel; + + private DataSource dataSource = null; + + public DataSourceSummaryTabbedPane() { + Map fileCountsMap = DataSourceInfoUtilities.getCountsOfFiles(); + + + countsPanel = new DataSourceSummaryCountsPanel(fileCountsMap); + detailsPanel = new DataSourceSummaryDetailsPanel(); + ingestHistoryPanel = new IngestJobInfoPanel(); + + addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); + addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); + addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); + } + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + + + countsPanel.updateCountsTableData(dataSource); + detailsPanel.setDataSource(dataSource); + ingestHistoryPanel.setDataSource(dataSource); + // TODO trigger updates in child components + } +} diff --git a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED new file mode 100644 index 0000000000..7965b3e04e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED @@ -0,0 +1,2 @@ +DataSourceSummaryResultViewer_title=Summary +TestPanel.jTextField1.text=It's a datasource From 1eb5fc5a331831b9ae8cbfed15c5c01404e7d1d3 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 23 Jul 2020 17:19:41 -0400 Subject: [PATCH 04/19] refactoring --- .../DataSourceSummaryTabbedPane.java | 19 +- .../DataSourceSummaryCountsPanel.form | 22 +- .../DataSourceSummaryCountsPanel.java | 375 ++++++------------ 3 files changed, 141 insertions(+), 275 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java index 50b78eced9..0bb1cfbef5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.casemodule.datasourcesummary; -import java.util.Map; import javax.swing.JTabbedPane; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; import org.sleuthkit.datamodel.DataSource; @@ -36,29 +35,27 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { private DataSource dataSource = null; public DataSourceSummaryTabbedPane() { - Map fileCountsMap = DataSourceInfoUtilities.getCountsOfFiles(); - - - countsPanel = new DataSourceSummaryCountsPanel(fileCountsMap); + countsPanel = new DataSourceSummaryCountsPanel(); detailsPanel = new DataSourceSummaryDetailsPanel(); ingestHistoryPanel = new IngestJobInfoPanel(); - + setTabs(); + } + + private void setTabs() { + this.removeAll(); addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); } - + public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; - - - countsPanel.updateCountsTableData(dataSource); + countsPanel.setDataSource(dataSource); detailsPanel.setDataSource(dataSource); ingestHistoryPanel.setDataSource(dataSource); - // TODO trigger updates in child components } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form index d3a17e0205..b82bd6f3a8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form @@ -70,18 +70,13 @@ - - - - - - + @@ -93,25 +88,20 @@ - - - - - - + - + @@ -125,12 +115,6 @@ - - - - -
-
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java index 1d99f1c445..8de75b1c24 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java @@ -18,12 +18,9 @@ */ package org.sleuthkit.autopsy.casemodule.datasourcesummary; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JLabel; -import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import org.openide.util.NbBundle.Messages; @@ -34,32 +31,53 @@ import org.sleuthkit.datamodel.DataSource; * Panel for displaying summary information on the known files present in the * specified DataSource */ +@Messages({"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type", + "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.count.header=Count", + "DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type", + "DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count", + "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.type.header=File Type", + "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count" +}) class DataSourceSummaryCountsPanel extends javax.swing.JPanel { - + private static final Object[] MIME_TYPE_COLUMN_HEADERS = new Object[]{ + Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_type_header(), + Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_count_header() + }; + + private static final Object[] FILE_BY_CATEGORY_COLUMN_HEADERS = new Object[]{ + Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_type_header(), + Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_count_header() + }; + + private static final Object[] ARTIFACT_COUNTS_COLUMN_HEADERS = new Object[]{ + Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_type_header(), + Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header() + }; + private static final long serialVersionUID = 1L; - private FilesByMimeTypeTableModel filesByMimeTypeTableModel = new FilesByMimeTypeTableModel(null); - private FilesByCategoryTableModel filesByCategoryTableModel = new FilesByCategoryTableModel(null); private static final Logger logger = Logger.getLogger(DataSourceSummaryCountsPanel.class.getName()); - private final Map allFilesCountsMap; - private final Map slackFilesCountsMap; - private final Map directoriesCountsMap; - private final Map unallocatedFilesCountsMap; - private final Map> artifactsByTypeCountsMap; private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer(); + + private DataSource dataSource; /** * Creates new form DataSourceSummaryCountsPanel */ - DataSourceSummaryCountsPanel(Map fileCountsMap) { - this.allFilesCountsMap = fileCountsMap; - this.slackFilesCountsMap = DataSourceInfoUtilities.getCountsOfSlackFiles(); - this.directoriesCountsMap = DataSourceInfoUtilities.getCountsOfDirectories(); - this.unallocatedFilesCountsMap = DataSourceInfoUtilities.getCountsOfUnallocatedFiles(); - this.artifactsByTypeCountsMap = DataSourceInfoUtilities.getCountsOfArtifactsByType(); + DataSourceSummaryCountsPanel() { rightAlignedRenderer.setHorizontalAlignment(JLabel.RIGHT); initComponents(); fileCountsByMimeTypeTable.getTableHeader().setReorderingAllowed(false); fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false); + setDataSource(null); + } + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + updateCountsTableData(dataSource); } /** @@ -67,36 +85,107 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { * * @param selectedDataSource the DataSource to display file information for */ - void updateCountsTableData(DataSource selectedDataSource) { - filesByMimeTypeTableModel = new FilesByMimeTypeTableModel(selectedDataSource); - fileCountsByMimeTypeTable.setModel(filesByMimeTypeTableModel); + private void updateCountsTableData(DataSource selectedDataSource) { + fileCountsByMimeTypeTable.setModel(new DefaultTableModel(getMimeTypeModel(selectedDataSource), MIME_TYPE_COLUMN_HEADERS)); fileCountsByMimeTypeTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); fileCountsByMimeTypeTable.getColumnModel().getColumn(0).setPreferredWidth(130); - filesByCategoryTableModel = new FilesByCategoryTableModel(selectedDataSource); - fileCountsByCategoryTable.setModel(filesByCategoryTableModel); + + fileCountsByCategoryTable.setModel(new DefaultTableModel(getFileCategoryModel(selectedDataSource), FILE_BY_CATEGORY_COLUMN_HEADERS)); fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130); - updateArtifactCounts(selectedDataSource); - this.repaint(); - } - - /** - * Helper method to update the artifact specific counts by clearing the - * table and adding counts for the artifacts which exist in the selected - * data source. - * - * @param selectedDataSource the data source to display artifact counts for - */ - private void updateArtifactCounts(DataSource selectedDataSource) { - ((DefaultTableModel) artifactCountsTable.getModel()).setRowCount(0); - if (selectedDataSource != null && artifactsByTypeCountsMap.get(selectedDataSource.getId()) != null) { - Map artifactCounts = artifactsByTypeCountsMap.get(selectedDataSource.getId()); - for (String key : artifactCounts.keySet()) { - ((DefaultTableModel) artifactCountsTable.getModel()).addRow(new Object[]{key, artifactCounts.get(key)}); - } - } + + artifactCountsTable.setModel(new DefaultTableModel(getArtifactCountsModel(selectedDataSource), ARTIFACT_COUNTS_COLUMN_HEADERS)); artifactCountsTable.getColumnModel().getColumn(0).setPreferredWidth(230); artifactCountsTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); + + this.repaint(); + } + + + private static Object[] pair(String key, Object val) { + return new Object[]{key, val}; + } + + @Messages({ + "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images", + "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos", + "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio", + "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents", + "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables" + }) + private static Object[][] getMimeTypeModel(DataSource dataSource) { + return new Object[][]{ + pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.IMAGE)), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.VIDEO)), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.AUDIO)), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.DOCUMENTS)), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.EXECUTABLE)) + }; + } + + private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) { + return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes()); + } + + + @Messages({ + "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All", + "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated", + "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.unallocated.row=Unallocated", + "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.slack.row=Slack", + "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory" + }) + private static Object[][] getFileCategoryModel(DataSource selectedDataSource) { + Long dataSourceId = selectedDataSource == null ? null : selectedDataSource.getId(); + // or 0 if not found + Long fileCount = zeroIfNull(DataSourceInfoUtilities.getCountsOfFiles().get(dataSourceId)); + Long unallocatedFiles = zeroIfNull(DataSourceInfoUtilities.getCountsOfUnallocatedFiles().get(dataSourceId)); + Long allocatedFiles = zeroIfNull(getAllocatedCount(fileCount, unallocatedFiles)); + Long slackFiles = zeroIfNull(DataSourceInfoUtilities.getCountsOfSlackFiles().get(dataSourceId)); + Long directories = zeroIfNull(DataSourceInfoUtilities.getCountsOfDirectories().get(dataSourceId)); + + return new Object[][]{ + pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_allocated_row(), allocatedFiles), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_unallocated_row(), unallocatedFiles), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_slack_row(), slackFiles), + pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_directory_row(), directories) + }; + } + + + private static Long zeroIfNull(Long origValue) { + return origValue == null ? 0 : origValue; + } + + + private static long getAllocatedCount(Long allFilesCount, Long unallocatedFilesCount) { + if (allFilesCount == null) { + return 0; + } else if (unallocatedFilesCount == null) { + return allFilesCount; + } else { + return allFilesCount - unallocatedFilesCount; + } + } + + private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) { + Long dataSourceId = selectedDataSource == null ? null : selectedDataSource.getId(); + Map artifactMapping = DataSourceInfoUtilities.getCountsOfArtifactsByType().get(dataSourceId); + if (artifactMapping == null) { + return new Object[][]{}; + } + + return artifactMapping.entrySet().stream() + .filter((entrySet) -> entrySet != null && entrySet.getKey() != null) + .sorted((a,b) -> a.getKey().compareTo(b.getKey())) + .map((entrySet) -> new Object[]{entrySet.getKey(), entrySet.getValue()}) + .toArray(Object[][]::new); } /** @@ -118,12 +207,10 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { artifactCountsScrollPane = new javax.swing.JScrollPane(); artifactCountsTable = new javax.swing.JTable(); - fileCountsByMimeTypeTable.setModel(filesByMimeTypeTableModel); fileCountsByMimeTypeScrollPane.setViewportView(fileCountsByMimeTypeTable); org.openide.awt.Mnemonics.setLocalizedText(byMimeTypeLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byMimeTypeLabel.text")); // NOI18N - fileCountsByCategoryTable.setModel(filesByCategoryTableModel); fileCountsByCategoryScrollPane.setViewportView(fileCountsByCategoryTable); org.openide.awt.Mnemonics.setLocalizedText(byCategoryLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byCategoryLabel.text")); // NOI18N @@ -131,22 +218,6 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.jLabel1.text")); // NOI18N artifactCountsTable.setAutoCreateRowSorter(true); - artifactCountsTable.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - - }, - new String [] { - "Result Type", "Count" - } - ) { - boolean[] canEdit = new boolean [] { - false, false - }; - - public boolean isCellEditable(int rowIndex, int columnIndex) { - return canEdit [columnIndex]; - } - }); artifactCountsScrollPane.setViewportView(artifactCountsTable); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); @@ -206,190 +277,4 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { private javax.swing.JTable fileCountsByMimeTypeTable; private javax.swing.JLabel jLabel1; // End of variables declaration//GEN-END:variables - - /** - * Table model for the files table model to display counts of specific file - * types by mime type found in the currently selected data source. - */ - @Messages({"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type", - "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.count.header=Count"}) - private class FilesByMimeTypeTableModel extends AbstractTableModel { - - private static final long serialVersionUID = 1L; - private final DataSource currentDataSource; - private final List columnHeaders = new ArrayList<>(); - private static final int IMAGES_ROW_INDEX = 0; - private static final int VIDEOS_ROW_INDEX = 1; - private static final int AUDIO_ROW_INDEX = 2; - private static final int DOCUMENTS_ROW_INDEX = 3; - private static final int EXECUTABLES_ROW_INDEX = 4; - - /** - * Create a FilesByMimeTypeTableModel for the speicified datasource. - * - * @param selectedDataSource the datasource which this - * FilesByMimeTypeTablemodel will represent - */ - FilesByMimeTypeTableModel(DataSource selectedDataSource) { - columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_type_header()); - columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_count_header()); - currentDataSource = selectedDataSource; - } - - @Override - public int getRowCount() { - //should be kept equal to the number of types we are displaying in the tables - return 5; - } - - @Override - public int getColumnCount() { - return columnHeaders.size(); - } - - @Messages({ - "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images", - "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos", - "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio", - "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents", - "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables" - }) - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - if (columnIndex == 0) { - switch (rowIndex) { - case IMAGES_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(); - case VIDEOS_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(); - case AUDIO_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(); - case DOCUMENTS_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(); - case EXECUTABLES_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(); - default: - break; - } - } else if (columnIndex == 1) { - switch (rowIndex) { - case 0: - return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.IMAGE.getMediaTypes()); - case 1: - return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.VIDEO.getMediaTypes()); - case 2: - return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.AUDIO.getMediaTypes()); - case 3: - return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.DOCUMENTS.getMediaTypes()); - case 4: - return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.EXECUTABLE.getMediaTypes()); - default: - break; - } - } - return null; - } - - @Override - public String getColumnName(int column) { - return columnHeaders.get(column); - } - } - - /** - * Table model for the files table model to display counts of specific file - * types by category found in the currently selected data source. - */ - @Messages({"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.type.header=File Type", - "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count"}) - private class FilesByCategoryTableModel extends AbstractTableModel { - - private static final long serialVersionUID = 1L; - private final DataSource currentDataSource; - private final List columnHeaders = new ArrayList<>(); - private static final int ALL_FILES_ROW_INDEX = 0; - private static final int ALLOCATED_FILES_ROW_INDEX = 1; - private static final int UNALLOCATED_FILES_ROW_INDEX = 2; - private static final int SLACK_FILES_ROW_INDEX = 3; - private static final int DIRECTORIES_ROW_INDEX = 4; - /** - * Create a FilesByCategoryTableModel for the speicified datasource. - * - * @param selectedDataSource the datasource which this - * FilesByCategoryTablemodel will represent - */ - FilesByCategoryTableModel(DataSource selectedDataSource) { - columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_type_header()); - columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_count_header()); - currentDataSource = selectedDataSource; - } - - @Override - public int getRowCount() { - //should be kept equal to the number of types we are displaying in the tables - return 5; - } - - @Override - public int getColumnCount() { - return columnHeaders.size(); - } - - @Messages({ - "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All", - "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated", - "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.unallocated.row=Unallocated", - "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.slack.row=Slack", - "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory" - }) - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - if (columnIndex == 0) { - switch (rowIndex) { - case ALL_FILES_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(); - case ALLOCATED_FILES_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_allocated_row(); - case UNALLOCATED_FILES_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_unallocated_row(); - case SLACK_FILES_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_slack_row(); - case DIRECTORIES_ROW_INDEX: - return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_directory_row(); - default: - break; - } - } else if (columnIndex == 1 && currentDataSource != null) { - switch (rowIndex) { - case 0: - return allFilesCountsMap.get(currentDataSource.getId()) == null ? 0 : allFilesCountsMap.get(currentDataSource.getId()); - case 1: - //All files should be either allocated or unallocated as dir_flags only has two values so any file that isn't unallocated is allocated - Long unallocatedFilesCount = unallocatedFilesCountsMap.get(currentDataSource.getId()); - Long allFilesCount = allFilesCountsMap.get(currentDataSource.getId()); - if (allFilesCount == null) { - return 0; - } else if (unallocatedFilesCount == null) { - return allFilesCount; - } else { - return allFilesCount - unallocatedFilesCount; - } - case 2: - return unallocatedFilesCountsMap.get(currentDataSource.getId()) == null ? 0 : unallocatedFilesCountsMap.get(currentDataSource.getId()); - case 3: - return slackFilesCountsMap.get(currentDataSource.getId()) == null ? 0 : slackFilesCountsMap.get(currentDataSource.getId()); - case 4: - return directoriesCountsMap.get(currentDataSource.getId()) == null ? 0 : directoriesCountsMap.get(currentDataSource.getId()); - default: - break; - } - } - return null; - } - - @Override - public String getColumnName(int column) { - return columnHeaders.get(column); - } - } } From 24e4c80a4c34c75f6df4524b3ea8cc90d2d0fe48 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 23 Jul 2020 17:25:52 -0400 Subject: [PATCH 05/19] adding bundles --- .../casemodule/datasourceSummary/Bundle.properties-MERGED | 2 ++ .../autopsy/resultviewers/summary/Bundle.properties-MERGED | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED index fe998b0e57..eb7affe9ee 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED @@ -1,4 +1,6 @@ CTL_DataSourceSummaryAction=Data Source Summary +DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count +DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count diff --git a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED index 7965b3e04e..8a629e17a9 100644 --- a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/Bundle.properties-MERGED @@ -1,2 +1 @@ DataSourceSummaryResultViewer_title=Summary -TestPanel.jTextField1.text=It's a datasource From 820006d9ab1b39195a87bd6de4c1d154b3026494 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 24 Jul 2020 08:55:42 -0400 Subject: [PATCH 06/19] code cleanup --- .../DataSourceSummaryTabbedPane.java | 29 +++- .../DataSourceSummaryCountsPanel.java | 135 ++++++++++++------ .../DataSourceSummaryDetailsPanel.java | 5 +- .../DataSourceSummaryResultViewer.java | 55 +++++-- 4 files changed, 159 insertions(+), 65 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java index 0bb1cfbef5..5fbcdeca38 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java @@ -19,21 +19,26 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import javax.swing.JTabbedPane; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; import org.sleuthkit.datamodel.DataSource; /** * A tabbed pane showing the summary of a data source including tabs of: - * DataSourceSummaryCountsPanel, DataSourceSummaryDetailsPanel, and + * DataSourceSummaryCountsPanel, DataSourceSummaryDetailsPanel, and * IngestJobInfoPanel. */ public class DataSourceSummaryTabbedPane extends JTabbedPane { + private final DataSourceSummaryCountsPanel countsPanel; private final DataSourceSummaryDetailsPanel detailsPanel; private final IngestJobInfoPanel ingestHistoryPanel; - + private DataSource dataSource = null; - + + /** + * Constructs a tabbed pane showing the summary of a data source. + */ public DataSourceSummaryTabbedPane() { countsPanel = new DataSourceSummaryCountsPanel(); detailsPanel = new DataSourceSummaryDetailsPanel(); @@ -47,15 +52,29 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); } - + + /** + * The datasource currently used as the model in this panel. + * + * @return The datasource currently being used as the model in this panel. + */ public DataSource getDataSource() { return dataSource; } + /** + * Sets datasource to visualize in the tabbed panel. + * + * @param dataSource The datasource to use in this panel. + */ public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; + countsPanel.setDataSource(dataSource); detailsPanel.setDataSource(dataSource); - ingestHistoryPanel.setDataSource(dataSource); + + // make sure ingest history panel doesn't try to show a data source when null or case is closed + ingestHistoryPanel.setDataSource( + dataSource != null && Case.isCaseOpen() ? dataSource : null); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java index 8de75b1c24..92337090c9 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java @@ -24,6 +24,7 @@ import javax.swing.JLabel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.FileTypeUtils; import org.sleuthkit.datamodel.DataSource; @@ -39,25 +40,28 @@ import org.sleuthkit.datamodel.DataSource; "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count" }) class DataSourceSummaryCountsPanel extends javax.swing.JPanel { + + private static final Object[][] EMPTY_PAIRS = new Object[][]{}; + private static final Object[] MIME_TYPE_COLUMN_HEADERS = new Object[]{ Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_type_header(), Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_count_header() }; - + private static final Object[] FILE_BY_CATEGORY_COLUMN_HEADERS = new Object[]{ Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_type_header(), Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_count_header() }; - + private static final Object[] ARTIFACT_COUNTS_COLUMN_HEADERS = new Object[]{ Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_type_header(), Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header() }; - + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(DataSourceSummaryCountsPanel.class.getName()); private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer(); - + private DataSource dataSource; /** @@ -71,41 +75,62 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { setDataSource(null); } + /** + * The datasource currently used as the model in this panel. + * + * @return The datasource currently being used as the model in this panel. + */ public DataSource getDataSource() { return dataSource; } + /** + * Sets datasource to visualize in the panel. + * + * @param dataSource The datasource to use in this panel. + */ public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; - updateCountsTableData(dataSource); + if (dataSource == null || !Case.isCaseOpen()) { + updateCountsTableData(EMPTY_PAIRS, + EMPTY_PAIRS, + EMPTY_PAIRS); + } else { + updateCountsTableData(getMimeTypeModel(dataSource), + getFileCategoryModel(dataSource), + getArtifactCountsModel(dataSource)); + } + } /** - * Specify the DataSource to display file information for + * Specify the DataSource to display file information for. * - * @param selectedDataSource the DataSource to display file information for + * @param mimeTypeDataModel The mime type data model. + * @param fileCategoryDataModel The file category data model. + * @param artifactDataModel The artifact type data model. */ - private void updateCountsTableData(DataSource selectedDataSource) { - fileCountsByMimeTypeTable.setModel(new DefaultTableModel(getMimeTypeModel(selectedDataSource), MIME_TYPE_COLUMN_HEADERS)); + private void updateCountsTableData(Object[][] mimeTypeDataModel, Object[][] fileCategoryDataModel, Object[][] artifactDataModel) { + fileCountsByMimeTypeTable.setModel(new DefaultTableModel(mimeTypeDataModel, MIME_TYPE_COLUMN_HEADERS)); fileCountsByMimeTypeTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); fileCountsByMimeTypeTable.getColumnModel().getColumn(0).setPreferredWidth(130); - - fileCountsByCategoryTable.setModel(new DefaultTableModel(getFileCategoryModel(selectedDataSource), FILE_BY_CATEGORY_COLUMN_HEADERS)); + + fileCountsByCategoryTable.setModel(new DefaultTableModel(fileCategoryDataModel, FILE_BY_CATEGORY_COLUMN_HEADERS)); fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130); - - artifactCountsTable.setModel(new DefaultTableModel(getArtifactCountsModel(selectedDataSource), ARTIFACT_COUNTS_COLUMN_HEADERS)); + + artifactCountsTable.setModel(new DefaultTableModel(artifactDataModel, ARTIFACT_COUNTS_COLUMN_HEADERS)); artifactCountsTable.getColumnModel().getColumn(0).setPreferredWidth(230); artifactCountsTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); - + this.repaint(); } - - - private static Object[] pair(String key, Object val) { - return new Object[]{key, val}; - } - + + /** + * Determines the JTable data model for datasource mime types. + * @param dataSource The DataSource. + * @return The model to be used with a JTable. + */ @Messages({ "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images", "DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos", @@ -115,24 +140,34 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { }) private static Object[][] getMimeTypeModel(DataSource dataSource) { return new Object[][]{ - pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(), - getCount(dataSource, FileTypeUtils.FileTypeCategory.IMAGE)), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(), - getCount(dataSource, FileTypeUtils.FileTypeCategory.VIDEO)), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(), - getCount(dataSource, FileTypeUtils.FileTypeCategory.AUDIO)), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(), - getCount(dataSource, FileTypeUtils.FileTypeCategory.DOCUMENTS)), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(), - getCount(dataSource, FileTypeUtils.FileTypeCategory.EXECUTABLE)) + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.IMAGE)}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.VIDEO)}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.AUDIO)}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.DOCUMENTS)}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(), + getCount(dataSource, FileTypeUtils.FileTypeCategory.EXECUTABLE)} }; } + /** + * Retrieves the counts of files of a particular mime type for a particular DataSource. + * @param dataSource The DataSource. + * @param category The mime type category. + * @return The count. + */ private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) { return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes()); } - - + + /** + * Determines the JTable data model for datasource file categories. + * @param dataSource The DataSource. + * @return The model to be used with a JTable. + */ @Messages({ "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All", "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated", @@ -150,20 +185,29 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { Long directories = zeroIfNull(DataSourceInfoUtilities.getCountsOfDirectories().get(dataSourceId)); return new Object[][]{ - pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_allocated_row(), allocatedFiles), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_unallocated_row(), unallocatedFiles), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_slack_row(), slackFiles), - pair(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_directory_row(), directories) + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_allocated_row(), allocatedFiles}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_unallocated_row(), unallocatedFiles}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_slack_row(), slackFiles}, + new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_directory_row(), directories} }; } - + /** + * Returns 0 if value is null. + * @param origValue The original value. + * @return The value or 0 if null. + */ private static Long zeroIfNull(Long origValue) { return origValue == null ? 0 : origValue; } - + /** + * Safely gets the allocated files count. + * @param allFilesCount The count of all files. + * @param unallocatedFilesCount The count of unallocated files. + * @return The count of allocated files. + */ private static long getAllocatedCount(Long allFilesCount, Long unallocatedFilesCount) { if (allFilesCount == null) { return 0; @@ -173,17 +217,22 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { return allFilesCount - unallocatedFilesCount; } } - + + /** + * The counts of different artifact types found in a DataSource. + * @param selectedDataSource The DataSource. + * @return The JTable data model of counts of artifact types. + */ private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) { Long dataSourceId = selectedDataSource == null ? null : selectedDataSource.getId(); Map artifactMapping = DataSourceInfoUtilities.getCountsOfArtifactsByType().get(dataSourceId); if (artifactMapping == null) { - return new Object[][]{}; + return EMPTY_PAIRS; } - + return artifactMapping.entrySet().stream() .filter((entrySet) -> entrySet != null && entrySet.getKey() != null) - .sorted((a,b) -> a.getKey().compareTo(b.getKey())) + .sorted((a, b) -> a.getKey().compareTo(b.getKey())) .map((entrySet) -> new Object[]{entrySet.getKey(), entrySet.getValue()}) .toArray(Object[][]::new); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java index 61667dbb42..7409c2eda3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java @@ -19,13 +19,12 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import java.text.DecimalFormat; -import java.util.Map; -import java.util.HashMap; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.table.DefaultTableModel; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.TskCoreException; @@ -70,7 +69,7 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel { public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; - if (dataSource == null) { + if (dataSource == null || !Case.isCaseOpen()) { updateDetailsPanelData(null, null, null, null); } else { long id = dataSource.getId(); diff --git a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java index 4a528c06d2..c3ca3ca2a2 100644 --- a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java @@ -33,35 +33,56 @@ import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; - /** * A tabular result viewer that displays a summary of the selected Data Source. */ @ServiceProvider(service = DataResultViewer.class) @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { + private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(DataSourceSummaryResultViewer.class.getName()); - + private final String title; - + + /** + * Constructs a tabular result viewer that displays a summary of the + * selected Data Source. + */ public DataSourceSummaryResultViewer() { this(null); } - + + /** + * Constructs a tabular result viewer that displays a summary of the + * selected Data Source. + * + * @param explorerManager The explorer manager of the ancestor top + * component. + * + */ @Messages({ "DataSourceSummaryResultViewer_title=Summary" }) public DataSourceSummaryResultViewer(ExplorerManager explorerManager) { this(explorerManager, Bundle.DataSourceSummaryResultViewer_title()); } - + + /** + * Constructs a tabular result viewer that displays a summary of the + * selected Data Source. + * + * @param explorerManager The explorer manager of the ancestor top + * component. + * @param title The title. + * + */ public DataSourceSummaryResultViewer(ExplorerManager explorerManager, String title) { super(explorerManager); this.title = title; initComponents(); } - + @Override public DataResultViewer createInstance() { return new DataSourceSummaryResultViewer(); @@ -71,9 +92,16 @@ public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { public boolean isSupported(Node node) { return getDataSource(node) != null; } - + + /** + * Returns the datasource attached to the node or null if none can be found. + * + * @param node The node to search. + * + * @return The datasource or null if not found. + */ private DataSource getDataSource(Node node) { - return node == null ? null: node.getLookup().lookup(DataSource.class); + return node == null ? null : node.getLookup().lookup(DataSource.class); } @Override @@ -83,19 +111,18 @@ public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { LOGGER.log(Level.SEVERE, "Attempting to run setNode() from non-EDT thread."); return; } - + DataSource dataSource = getDataSource(node); - + if (dataSource == null) { LOGGER.log(Level.SEVERE, "No datasource for node found."); return; } - + this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { summaryPanel.setDataSource(dataSource); - } - finally { + } finally { this.setCursor(null); } } @@ -104,7 +131,7 @@ public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { public String getTitle() { return title; } - + private void initComponents() { summaryPanel = new DataSourceSummaryTabbedPane(); setLayout(new BorderLayout()); From de588e9e5a152d20fc951d419ab9be7fdc50883a Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 24 Jul 2020 11:44:59 -0400 Subject: [PATCH 07/19] acquiring single data source in data layer --- .../DataSourceInfoUtilities.java | 45 +++++++++++++++++++ .../DataSourceSummaryCountsPanel.java | 8 ++-- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java index c2d8263056..b884118f5f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java @@ -97,6 +97,51 @@ final class DataSourceInfoUtilities { } } + private static Long baseCountOfFiles(DataSource currentDataSource, String additionalWhere, String onError) { + if (currentDataSource != null) { + try { + SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + return skCase.countFilesWhere( + "COUNT(*) AS value" + + " FROM tsk_files" + + " WHERE dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() + + " AND name<>''" + + " AND data_source_obj_id=" + currentDataSource.getId() + + " AND " + additionalWhere); + } catch (TskCoreException | NoCurrentCaseException ex) { + logger.log(Level.WARNING, onError, ex); + //unable to get count of files for the specified mimetypes cell will be displayed as empty + } + } + return null; + } + + static Long getCountOfFiles(DataSource currentDataSource) { + return baseCountOfFiles(currentDataSource, + "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(), + "Unable to get count of files, providing empty results"); + } + + static Long getCountOfUnallocatedFiles(DataSource currentDataSource) { + return baseCountOfFiles(currentDataSource, + "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue(), + "Unable to get counts of unallocated files for datasource, providing empty results"); + } + + static Long getCountOfDirectories(DataSource currentDataSource) { + return baseCountOfFiles(currentDataSource, + "'type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + + " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue(), + "Unable to get count of directories for datasource, providing empty results"); + } + + static Long getCountOfSlackFiles(DataSource currentDataSource) { + return baseCountOfFiles(currentDataSource, + "type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(), + "Unable to get count of slack files for datasources, providing empty results"); + } + /** * Get a map containing the number of artifacts in each data source in the * current case. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java index 92337090c9..0df73ce93f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java @@ -178,11 +178,11 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { private static Object[][] getFileCategoryModel(DataSource selectedDataSource) { Long dataSourceId = selectedDataSource == null ? null : selectedDataSource.getId(); // or 0 if not found - Long fileCount = zeroIfNull(DataSourceInfoUtilities.getCountsOfFiles().get(dataSourceId)); - Long unallocatedFiles = zeroIfNull(DataSourceInfoUtilities.getCountsOfUnallocatedFiles().get(dataSourceId)); + Long fileCount = zeroIfNull(DataSourceInfoUtilities.getCountOfFiles(selectedDataSource)); + Long unallocatedFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfUnallocatedFiles(selectedDataSource)); Long allocatedFiles = zeroIfNull(getAllocatedCount(fileCount, unallocatedFiles)); - Long slackFiles = zeroIfNull(DataSourceInfoUtilities.getCountsOfSlackFiles().get(dataSourceId)); - Long directories = zeroIfNull(DataSourceInfoUtilities.getCountsOfDirectories().get(dataSourceId)); + Long slackFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfSlackFiles(selectedDataSource)); + Long directories = zeroIfNull(DataSourceInfoUtilities.getCountOfDirectories(selectedDataSource)); return new Object[][]{ new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount}, From d8f5bcec3a5177a0aaa796316e150e05d3e711fc Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 27 Jul 2020 12:12:29 -0400 Subject: [PATCH 08/19] commenting and sql results per data source --- .../DataSourceSummaryTabbedPane.java | 5 +- .../DataSourceInfoUtilities.java | 489 ++++++++++-------- .../DataSourceSummaryCountsPanel.java | 28 +- .../DataSourceSummaryDetailsPanel.java | 7 +- 4 files changed, 312 insertions(+), 217 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java index 5fbcdeca38..d435b5e135 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java @@ -46,6 +46,9 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { setTabs(); } + /** + * Set tabs to the details panel, counts panel, and ingest history panel. + */ private void setTabs() { this.removeAll(); addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); @@ -72,7 +75,7 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { countsPanel.setDataSource(dataSource); detailsPanel.setDataSource(dataSource); - + // make sure ingest history panel doesn't try to show a data source when null or case is closed ingestHistoryPanel.setDataSource( dataSource != null && Case.isCaseOpen() ? dataSource : null); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java index b884118f5f..cfa28d5c38 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.casemodule.datasourcesummary; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -43,6 +45,288 @@ final class DataSourceInfoUtilities { private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName()); + /** + * Gets a count of files for a particular datasource where it is not a + * virtual directory and has a name. + * + * @param currentDataSource The datasource. + * @param additionalWhere Additional sql where clauses. + * @param onError The message to log on error. + * + * @return The count of files or null on error. + */ + private static Long getCountOfFiles(DataSource currentDataSource, String additionalWhere, String onError) { + if (currentDataSource != null) { + try { + SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + return skCase.countFilesWhere( + "dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() + + " AND name<>''" + + " AND data_source_obj_id=" + currentDataSource.getId() + + " AND " + additionalWhere); + } catch (TskCoreException | NoCurrentCaseException ex) { + logger.log(Level.WARNING, onError, ex); + //unable to get count of files for the specified types cell will be displayed as empty + } + } + return null; + } + + /** + * Get count of files in a data source. + * + * @param currentDataSource The data source. + * + * @return The count. + */ + static Long getCountOfFiles(DataSource currentDataSource) { + return getCountOfFiles(currentDataSource, + "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(), + "Unable to get count of files, providing empty results"); + } + + /** + * Get count of unallocated files in a data source. + * + * @param currentDataSource The data source. + * + * @return The count. + */ + static Long getCountOfUnallocatedFiles(DataSource currentDataSource) { + return getCountOfFiles(currentDataSource, + "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue(), + "Unable to get counts of unallocated files for datasource, providing empty results"); + } + + /** + * Get count of directories in a data source. + * + * @param currentDataSource The data source. + * + * @return The count. + */ + static Long getCountOfDirectories(DataSource currentDataSource) { + return getCountOfFiles(currentDataSource, + "'type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + + " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue(), + "Unable to get count of directories for datasource, providing empty results"); + } + + /** + * Get count of slack files in a data source. + * + * @param currentDataSource The data source. + * + * @return The count. + */ + static Long getCountOfSlackFiles(DataSource currentDataSource) { + return getCountOfFiles(currentDataSource, + "type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(), + "Unable to get count of slack files for datasources, providing empty results"); + } + + /** + * An interface for handling a result set and returning a value. + */ + private interface ResultSetHandler { + + T process(ResultSet resultset) throws SQLException; + } + + /** + * Retrieves a result based on the provided query. + * + * @param query The query. + * @param processor The result set handler. + * @param errorMessage The error message to display if there is an error + * retrieving the resultset. + * + * @return The ResultSetHandler value or null if no ResultSet could be + * obtained. + */ + private static T getBaseQueryResult(String query, ResultSetHandler processor, String errorMessage) { + try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) { + ResultSet resultSet = dbQuery.getResultSet(); + try { + return processor.process(resultSet); + } catch (SQLException ex) { + logger.log(Level.WARNING, errorMessage, ex); + } + } catch (TskCoreException | NoCurrentCaseException ex) { + logger.log(Level.WARNING, errorMessage, ex); + } + return null; + } + + /** + * Gets the size of unallocated files in a particular datasource. + * + * @param currentDataSource The data source. + * + * @return The size or null if the query could not be executed. + */ + static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) { + if (currentDataSource == null) { + return null; + } + + final String valueParam = "value"; + String query = "SELECT SUM(size) AS " + valueParam + + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() + + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() + + " AND name<>''" + + " AND data_source_obj_id=" + currentDataSource.getId(); + + ResultSetHandler handler = (resultSet) -> resultSet.getLong(valueParam); + String errorMessage = "Unable to get size of unallocated files; returning null."; + + return getBaseQueryResult(query, handler, errorMessage); + } + + /** + * Retrieves counts for each artifact type in a data source. + * + * @param selectedDataSource The data source. + * + * @return A mapping of artifact type name to the counts or null if there + * was an error executing the query. + */ + static Map getCountsOfArtifactsByType(DataSource selectedDataSource) { + if (selectedDataSource == null) { + return Collections.emptyMap(); + } + + final String nameParam = "name"; + final String valueParam = "value"; + String query + = "SELECT bbt.display_name AS " + nameParam + ", COUNT(*) AS " + valueParam + + " FROM blackboard_artifacts bba " + + " INNER JOIN blackboard_artifact_types bbt ON bba.artifact_type_id = bbt.artifact_type_id" + + " WHERE bba.data_source_obj_id =" + selectedDataSource.getId() + + " GROUP BY bbt.display_name"; + + ResultSetHandler> handler = (resultSet) -> { + Map toRet = new HashMap<>(); + while (resultSet.next()) { + try { + toRet.put(resultSet.getString(nameParam), resultSet.getLong(valueParam)); + } catch (SQLException ex) { + logger.log(Level.WARNING, "Failed to get a result pair from the result set.", ex); + } + } + + return toRet; + }; + + String errorMessage = "Unable to get artifact type counts; returning null."; + + return getBaseQueryResult(query, handler, errorMessage); + } + + /** + * Generates a string which is a concatenation of the value received from + * the result set. + * + * @param query The query. + * @param valueParam The parameter for the value in the result set. + * @param separator The string separator used in concatenation. + * @param errorMessage The error message if the result set could not + * be received. + * @param singleErrorMessage The error message if a single result could not + * be obtained. + * + * @return The concatenated string or null if the query could not be + * executed. + */ + private static String getConcattedStringQuery(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) { + ResultSetHandler handler = (resultSet) -> { + String toRet = ""; + boolean first = true; + while (resultSet.next()) { + try { + if (first) { + first = false; + } else { + toRet += separator; + } + toRet += resultSet.getString(valueParam); + } catch (SQLException ex) { + logger.log(Level.WARNING, singleErrorMessage, ex); + } + } + + return toRet; + }; + + return getBaseQueryResult(query, handler, errorMessage); + } + + /** + * Generates a concatenated string value based on the text value of a + * particular attribute in a particular artifact for a specific data source. + * + * @param dataSourceId The data source id. + * @param artifactTypeId The artifact type id. + * @param attributeTypeId The attribute type id. + * + * @return The concatenated value or null if the query could not be + * executed. + */ + private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) { + final String valueParam = "concatted_attribute_value"; + String query = "SELECT attr.value_text AS " + valueParam + + " FROM blackboard_artifacts bba " + + " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id " + + " WHERE bba.data_source_obj_id = " + dataSourceId + + " AND bba.artifact_type_id = " + artifactTypeId + + " AND attr.attribute_type_id = " + attributeTypeId; + + String errorMessage = "Unable to execute query to retrieve concatted attribute values."; + String singleErrorMessage = "There was an error retrieving one of the results. That result will be omitted from concatted value."; + String separator = ", "; + return getConcattedStringQuery(query, valueParam, separator, errorMessage, singleErrorMessage); + } + + /** + * Retrieves the concatenation of operating system attributes for a + * particular data source. + * + * @param dataSource The data source. + * + * @return The concatenated value or null if the query could not be + * executed. + */ + static String getOperatingSystems(DataSource dataSource) { + if (dataSource == null) { + return null; + } + + return getConcattedAttrValue(dataSource.getId(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()); + } + + /** + * Retrieves the concatenation of data source usage for a particular data + * source. + * + * @param dataSource The data source. + * + * @return The concatenated value or null if the query could not be + * executed. + */ + static String getDataSourceType(DataSource dataSource) { + if (dataSource == null) { + return null; + } + + return getConcattedAttrValue(dataSource.getId(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID()); + } + /** * Get a map containing the TSK_DATA_SOURCE_USAGE description attributes * associated with each data source in the current case. @@ -97,51 +381,6 @@ final class DataSourceInfoUtilities { } } - private static Long baseCountOfFiles(DataSource currentDataSource, String additionalWhere, String onError) { - if (currentDataSource != null) { - try { - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - return skCase.countFilesWhere( - "COUNT(*) AS value" - + " FROM tsk_files" - + " WHERE dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() - + " AND name<>''" - + " AND data_source_obj_id=" + currentDataSource.getId() - + " AND " + additionalWhere); - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.WARNING, onError, ex); - //unable to get count of files for the specified mimetypes cell will be displayed as empty - } - } - return null; - } - - static Long getCountOfFiles(DataSource currentDataSource) { - return baseCountOfFiles(currentDataSource, - "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(), - "Unable to get count of files, providing empty results"); - } - - static Long getCountOfUnallocatedFiles(DataSource currentDataSource) { - return baseCountOfFiles(currentDataSource, - "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() - + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue(), - "Unable to get counts of unallocated files for datasource, providing empty results"); - } - - static Long getCountOfDirectories(DataSource currentDataSource) { - return baseCountOfFiles(currentDataSource, - "'type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() - + " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue(), - "Unable to get count of directories for datasource, providing empty results"); - } - - static Long getCountOfSlackFiles(DataSource currentDataSource) { - return baseCountOfFiles(currentDataSource, - "type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(), - "Unable to get count of slack files for datasources, providing empty results"); - } - /** * Get a map containing the number of artifacts in each data source in the * current case. @@ -192,39 +431,6 @@ final class DataSourceInfoUtilities { } } - /** - * Get a map containing the names of operating systems joined in a comma - * seperated list to the Data Source they exist on in the current case. No - * item will exist in the map for data sources which do not contain - * TS_OS_INFO artifacts which have a program name. - * - * @return Collection which maps datasource id to a String which is a comma - * seperated list of Operating system names found on the data - * source. - */ - static Map getOperatingSystems() { - Map osDetailMap = new HashMap<>(); - try { - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - ArrayList osInfoArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO); - for (BlackboardArtifact osInfo : osInfoArtifacts) { - BlackboardAttribute programName = osInfo.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME)); - if (programName != null) { - String currentOsString = osDetailMap.get(osInfo.getDataSource().getId()); - if (currentOsString == null || currentOsString.isEmpty()) { - currentOsString = programName.getValueString(); - } else { - currentOsString = currentOsString + ", " + programName.getValueString(); - } - osDetailMap.put(osInfo.getDataSource().getId(), currentOsString); - } - } - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Failed to load OS info artifacts.", ex); - } - return osDetailMap; - } - /** * Get the number of files in the case database for the current data source * which have the specified mimetypes. @@ -257,133 +463,6 @@ final class DataSourceInfoUtilities { return null; } - /** - * Get a map containing the number of unallocated files in each data source - * in the current case. - * - * @return Collection which maps datasource id to a count for the number of - * unallocated files in the datasource, will only contain entries - * for datasources which have at least 1 unallocated file - */ - static Map getCountsOfUnallocatedFiles() { - try { - final String countUnallocatedFilesQuery = "data_source_obj_id, COUNT(*) AS value" - + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() - + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() - + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() - + " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS - return getValuesMap(countUnallocatedFilesQuery); - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to get counts of unallocated files for all datasources, providing empty results", ex); - return Collections.emptyMap(); - } - } - - /** - * Get a map containing the total size of unallocated files in each data - * source in the current case. - * - * @return Collection which maps datasource id to a total size in bytes of - * unallocated files in the datasource, will only contain entries - * for datasources which have at least 1 unallocated file - */ - static Map getSizeOfUnallocatedFiles() { - try { - final String countUnallocatedFilesQuery = "data_source_obj_id, sum(size) AS value" - + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() - + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() - + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() - + " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS - return getValuesMap(countUnallocatedFilesQuery); - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to get size of unallocated files for all datasources, providing empty results", ex); - return Collections.emptyMap(); - } - } - - /** - * Get a map containing the number of directories in each data source in the - * current case. - * - * @return Collection which maps datasource id to a count for the number of - * directories in the datasource, will only contain entries for - * datasources which have at least 1 directory - */ - static Map getCountsOfDirectories() { - try { - final String countDirectoriesQuery = "data_source_obj_id, COUNT(*) AS value" - + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() - + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() - + " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue() - + " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS - return getValuesMap(countDirectoriesQuery); - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to get counts of directories for all datasources, providing empty results", ex); - return Collections.emptyMap(); - } - } - - /** - * Get a map containing the number of slack files in each data source in the - * current case. - * - * @return Collection which maps datasource id to a count for the number of - * slack files in the datasource, will only contain entries for - * datasources which have at least 1 slack file - */ - static Map getCountsOfSlackFiles() { - try { - final String countSlackFilesQuery = "data_source_obj_id, COUNT(*) AS value" - + " FROM tsk_files WHERE type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() - + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() - + " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS - return getValuesMap(countSlackFilesQuery); - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to get counts of slack files for all datasources, providing empty results", ex); - return Collections.emptyMap(); - } - } - - /** - * Get a map containing maps which map artifact type to the number of times - * it exosts in each data source in the current case. - * - * @return Collection which maps datasource id to maps of artifact display - * name to number of occurences in the datasource, will only contain - * entries for artifacts which have at least one occurence in the - * data source. - */ - static Map> getCountsOfArtifactsByType() { - try { - final String countArtifactsQuery = "blackboard_artifacts.data_source_obj_id, blackboard_artifact_types.display_name AS label, COUNT(*) AS value" - + " FROM blackboard_artifacts, blackboard_artifact_types" - + " WHERE blackboard_artifacts.artifact_type_id = blackboard_artifact_types.artifact_type_id" - + " GROUP BY blackboard_artifacts.data_source_obj_id, blackboard_artifact_types.display_name"; - return getLabeledValuesMap(countArtifactsQuery); - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to get counts of all artifact types for all datasources, providing empty results", ex); - return Collections.emptyMap(); - } - } - - /** - * Helper method to execute a select query with a - * DataSourceLabeledValueCallback. - * - * @param query the portion of the query which should follow the SELECT - * - * @return a map of datasource object IDs to maps of String labels to the - * values associated with them. - * - * @throws TskCoreException - * @throws NoCurrentCaseException - */ - private static Map> getLabeledValuesMap(String query) throws TskCoreException, NoCurrentCaseException { - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - DataSourceLabeledValueCallback callback = new DataSourceLabeledValueCallback(); - skCase.getCaseDbAccessManager().select(query, callback); - return callback.getMapOfLabeledValues(); - } /** * Helper method to execute a select query with a diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java index 0df73ce93f..44a108d0aa 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java @@ -41,18 +41,22 @@ import org.sleuthkit.datamodel.DataSource; }) class DataSourceSummaryCountsPanel extends javax.swing.JPanel { + // Result returned for a data model if no data found. private static final Object[][] EMPTY_PAIRS = new Object[][]{}; + // column headers for mime type table private static final Object[] MIME_TYPE_COLUMN_HEADERS = new Object[]{ Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_type_header(), Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_count_header() }; + // column headers for file by category table private static final Object[] FILE_BY_CATEGORY_COLUMN_HEADERS = new Object[]{ Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_type_header(), Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_count_header() }; + // column headers for artifact counts table private static final Object[] ARTIFACT_COUNTS_COLUMN_HEADERS = new Object[]{ Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_type_header(), Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header() @@ -128,7 +132,9 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { /** * Determines the JTable data model for datasource mime types. + * * @param dataSource The DataSource. + * * @return The model to be used with a JTable. */ @Messages({ @@ -154,9 +160,12 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { } /** - * Retrieves the counts of files of a particular mime type for a particular DataSource. + * Retrieves the counts of files of a particular mime type for a particular + * DataSource. + * * @param dataSource The DataSource. - * @param category The mime type category. + * @param category The mime type category. + * * @return The count. */ private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) { @@ -165,7 +174,9 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { /** * Determines the JTable data model for datasource file categories. + * * @param dataSource The DataSource. + * * @return The model to be used with a JTable. */ @Messages({ @@ -176,8 +187,6 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { "DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory" }) private static Object[][] getFileCategoryModel(DataSource selectedDataSource) { - Long dataSourceId = selectedDataSource == null ? null : selectedDataSource.getId(); - // or 0 if not found Long fileCount = zeroIfNull(DataSourceInfoUtilities.getCountOfFiles(selectedDataSource)); Long unallocatedFiles = zeroIfNull(DataSourceInfoUtilities.getCountOfUnallocatedFiles(selectedDataSource)); Long allocatedFiles = zeroIfNull(getAllocatedCount(fileCount, unallocatedFiles)); @@ -195,7 +204,9 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { /** * Returns 0 if value is null. + * * @param origValue The original value. + * * @return The value or 0 if null. */ private static Long zeroIfNull(Long origValue) { @@ -204,8 +215,10 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { /** * Safely gets the allocated files count. - * @param allFilesCount The count of all files. + * + * @param allFilesCount The count of all files. * @param unallocatedFilesCount The count of unallocated files. + * * @return The count of allocated files. */ private static long getAllocatedCount(Long allFilesCount, Long unallocatedFilesCount) { @@ -220,12 +233,13 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { /** * The counts of different artifact types found in a DataSource. + * * @param selectedDataSource The DataSource. + * * @return The JTable data model of counts of artifact types. */ private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) { - Long dataSourceId = selectedDataSource == null ? null : selectedDataSource.getId(); - Map artifactMapping = DataSourceInfoUtilities.getCountsOfArtifactsByType().get(dataSourceId); + Map artifactMapping = DataSourceInfoUtilities.getCountsOfArtifactsByType(selectedDataSource); if (artifactMapping == null) { return EMPTY_PAIRS; } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java index 7409c2eda3..21caa2c4b8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDetailsPanel.java @@ -72,11 +72,10 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel { if (dataSource == null || !Case.isCaseOpen()) { updateDetailsPanelData(null, null, null, null); } else { - long id = dataSource.getId(); updateDetailsPanelData(dataSource, - DataSourceInfoUtilities.getSizeOfUnallocatedFiles().get(id), - DataSourceInfoUtilities.getOperatingSystems().get(id), - DataSourceInfoUtilities.getDataSourceTypes().get(id)); + DataSourceInfoUtilities.getSizeOfUnallocatedFiles(dataSource), + DataSourceInfoUtilities.getOperatingSystems(dataSource), + DataSourceInfoUtilities.getDataSourceType(dataSource)); } } From 4e7ee4142d3c9a98012e174f9ae92d6e9cb89856 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 27 Jul 2020 14:31:12 -0400 Subject: [PATCH 09/19] bug fixes --- .../DataSourceInfoUtilities.java | 16 ++++++++++++---- .../summary/DataSourceSummaryResultViewer.java | 5 ----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java index cfa28d5c38..662f3739f0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java @@ -108,7 +108,7 @@ final class DataSourceInfoUtilities { */ static Long getCountOfDirectories(DataSource currentDataSource) { return getCountOfFiles(currentDataSource, - "'type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + "type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue(), "Unable to get count of directories for datasource, providing empty results"); } @@ -172,14 +172,23 @@ final class DataSourceInfoUtilities { } final String valueParam = "value"; - String query = "SELECT SUM(size) AS " + valueParam + final String countParam = "count"; + String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam + " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType() + " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue() + " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() + " AND name<>''" + " AND data_source_obj_id=" + currentDataSource.getId(); - ResultSetHandler handler = (resultSet) -> resultSet.getLong(valueParam); + ResultSetHandler handler = (resultSet) -> { + if (resultSet.next()) { + // ensure that there is an unallocated count result that is attached to this data source + long resultCount = resultSet.getLong(valueParam); + return (resultCount > 0) ? resultSet.getLong(valueParam) : null; + } else { + return null; + } + }; String errorMessage = "Unable to get size of unallocated files; returning null."; return getBaseQueryResult(query, handler, errorMessage); @@ -463,7 +472,6 @@ final class DataSourceInfoUtilities { return null; } - /** * Helper method to execute a select query with a * DataSourceSingleValueCallback. diff --git a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java index c3ca3ca2a2..1b1b3cb127 100644 --- a/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/resultviewers/summary/DataSourceSummaryResultViewer.java @@ -114,11 +114,6 @@ public class DataSourceSummaryResultViewer extends AbstractDataResultViewer { DataSource dataSource = getDataSource(node); - if (dataSource == null) { - LOGGER.log(Level.SEVERE, "No datasource for node found."); - return; - } - this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { summaryPanel.setDataSource(dataSource); From 1b5f43fa2b300e658bac0037eb74637da2ce1b3f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 27 Jul 2020 14:37:03 -0400 Subject: [PATCH 10/19] removing files to fix directory issue --- .../Bundle.properties-MERGED | 75 ----------------- .../DataSourceSummaryTabbedPane.java | 83 ------------------- 2 files changed, 158 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED delete mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED deleted file mode 100755 index eb7affe9ee..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED +++ /dev/null @@ -1,75 +0,0 @@ -CTL_DataSourceSummaryAction=Data Source Summary -DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count -DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type -DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All -DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated -DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count -DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory -DataSourceSummaryCountsPanel.FilesByCategoryTableModel.slack.row=Slack -DataSourceSummaryCountsPanel.FilesByCategoryTableModel.type.header=File Type -DataSourceSummaryCountsPanel.FilesByCategoryTableModel.unallocated.row=Unallocated -DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio -DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.count.header=Count -DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents -DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables -DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images -DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type -DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos -DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case. -DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure -DataSourceSummaryDetailsPanel.units.bytes=\ bytes -DataSourceSummaryDetailsPanel.units.gigabytes=\ GB -DataSourceSummaryDetailsPanel.units.kilobytes=\ kB -DataSourceSummaryDetailsPanel.units.megabytes=\ MB -DataSourceSummaryDetailsPanel.units.petabytes=\ PB -DataSourceSummaryDetailsPanel.units.terabytes=\ TB -DataSourceSummaryDialog.closeButton.text=Close -DataSourceSummaryDetailsPanel.displayNameLabel.text=Display Name: -DataSourceSummaryDetailsPanel.originalNameLabel.text=Name: -DataSourceSummaryDetailsPanel.deviceIdLabel.text=Device ID: -DataSourceSummaryDetailsPanel.operatingSystemLabel.text=OS: -DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text=Usage: -DataSourceSummaryDetailsPanel.timeZoneLabel.text=Time Zone: -DataSourceSummaryDetailsPanel.imageTypeLabel.text=Image Type: -DataSourceSummaryDetailsPanel.sizeLabel.text=Size: -DataSourceSummaryDetailsPanel.sectorSizeLabel.text=Sector Size: -DataSourceSummaryDetailsPanel.md5HashLabel.text=MD5: -DataSourceSummaryDetailsPanel.sha1HashLabel.text=SHA1: -DataSourceSummaryDetailsPanel.sha256HashLabel.text=SHA256: -DataSourceSummaryDetailsPanel.filePathsLabel.text=File Paths: -DataSourceSummaryDetailsPanel.displayNameValue.text= -DataSourceSummaryDetailsPanel.originalNameValue.text= -DataSourceSummaryDetailsPanel.deviceIdValue.toolTipText= -DataSourceSummaryDetailsPanel.deviceIdValue.text= -DataSourceSummaryDetailsPanel.dataSourceUsageValue.text= -DataSourceSummaryDetailsPanel.operatingSystemValue.toolTipText= -DataSourceSummaryDetailsPanel.operatingSystemValue.text= -DataSourceSummaryDetailsPanel.timeZoneValue.text= -DataSourceSummaryDetailsPanel.imageTypeValue.toolTipText= -DataSourceSummaryDetailsPanel.imageTypeValue.text= -DataSourceSummaryDetailsPanel.sizeValue.text= -DataSourceSummaryDetailsPanel.sectorSizeValue.text= -DataSourceSummaryDetailsPanel.md5HashValue.toolTipText= -DataSourceSummaryDetailsPanel.md5HashValue.text= -DataSourceSummaryDetailsPanel.sha1HashValue.text= -DataSourceSummaryDetailsPanel.sha256HashValue.text= -DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0= -DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text= -DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details: -DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space: -DataSourceSummaryDetailsPanel.unallocatedSizeValue.text= -DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type -DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category -DataSourceSummaryCountsPanel.jLabel1.text=Results by Type -DataSourceSummaryDialog.countsTab.title=Counts -DataSourceSummaryDialog.detailsTab.title=Details -DataSourceSummaryDialog.ingestHistoryTab.title=Ingest History -DataSourceSummaryDialog.window.title=Data Sources Summary -DataSourceSummaryNode.column.dataSourceName.header=Data Source Name -DataSourceSummaryNode.column.files.header=Files -DataSourceSummaryNode.column.results.header=Results -DataSourceSummaryNode.column.status.header=Ingest Status -DataSourceSummaryNode.column.tags.header=Tags -DataSourceSummaryNode.column.type.header=Type -DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source -ViewSummaryInformationAction.name.text=View Summary Information diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java deleted file mode 100644 index d435b5e135..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.casemodule.datasourcesummary; - -import javax.swing.JTabbedPane; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; -import org.sleuthkit.datamodel.DataSource; - -/** - * A tabbed pane showing the summary of a data source including tabs of: - * DataSourceSummaryCountsPanel, DataSourceSummaryDetailsPanel, and - * IngestJobInfoPanel. - */ -public class DataSourceSummaryTabbedPane extends JTabbedPane { - - private final DataSourceSummaryCountsPanel countsPanel; - private final DataSourceSummaryDetailsPanel detailsPanel; - private final IngestJobInfoPanel ingestHistoryPanel; - - private DataSource dataSource = null; - - /** - * Constructs a tabbed pane showing the summary of a data source. - */ - public DataSourceSummaryTabbedPane() { - countsPanel = new DataSourceSummaryCountsPanel(); - detailsPanel = new DataSourceSummaryDetailsPanel(); - ingestHistoryPanel = new IngestJobInfoPanel(); - setTabs(); - } - - /** - * Set tabs to the details panel, counts panel, and ingest history panel. - */ - private void setTabs() { - this.removeAll(); - addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); - addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); - addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); - } - - /** - * The datasource currently used as the model in this panel. - * - * @return The datasource currently being used as the model in this panel. - */ - public DataSource getDataSource() { - return dataSource; - } - - /** - * Sets datasource to visualize in the tabbed panel. - * - * @param dataSource The datasource to use in this panel. - */ - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - - countsPanel.setDataSource(dataSource); - detailsPanel.setDataSource(dataSource); - - // make sure ingest history panel doesn't try to show a data source when null or case is closed - ingestHistoryPanel.setDataSource( - dataSource != null && Case.isCaseOpen() ? dataSource : null); - } -} From 8f967cb2384f56076f62551bab2d75b0569ea08d Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 27 Jul 2020 14:37:49 -0400 Subject: [PATCH 11/19] re-adding files to fix directory issue --- .../Bundle.properties-MERGED | 75 +++++++++++++++++ .../DataSourceSummaryTabbedPane.java | 83 +++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED new file mode 100644 index 0000000000..eb7affe9ee --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED @@ -0,0 +1,75 @@ +CTL_DataSourceSummaryAction=Data Source Summary +DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count +DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type +DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All +DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated +DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count +DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory +DataSourceSummaryCountsPanel.FilesByCategoryTableModel.slack.row=Slack +DataSourceSummaryCountsPanel.FilesByCategoryTableModel.type.header=File Type +DataSourceSummaryCountsPanel.FilesByCategoryTableModel.unallocated.row=Unallocated +DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio +DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.count.header=Count +DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents +DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables +DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images +DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type +DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos +DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case. +DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure +DataSourceSummaryDetailsPanel.units.bytes=\ bytes +DataSourceSummaryDetailsPanel.units.gigabytes=\ GB +DataSourceSummaryDetailsPanel.units.kilobytes=\ kB +DataSourceSummaryDetailsPanel.units.megabytes=\ MB +DataSourceSummaryDetailsPanel.units.petabytes=\ PB +DataSourceSummaryDetailsPanel.units.terabytes=\ TB +DataSourceSummaryDialog.closeButton.text=Close +DataSourceSummaryDetailsPanel.displayNameLabel.text=Display Name: +DataSourceSummaryDetailsPanel.originalNameLabel.text=Name: +DataSourceSummaryDetailsPanel.deviceIdLabel.text=Device ID: +DataSourceSummaryDetailsPanel.operatingSystemLabel.text=OS: +DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text=Usage: +DataSourceSummaryDetailsPanel.timeZoneLabel.text=Time Zone: +DataSourceSummaryDetailsPanel.imageTypeLabel.text=Image Type: +DataSourceSummaryDetailsPanel.sizeLabel.text=Size: +DataSourceSummaryDetailsPanel.sectorSizeLabel.text=Sector Size: +DataSourceSummaryDetailsPanel.md5HashLabel.text=MD5: +DataSourceSummaryDetailsPanel.sha1HashLabel.text=SHA1: +DataSourceSummaryDetailsPanel.sha256HashLabel.text=SHA256: +DataSourceSummaryDetailsPanel.filePathsLabel.text=File Paths: +DataSourceSummaryDetailsPanel.displayNameValue.text= +DataSourceSummaryDetailsPanel.originalNameValue.text= +DataSourceSummaryDetailsPanel.deviceIdValue.toolTipText= +DataSourceSummaryDetailsPanel.deviceIdValue.text= +DataSourceSummaryDetailsPanel.dataSourceUsageValue.text= +DataSourceSummaryDetailsPanel.operatingSystemValue.toolTipText= +DataSourceSummaryDetailsPanel.operatingSystemValue.text= +DataSourceSummaryDetailsPanel.timeZoneValue.text= +DataSourceSummaryDetailsPanel.imageTypeValue.toolTipText= +DataSourceSummaryDetailsPanel.imageTypeValue.text= +DataSourceSummaryDetailsPanel.sizeValue.text= +DataSourceSummaryDetailsPanel.sectorSizeValue.text= +DataSourceSummaryDetailsPanel.md5HashValue.toolTipText= +DataSourceSummaryDetailsPanel.md5HashValue.text= +DataSourceSummaryDetailsPanel.sha1HashValue.text= +DataSourceSummaryDetailsPanel.sha256HashValue.text= +DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0= +DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text= +DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details: +DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space: +DataSourceSummaryDetailsPanel.unallocatedSizeValue.text= +DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type +DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category +DataSourceSummaryCountsPanel.jLabel1.text=Results by Type +DataSourceSummaryDialog.countsTab.title=Counts +DataSourceSummaryDialog.detailsTab.title=Details +DataSourceSummaryDialog.ingestHistoryTab.title=Ingest History +DataSourceSummaryDialog.window.title=Data Sources Summary +DataSourceSummaryNode.column.dataSourceName.header=Data Source Name +DataSourceSummaryNode.column.files.header=Files +DataSourceSummaryNode.column.results.header=Results +DataSourceSummaryNode.column.status.header=Ingest Status +DataSourceSummaryNode.column.tags.header=Tags +DataSourceSummaryNode.column.type.header=Type +DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source +ViewSummaryInformationAction.name.text=View Summary Information diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java new file mode 100644 index 0000000000..d435b5e135 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java @@ -0,0 +1,83 @@ +/* + * 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.casemodule.datasourcesummary; + +import javax.swing.JTabbedPane; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; +import org.sleuthkit.datamodel.DataSource; + +/** + * A tabbed pane showing the summary of a data source including tabs of: + * DataSourceSummaryCountsPanel, DataSourceSummaryDetailsPanel, and + * IngestJobInfoPanel. + */ +public class DataSourceSummaryTabbedPane extends JTabbedPane { + + private final DataSourceSummaryCountsPanel countsPanel; + private final DataSourceSummaryDetailsPanel detailsPanel; + private final IngestJobInfoPanel ingestHistoryPanel; + + private DataSource dataSource = null; + + /** + * Constructs a tabbed pane showing the summary of a data source. + */ + public DataSourceSummaryTabbedPane() { + countsPanel = new DataSourceSummaryCountsPanel(); + detailsPanel = new DataSourceSummaryDetailsPanel(); + ingestHistoryPanel = new IngestJobInfoPanel(); + setTabs(); + } + + /** + * Set tabs to the details panel, counts panel, and ingest history panel. + */ + private void setTabs() { + this.removeAll(); + addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); + addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); + addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); + } + + /** + * The datasource currently used as the model in this panel. + * + * @return The datasource currently being used as the model in this panel. + */ + public DataSource getDataSource() { + return dataSource; + } + + /** + * Sets datasource to visualize in the tabbed panel. + * + * @param dataSource The datasource to use in this panel. + */ + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + + countsPanel.setDataSource(dataSource); + detailsPanel.setDataSource(dataSource); + + // make sure ingest history panel doesn't try to show a data source when null or case is closed + ingestHistoryPanel.setDataSource( + dataSource != null && Case.isCaseOpen() ? dataSource : null); + } +} From b248596598b848c7c9e0079f5bfafe97afc1e85f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 27 Jul 2020 14:42:55 -0400 Subject: [PATCH 12/19] directory fix --- .../Bundle.properties-MERGED | 0 .../{datasourceSummary => datasourcesummary}/Bundle_ja.properties | 0 .../DataSourceSummaryTabbedPane.java | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Core/src/org/sleuthkit/autopsy/casemodule/{datasourceSummary => datasourcesummary}/Bundle.properties-MERGED (100%) rename Core/src/org/sleuthkit/autopsy/casemodule/{datasourceSummary => datasourcesummary}/Bundle_ja.properties (100%) rename Core/src/org/sleuthkit/autopsy/casemodule/{datasourceSummary => datasourcesummary}/DataSourceSummaryTabbedPane.java (100%) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED similarity index 100% rename from Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties-MERGED diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle_ja.properties similarity index 100% rename from Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle_ja.properties rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle_ja.properties diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java similarity index 100% rename from Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/DataSourceSummaryTabbedPane.java rename to Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java From 3c096cdb2d8143ee22353cd4cd03cf8d626f172e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 27 Jul 2020 16:05:53 -0400 Subject: [PATCH 13/19] addressing codacy remarks and bug fix --- .../DataSourceSummaryTabbedPane.java | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java index d435b5e135..8ef4d62c5d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java @@ -30,9 +30,13 @@ import org.sleuthkit.datamodel.DataSource; */ public class DataSourceSummaryTabbedPane extends JTabbedPane { + private static final long serialVersionUID = 1L; private final DataSourceSummaryCountsPanel countsPanel; private final DataSourceSummaryDetailsPanel detailsPanel; - private final IngestJobInfoPanel ingestHistoryPanel; + + // ingest panel requires an open case in order to properly initialize. + // So it will be instantiated when a data source is selected. + private IngestJobInfoPanel ingestHistoryPanel = null; private DataSource dataSource = null; @@ -42,18 +46,30 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { public DataSourceSummaryTabbedPane() { countsPanel = new DataSourceSummaryCountsPanel(); detailsPanel = new DataSourceSummaryDetailsPanel(); - ingestHistoryPanel = new IngestJobInfoPanel(); - setTabs(); } /** - * Set tabs to the details panel, counts panel, and ingest history panel. + * Set tabs to the details panel, counts panel, and ingest history panel. If + * no data source or case is closed, no tabs will be shwon. + * + * @param dataSource The data source to display. */ - private void setTabs() { + private void setTabs(DataSource dataSource) { this.removeAll(); - addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); - addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); - addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); + if (dataSource != null && Case.isCaseOpen()) { + addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); + detailsPanel.setDataSource(dataSource); + + addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); + countsPanel.setDataSource(dataSource); + + if (ingestHistoryPanel == null) { + ingestHistoryPanel = new IngestJobInfoPanel(); + } + + addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); + ingestHistoryPanel.setDataSource(dataSource); + } } /** @@ -72,12 +88,6 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { */ public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; - - countsPanel.setDataSource(dataSource); - detailsPanel.setDataSource(dataSource); - - // make sure ingest history panel doesn't try to show a data source when null or case is closed - ingestHistoryPanel.setDataSource( - dataSource != null && Case.isCaseOpen() ? dataSource : null); + setTabs(dataSource); } } From 34ee2bd5c146d7423868e27f63ac6f8deabe1dbd Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 30 Jul 2020 11:15:04 -0400 Subject: [PATCH 14/19] non editable table model --- .../DataSourceSummaryCountsPanel.java | 7 ++-- .../NonEditableTableModel.java | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java index 44a108d0aa..2a1190d30b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java @@ -22,7 +22,6 @@ import java.util.Map; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JLabel; import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.DefaultTableModel; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.FileTypeUtils; @@ -115,15 +114,15 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { * @param artifactDataModel The artifact type data model. */ private void updateCountsTableData(Object[][] mimeTypeDataModel, Object[][] fileCategoryDataModel, Object[][] artifactDataModel) { - fileCountsByMimeTypeTable.setModel(new DefaultTableModel(mimeTypeDataModel, MIME_TYPE_COLUMN_HEADERS)); + fileCountsByMimeTypeTable.setModel(new NonEditableTableModel(mimeTypeDataModel, MIME_TYPE_COLUMN_HEADERS)); fileCountsByMimeTypeTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); fileCountsByMimeTypeTable.getColumnModel().getColumn(0).setPreferredWidth(130); - fileCountsByCategoryTable.setModel(new DefaultTableModel(fileCategoryDataModel, FILE_BY_CATEGORY_COLUMN_HEADERS)); + fileCountsByCategoryTable.setModel(new NonEditableTableModel(fileCategoryDataModel, FILE_BY_CATEGORY_COLUMN_HEADERS)); fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130); - artifactCountsTable.setModel(new DefaultTableModel(artifactDataModel, ARTIFACT_COUNTS_COLUMN_HEADERS)); + artifactCountsTable.setModel(new NonEditableTableModel(artifactDataModel, ARTIFACT_COUNTS_COLUMN_HEADERS)); artifactCountsTable.getColumnModel().getColumn(0).setPreferredWidth(230); artifactCountsTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java new file mode 100644 index 0000000000..0550e8f778 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java @@ -0,0 +1,36 @@ +/* + * 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.casemodule.datasourcesummary; + +import javax.swing.table.DefaultTableModel; + +/** + * A Table model where cells are not editable. + */ +class NonEditableTableModel extends DefaultTableModel { + + NonEditableTableModel(Object[][] data, Object[] columnNames) { + super(data, columnNames); + } + + @Override + public boolean isCellEditable(int row, int column) { + return false; + } +} From 1bb530923df9cc4f9003556bc96216b6c7309795 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 30 Jul 2020 11:51:07 -0400 Subject: [PATCH 15/19] fix for artifact counts table --- .../datasourcesummary/DataSourceSummaryCountsPanel.form | 3 --- .../datasourcesummary/DataSourceSummaryCountsPanel.java | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form index b82bd6f3a8..9a82746da6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.form @@ -113,9 +113,6 @@ - - - diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java index 2a1190d30b..6bb6603c11 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryCountsPanel.java @@ -75,6 +75,7 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { initComponents(); fileCountsByMimeTypeTable.getTableHeader().setReorderingAllowed(false); fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false); + artifactCountsTable.getTableHeader().setReorderingAllowed(false); setDataSource(null); } @@ -279,7 +280,6 @@ class DataSourceSummaryCountsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.jLabel1.text")); // NOI18N - artifactCountsTable.setAutoCreateRowSorter(true); artifactCountsScrollPane.setViewportView(artifactCountsTable); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); From dcc134939ec1c65ccb7383c843577248d344ccb6 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 31 Jul 2020 16:26:20 -0400 Subject: [PATCH 16/19] tab updates and case updates in IngestJobInfoPanel --- .../casemodule/IngestJobInfoPanel.java | 26 ++++++++++++++++--- .../DataSourceSummaryTabbedPane.java | 15 +++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java index b1e6d83482..6381acd32d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java @@ -31,7 +31,9 @@ import javax.swing.JOptionPane; import javax.swing.event.ListSelectionEvent; import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle.Messages; +import static org.sleuthkit.autopsy.casemodule.Case.Events.CURRENT_CASE; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.IngestModuleInfo; @@ -47,6 +49,8 @@ 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 static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE); + private List ingestJobs; private final List ingestJobsForSelectedDataSource = new ArrayList<>(); private IngestJobTableModel ingestJobTableModel = new IngestJobTableModel(); @@ -79,6 +83,16 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { refresh(); } }); + + Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> { + if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) { + return; + } + + if (CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName())) { + refresh(); + } + }); } /** @@ -110,9 +124,15 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { */ private void refresh() { try { - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - this.ingestJobs = skCase.getIngestJobs(); - setDataSource(selectedDataSource); + if (Case.isCaseOpen()) { + SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + this.ingestJobs = skCase.getIngestJobs(); + setDataSource(selectedDataSource); + } else { + this.ingestJobs = new ArrayList<>(); + setDataSource(null); + } + } catch (TskCoreException | NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex); JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java index 8ef4d62c5d..6375bffd28 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java @@ -31,6 +31,8 @@ import org.sleuthkit.datamodel.DataSource; public class DataSourceSummaryTabbedPane extends JTabbedPane { private static final long serialVersionUID = 1L; + private static final int TAB_COUNT = 3; + private final DataSourceSummaryCountsPanel countsPanel; private final DataSourceSummaryDetailsPanel detailsPanel; @@ -55,20 +57,23 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { * @param dataSource The data source to display. */ private void setTabs(DataSource dataSource) { - this.removeAll(); if (dataSource != null && Case.isCaseOpen()) { - addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); detailsPanel.setDataSource(dataSource); - - addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); countsPanel.setDataSource(dataSource); if (ingestHistoryPanel == null) { ingestHistoryPanel = new IngestJobInfoPanel(); } - addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); ingestHistoryPanel.setDataSource(dataSource); + + // initialize tabs if they have not been initialized properly. + if (getTabCount() != TAB_COUNT) { + removeAll(); + addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); + addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); + addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); + } } } From ef1a5840dda79b12522362d20bb9cbbb8f0f7756 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 3 Aug 2020 08:49:58 -0400 Subject: [PATCH 17/19] fix for ingest job info panel and tabs --- .../DataSourceSummaryTabbedPane.java | 44 +++++-------------- .../relationships/Bundle.properties-MERGED | 2 +- .../autoingest/Bundle.properties-MERGED | 2 - .../netbeans/core/startup/Bundle.properties | 2 +- .../core/windows/view/ui/Bundle.properties | 2 +- 5 files changed, 13 insertions(+), 39 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java index 6375bffd28..e1d15a6b0d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryTabbedPane.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import javax.swing.JTabbedPane; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; import org.sleuthkit.datamodel.DataSource; @@ -31,14 +30,10 @@ import org.sleuthkit.datamodel.DataSource; public class DataSourceSummaryTabbedPane extends JTabbedPane { private static final long serialVersionUID = 1L; - private static final int TAB_COUNT = 3; private final DataSourceSummaryCountsPanel countsPanel; private final DataSourceSummaryDetailsPanel detailsPanel; - - // ingest panel requires an open case in order to properly initialize. - // So it will be instantiated when a data source is selected. - private IngestJobInfoPanel ingestHistoryPanel = null; + private final IngestJobInfoPanel ingestHistoryPanel; private DataSource dataSource = null; @@ -48,33 +43,11 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { public DataSourceSummaryTabbedPane() { countsPanel = new DataSourceSummaryCountsPanel(); detailsPanel = new DataSourceSummaryDetailsPanel(); - } - - /** - * Set tabs to the details panel, counts panel, and ingest history panel. If - * no data source or case is closed, no tabs will be shwon. - * - * @param dataSource The data source to display. - */ - private void setTabs(DataSource dataSource) { - if (dataSource != null && Case.isCaseOpen()) { - detailsPanel.setDataSource(dataSource); - countsPanel.setDataSource(dataSource); - - if (ingestHistoryPanel == null) { - ingestHistoryPanel = new IngestJobInfoPanel(); - } - - ingestHistoryPanel.setDataSource(dataSource); - - // initialize tabs if they have not been initialized properly. - if (getTabCount() != TAB_COUNT) { - removeAll(); - addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); - addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); - addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); - } - } + ingestHistoryPanel = new IngestJobInfoPanel(); + + addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel); + addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel); + addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel); } /** @@ -93,6 +66,9 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane { */ public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; - setTabs(dataSource); + + detailsPanel.setDataSource(dataSource); + countsPanel.setDataSource(dataSource); + ingestHistoryPanel.setDataSource(dataSource); } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED index 6778d8dc53..616408978d 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED @@ -73,5 +73,5 @@ SummaryViewer.referencesLabel.text=Communication References: SummaryViewer.referencesDataLabel.text= SummaryViewer.contactsLabel.text=Book Entries: SummaryViewer.accountCountry.text= -SummaryViewer.fileRefPane.border.title=File Referernce(s) in Current Case +SummaryViewer.fileRefPane.border.title=File References in Current Case SummaryViewer.selectAccountFileRefLabel.text= diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index 56a675e256..823399e0d0 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -205,7 +205,9 @@ DeleteCaseTask.progress.parsingManifest=Parsing manifest file {0}... DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}... DeleteCaseTask.progress.startMessage=Starting deletion... DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes +# {0} - item count DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=Znodes found: {0} +# {0} - item count DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=ZNODES FOUND: {0} DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service # {0} - node path diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index c2167700fd..35138509d8 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Mon, 03 Aug 2020 08:23:57 -0400 +#Wed, 08 Jul 2020 15:15:46 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 9d11d2bf7a..cf36e85b33 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Mon, 03 Aug 2020 08:23:57 -0400 +#Wed, 08 Jul 2020 15:15:46 -0400 CTL_MainWindow_Title=Autopsy 4.16.0 CTL_MainWindow_Title_No_Project=Autopsy 4.16.0 From 36145d9c409fe8e4b40f3814d4054a49fa7a82eb Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 3 Aug 2020 11:49:30 -0400 Subject: [PATCH 19/19] updated for review remarks --- .../datasourcesummary/DataSourceInfoUtilities.java | 5 ++--- .../casemodule/datasourcesummary/NonEditableTableModel.java | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java index 662f3739f0..dcbf9bb82d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceInfoUtilities.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Level; @@ -249,7 +248,7 @@ final class DataSourceInfoUtilities { * @return The concatenated string or null if the query could not be * executed. */ - private static String getConcattedStringQuery(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) { + private static String getConcattedStringsResult(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) { ResultSetHandler handler = (resultSet) -> { String toRet = ""; boolean first = true; @@ -295,7 +294,7 @@ final class DataSourceInfoUtilities { String errorMessage = "Unable to execute query to retrieve concatted attribute values."; String singleErrorMessage = "There was an error retrieving one of the results. That result will be omitted from concatted value."; String separator = ", "; - return getConcattedStringQuery(query, valueParam, separator, errorMessage, singleErrorMessage); + return getConcattedStringsResult(query, valueParam, separator, errorMessage, singleErrorMessage); } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java index 0550e8f778..8ed965e2ab 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/NonEditableTableModel.java @@ -24,7 +24,8 @@ import javax.swing.table.DefaultTableModel; * A Table model where cells are not editable. */ class NonEditableTableModel extends DefaultTableModel { - + private static final long serialVersionUID = 1L; + NonEditableTableModel(Object[][] data, Object[] columnNames) { super(data, columnNames); }