diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java index e8630b1a5d..eb10fd7c47 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java @@ -200,8 +200,6 @@ final class AddImageWizardSelectDspVisual extends JPanel { dspList.add(LocalDiskDSProcessor.getType()); dspList.add(LocalFilesDSProcessor.getType()); dspList.add(RawDSProcessor.getType()); - Foo foo = new Foo(); - dspList.add(foo.bar()); dspList.add(LogicalImagerDSProcessor.getType()); // now add any addtional DSPs that haven't already been added for (String dspType : datasourceProcessorsMap.keySet()) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 4a2d3986c1..3d6475fd6d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -105,6 +105,7 @@ IntervalErrorReport.TotalIssues=total issue(s) IntervalErrorReport.ErrorText=Database Connection Error CaseDetailsAction.window.title=Case Details CueBannerPanel.title.text=Open Recent Case +LogicalImagerDSProcessor.dsType.text=Autopsy Imager ImageDSProcessor.dsType.text=Disk Image or VM File ImageDSProcessor.allDesc.text=All Supported Types LocalDiskDSProcessor.dsType.text=Local Disk @@ -238,3 +239,18 @@ OpenMultiUserCasePanel.cancelButton.text=Cancel OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case... OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name +LogicalImagerPanel.jLabel1.text=Insert external drive +LogicalImagerPanel.scanButton.text=Scan +LogicalImagerPanel.jLabel6.text=Or, pick a folder +LogicalImagerPanel.browseButton.text=Browse +LogicalImagerPanel.topLabel.text=Import Autopsy Imager Results +LogicalImagerPanel.selectDriveLabel.text=Select Drive +LogicalImagerPanel.selectAcquisitionFromDriveLabel.text=Select acquisition from Drive +LogicalImagerPanel.imageTable.columnModel.title0=Hostname +LogicalImagerPanel.imageTable.columnModel.title1=Extracted Date +LogicalImagerPanel.messageLabel.text=Error/Status message +LogicalImagerPanel.messageLabel.clickScanOrBrowse=Click SCAN or BROWSE button to find images +LogicalImagerPanel.messageLabel.noExternalDriveFound=No external drive found +LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for sparse_image.vhd ... +LogicalImagerPanel.messageLabel.selectedImage=Selected image +LogicalImagerPanel.messageLabel.noImageSelected=No image selected \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index 64dfb6481a..716ac1937f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -167,6 +167,9 @@ LogicalEvidenceFilePanel.pathValidation.getOpenCase.Error=Warning: Exception whi LogicalEvidenceFilePanel.validatePanel.nonL01Error.text=Only files with the .l01 file extension are supported here. LogicalFilesDspPanel.subTypeComboBox.l01FileOption.text=Logical evidence file (L01) LogicalFilesDspPanel.subTypeComboBox.localFilesOption.text=Local files and folders +LogicalImagerDSProcessor.dataSourceType=Logical Imager +LogicalImagerPanel.moduleErr=Module Error +LogicalImagerPanel.moduleErr.msg=A module caused an error listening to LogicalImagerPanel updates. See log to determine which module. Some data could be incomplete.\n Menu/Case/OpenRecentCase=Open Recent Case CTL_CaseDeleteAction=Delete Case OpenIDE-Module-Name=Case @@ -272,6 +275,7 @@ IntervalErrorReport.TotalIssues=total issue(s) IntervalErrorReport.ErrorText=Database Connection Error CaseDetailsAction.window.title=Case Details CueBannerPanel.title.text=Open Recent Case +LogicalImagerDSProcessor.dsType.text=Autopsy Imager ImageDSProcessor.dsType.text=Disk Image or VM File ImageDSProcessor.allDesc.text=All Supported Types LocalDiskDSProcessor.dsType.text=Local Disk @@ -425,3 +429,18 @@ OpenMultiUserCasePanel.cancelButton.text=Cancel OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case... OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name +LogicalImagerPanel.jLabel1.text=Insert external drive +LogicalImagerPanel.scanButton.text=Scan +LogicalImagerPanel.jLabel6.text=Or, pick a folder +LogicalImagerPanel.browseButton.text=Browse +LogicalImagerPanel.topLabel.text=Import Autopsy Imager Results +LogicalImagerPanel.selectDriveLabel.text=Select Drive +LogicalImagerPanel.selectAcquisitionFromDriveLabel.text=Select acquisition from Drive +LogicalImagerPanel.imageTable.columnModel.title0=Hostname +LogicalImagerPanel.imageTable.columnModel.title1=Extracted Date +LogicalImagerPanel.messageLabel.text=Error/Status message +LogicalImagerPanel.messageLabel.clickScanOrBrowse=Click SCAN or BROWSE button to find images +LogicalImagerPanel.messageLabel.noExternalDriveFound=No external drive found +LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for sparse_image.vhd ... +LogicalImagerPanel.messageLabel.selectedImage=Selected image +LogicalImagerPanel.messageLabel.noImageSelected=No image selected diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties index d84c7fd96a..2b05d5cac8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties @@ -196,7 +196,3 @@ CaseDetailsPanel.lbDbName.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\uff1a CaseDetailsPanel.lbDbType.text=\u30b1\u30fc\u30b9\u30bf\u30a4\u30d7\uff1a CaseDetailsPanel.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a OpenMultiUserCasePanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb -LogicalImagerPanel.sectorSizeLabel.text=\u30a4\u30f3\u30d7\u30c3\u30c8\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a -LogicalImagerPanel.errorLabel.text=\u30a8\u30e9\u30fc\u30e9\u30d9\u30eb -LogicalImagerPanel.noFatOrphansCheckbox.text=FAT\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306e\u30aa\u30fc\u30d5\u30a1\u30f3\u30d5\u30a1\u30a4\u30eb\u306f\u7121\u8996 -LogicalImagerPanel.browseButton.text=\u95b2\u89a7 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Foo.java b/Core/src/org/sleuthkit/autopsy/casemodule/Foo.java deleted file mode 100644 index 066465e420..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Foo.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.casemodule; - -/** - * - * @author jkho - */ -public class Foo { - - public Foo() { - } - - public String bar() { - return "bar"; - } - - public static String getFoo() { - return "foo"; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java index 60e480c2bb..7ca0e8b1d5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,29 +19,46 @@ package org.sleuthkit.autopsy.casemodule; import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; +import java.util.UUID; import javax.swing.JPanel; import javax.swing.filechooser.FileFilter; -import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; +import org.openide.util.lookup.ServiceProviders; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** - * A LogicalImager data source processor that implements the DataSourceProcessor service + * A Raw data source processor that implements the DataSourceProcessor service * provider interface to allow integration with the add data source wizard. It * also provides a run method overload to allow it to be used independently of * the wizard. */ -@ServiceProvider(service = DataSourceProcessor.class) +@ServiceProviders(value={ + @ServiceProvider(service=DataSourceProcessor.class)} +) public class LogicalImagerDSProcessor implements DataSourceProcessor { private final LogicalImagerPanel configPanel; - private final static String DATA_SOURCE_TYPE = NbBundle.getMessage(LogicalImagerDSProcessor.class, "LogicalImagerDSProcessor.dsType.text"); + private static final GeneralFilter rawFilter = new GeneralFilter(GeneralFilter.RAW_IMAGE_EXTS, GeneralFilter.RAW_IMAGE_DESC); + private static final GeneralFilter encaseFilter = new GeneralFilter(GeneralFilter.ENCASE_IMAGE_EXTS, GeneralFilter.ENCASE_IMAGE_DESC); + private static final List filtersList = new ArrayList<>(); + static { + filtersList.add(rawFilter); + filtersList.add(encaseFilter); + } + + // By default, split image into 2GB unallocated space chunks + private static final long DEFAULT_CHUNK_SIZE = 2000000000L; // 2 GB + + private AddImageTask addImageTask; /* - * Constructs a Logical Imaager data source processor that implements the + * Constructs a Raw data source processor that implements the * DataSourceProcessor service provider interface to allow integration with * the add data source wizard. It also provides a run method overload to * allow it to be used independently of the wizard. @@ -57,8 +74,9 @@ public class LogicalImagerDSProcessor implements DataSourceProcessor { * * @return A data source type display string for this data source processor. */ + @Messages({"LogicalImagerDSProcessor.dataSourceType=Logical Imager"}) public static String getType() { - return DATA_SOURCE_TYPE; + return Bundle.LogicalImagerDSProcessor_dataSourceType(); } /** @@ -70,7 +88,7 @@ public class LogicalImagerDSProcessor implements DataSourceProcessor { */ @Override public String getDataSourceType() { - return getType(); + return Bundle.LogicalImagerDSProcessor_dataSourceType(); } /** @@ -117,11 +135,16 @@ public class LogicalImagerDSProcessor implements DataSourceProcessor { @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { configPanel.storeSettings(); - // TODO + Path imagePath = configPanel.getImagePath(); + System.out.println("ImagePath: " + imagePath.toString()); + String deviceId = UUID.randomUUID().toString(); + String timeZone = "America/New_York"; + boolean ignoreFatOrphanFiles = false; + run(deviceId, imagePath.toString(), 0, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callback); } /** - * Adds a "LogicalImager" data source to the case database using a background task in + * Adds a "raw" data source to the case database using a background task in * a separate thread and the given settings instead of those provided by the * selection and configuration panel. Returns as soon as the background task * is started and uses the callback object to signal task completion and @@ -142,10 +165,9 @@ public class LogicalImagerDSProcessor implements DataSourceProcessor { * during processing. * @param callback Callback to call when processing is done. */ - private void run(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { -// AddRawImageTask addImageTask = new AddRawImageTask(deviceId, imageFilePath, timeZone, chunkSize, progressMonitor, callback); -// new Thread(addImageTask).start(); -// TODO: 5011 Logical Imager DSP adds data + private void run(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { + addImageTask = new AddImageTask(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, null, progressMonitor, callback); + new Thread(addImageTask).start(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form index 9077c1722c..52de03d2ec 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form @@ -25,107 +25,160 @@ - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - - + + + + + + + + - - - - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -139,131 +192,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java index d8a0e955ec..fcbe10b8d8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java @@ -18,39 +18,41 @@ */ package org.sleuthkit.autopsy.casemodule; +import java.util.Vector; import java.io.File; -import java.util.Calendar; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.swing.JFileChooser; -import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JTextField; +import javax.swing.JTable; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import javax.swing.filechooser.FileFilter; -import org.apache.commons.lang3.StringUtils; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableModel; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; -import org.sleuthkit.autopsy.coreutils.DriveUtils; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; -import org.sleuthkit.autopsy.coreutils.PathValidator; -import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; -import org.sleuthkit.datamodel.HashUtility; /** - * Panel for adding an image file such as .img, .E0x, .00x, etc. Allows the user - * to select a file as well as choose the timezone and whether to ignore orphan - * files in FAT32. + * Panel for adding an logical image file from drive letters. Allows the user + * to select a file. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public class LogicalImagerPanel extends JPanel implements DocumentListener { private static final long serialVersionUID = 1L; - private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS - private static final String[] SECTOR_SIZE_CHOICES = {"Auto Detect", "512", "1024", "2048", "4096"}; + private static final String SELECTED_IMAGE_STR = NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageLabel.selectedImage"); + private static final String NO_IMAGE_SELECTED_STR = NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageLabel.noImageSelected"); + private static final String[] EMPTY_LIST_DATA = {}; private final JFileChooser fileChooser = new JFileChooser(); private final String contextName; - + private final Pattern regex = Pattern.compile("Logical_Imager_(.+)_(\\d{4})(\\d{2})(\\d{2})_(\\d{2})_(\\d{2})_(\\d{2})"); + private Path choosenImagePath; + private TableModel imageTableModel; /** * Creates new form LogicalImagerPanel * @@ -60,35 +62,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener { private LogicalImagerPanel(String context) { this.contextName = context; initComponents(); - - // Populate the drop down list of time zones - createTimeZoneList(); - - // Populate the drop down list of sector size options - for (String choice : SECTOR_SIZE_CHOICES) { - sectorSizeComboBox.addItem(choice); - } - sectorSizeComboBox.setSelectedIndex(0); - - errorLabel.setVisible(false); - - fileChooser.setDragEnabled(false); - fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.setMultiSelectionEnabled(false); - } - - /** - * Creates the drop down list for the time zones and defaults the selection - * to the local machine time zone. - */ - private void createTimeZoneList() { - List timeZoneList = TimeZoneUtils.createTimeZoneList(); - for (String timeZone : timeZoneList) { - timeZoneComboBox.addItem(timeZone); - } - - // set the selected timezone - timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone())); } /** @@ -104,29 +77,11 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener { public static synchronized LogicalImagerPanel createInstance(String context) { LogicalImagerPanel instance = new LogicalImagerPanel(context); // post-constructor initialization of listener support without leaking references of uninitialized objects - instance.getPathTextField().getDocument().addDocumentListener(instance); - instance.getMd5TextFieldField().getDocument().addDocumentListener(instance); - instance.getSha1TextField().getDocument().addDocumentListener(instance); - instance.getSha256TextField().getDocument().addDocumentListener(instance); + String label = NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageLabel.clickScanOrBrowse"); + instance.messageLabel.setText(label); return instance; } - private JTextField getPathTextField() { - return pathTextField; - } - - private JTextField getMd5TextFieldField() { - return md5HashTextField; - } - - private JTextField getSha1TextField() { - return sha1HashTextField; - } - - private JTextField getSha256TextField() { - return sha256HashTextField; - } - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -135,28 +90,54 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener { // //GEN-BEGIN:initComponents private void initComponents() { - pathLabel = new javax.swing.JLabel(); + topLabel = new javax.swing.JLabel(); + jLabel1 = new javax.swing.JLabel(); + scanButton = new javax.swing.JButton(); + messageLabel = new javax.swing.JLabel(); + selectDriveLabel = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + driveList = new javax.swing.JList<>(); + selectAcquisitionFromDriveLabel = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); browseButton = new javax.swing.JButton(); - pathTextField = new javax.swing.JTextField(); - timeZoneLabel = new javax.swing.JLabel(); - timeZoneComboBox = new javax.swing.JComboBox<>(); - noFatOrphansCheckbox = new javax.swing.JCheckBox(); - errorLabel = new javax.swing.JLabel(); - sectorSizeLabel = new javax.swing.JLabel(); - sectorSizeComboBox = new javax.swing.JComboBox<>(); - sha256HashLabel = new javax.swing.JLabel(); - sha256HashTextField = new javax.swing.JTextField(); - sha1HashTextField = new javax.swing.JTextField(); - md5HashTextField = new javax.swing.JTextField(); - sha1HashLabel = new javax.swing.JLabel(); - md5HashLabel = new javax.swing.JLabel(); - hashValuesLabel = new javax.swing.JLabel(); - hashValuesNoteLabel = new javax.swing.JLabel(); + imageScrollPane = new javax.swing.JScrollPane(); + imageTable = new javax.swing.JTable(); setMinimumSize(new java.awt.Dimension(0, 65)); setPreferredSize(new java.awt.Dimension(403, 65)); - org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.pathLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(topLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.topLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(scanButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.scanButton.text")); // NOI18N + scanButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + scanButtonActionPerformed(evt); + } + }); + + messageLabel.setForeground(new java.awt.Color(255, 0, 0)); + org.openide.awt.Mnemonics.setLocalizedText(messageLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(selectDriveLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectDriveLabel.text")); // NOI18N + + driveList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + driveList.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + driveListMouseClicked(evt); + } + }); + driveList.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + driveListKeyReleased(evt); + } + }); + jScrollPane1.setViewportView(driveList); + + org.openide.awt.Mnemonics.setLocalizedText(selectAcquisitionFromDriveLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectAcquisitionFromDriveLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.jLabel6.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.browseButton.text")); // NOI18N browseButton.addActionListener(new java.awt.event.ActionListener() { @@ -165,266 +146,230 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener { } }); - pathTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.pathTextField.text")); // NOI18N + imageTable.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { - org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.timeZoneLabel.text")); // NOI18N + }, + new String [] { - timeZoneComboBox.setMaximumRowCount(30); - - org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.noFatOrphansCheckbox.text")); // NOI18N - noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.noFatOrphansCheckbox.toolTipText")); // NOI18N - - errorLabel.setForeground(new java.awt.Color(255, 0, 0)); - org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.errorLabel.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(sectorSizeLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sectorSizeLabel.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(sha256HashLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha256HashLabel.text")); // NOI18N - sha256HashLabel.setEnabled(false); - - sha256HashTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha256HashTextField.text")); // NOI18N - sha256HashTextField.setEnabled(false); - - sha1HashTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha1HashTextField.text")); // NOI18N - sha1HashTextField.setEnabled(false); - - md5HashTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.md5HashTextField.text")); // NOI18N - md5HashTextField.setEnabled(false); - - org.openide.awt.Mnemonics.setLocalizedText(sha1HashLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha1HashLabel.text")); // NOI18N - sha1HashLabel.setEnabled(false); - - org.openide.awt.Mnemonics.setLocalizedText(md5HashLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.md5HashLabel.text")); // NOI18N - md5HashLabel.setEnabled(false); - - org.openide.awt.Mnemonics.setLocalizedText(hashValuesLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.hashValuesLabel.text")); // NOI18N - hashValuesLabel.setEnabled(false); - - org.openide.awt.Mnemonics.setLocalizedText(hashValuesNoteLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.hashValuesNoteLabel.text")); // NOI18N - hashValuesNoteLabel.setEnabled(false); + } + )); + imageTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); + imageTable.setShowHorizontalLines(false); + imageTable.setShowVerticalLines(false); + imageTable.getTableHeader().setReorderingAllowed(false); + imageTable.setUpdateSelectionOnSort(false); + imageTable.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + imageTableMouseClicked(evt); + } + }); + imageTable.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + imageTableKeyReleased(evt); + } + }); + imageScrollPane.setViewportView(imageTable); + imageTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(pathTextField) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(browseButton) - .addGap(2, 2, 2)) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pathLabel) - .addComponent(noFatOrphansCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 262, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(0, 368, Short.MAX_VALUE)) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(errorLabel) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addGroup(layout.createSequentialGroup() - .addComponent(timeZoneLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(sectorSizeLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(md5HashLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(sha1HashLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(sha256HashLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addComponent(hashValuesNoteLabel) - .addComponent(hashValuesLabel)) + .addGap(104, 104, 104) + .addComponent(topLabel) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(messageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addGap(28, 28, 28) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 258, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(scanButton, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 218, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addGap(13, 13, 13) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 305, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(selectAcquisitionFromDriveLabel) + .addComponent(browseButton)) + .addGap(0, 8, Short.MAX_VALUE)))) + .addGroup(layout.createSequentialGroup() + .addComponent(selectDriveLabel) + .addGap(0, 0, Short.MAX_VALUE))))) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(pathLabel) + .addComponent(topLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(browseButton) - .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(noFatOrphansCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel1) + .addComponent(jLabel6)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(timeZoneLabel)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(sectorSizeLabel)) - .addGap(39, 39, 39) - .addComponent(hashValuesLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(md5HashLabel)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(sha1HashLabel)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(sha256HashLabel)) - .addGap(18, 18, 18) - .addComponent(hashValuesNoteLabel) - .addGap(18, 18, 18) - .addComponent(errorLabel) - .addContainerGap(51, Short.MAX_VALUE)) + .addComponent(scanButton) + .addComponent(browseButton)) + .addGap(26, 26, 26) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(selectAcquisitionFromDriveLabel, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(selectDriveLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 118, Short.MAX_VALUE)) + .addGap(102, 102, 102) + .addComponent(messageLabel) + .addGap(154, 154, 154)) ); }// //GEN-END:initComponents - @NbBundle.Messages({"LogicalImagerPanel.000.confirmationMessage=The selected file" - + " has extenson .001 but there is a .000 file in the sequence of raw images." - + "\nShould the .000 file be used as the start, instead of the selected .001 file?\n"}) - private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed - String oldText = getContentPaths(); - // set the current directory of the FileChooser if the ImagePath Field is valid - File currentDir = new File(oldText); - if (currentDir.exists()) { - fileChooser.setCurrentDirectory(currentDir); + public static String humanReadableByteCount(long bytes, boolean si) { + int unit = si ? 1000 : 1024; + if (bytes < unit) return bytes + " B"; + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i"); + return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); + } + + private void scanButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scanButtonActionPerformed + // Scan external drives for sparse_image.vhd + messageLabel.setText(NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageLabel.scanningExternalDrives")); + Vector listData = new Vector<>(); + File[] paths = File.listRoots(); + // for each pathname in pathname array + for (File path : paths) { + String description = FileSystemView.getFileSystemView().getSystemTypeDescription(path); + Path tskLogicalImagerExe = Paths.get(path.toString(), "tsk_logical_imager.exe"); + File f = tskLogicalImagerExe.toFile(); + if (f.exists() && f.isFile() && f.canExecute()) { + long spaceInBytes = path.getTotalSpace(); + String sizeWithUnit = humanReadableByteCount(spaceInBytes, false); + listData.add(path + " (" + description + ") (" + sizeWithUnit + ")"); + } } + driveList.setListData(listData); + if (listData.size() > 0) { + // auto-select the first drive + driveList.setSelectedIndex(0); + driveListMouseClicked(null); + } else { + messageLabel.setText(NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageLabel.noExternalDriveFound")); + } + }//GEN-LAST:event_scanButtonActionPerformed - if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + int retval = fileChooser.showOpenDialog(this); + if (retval == JFileChooser.APPROVE_OPTION) { String path = fileChooser.getSelectedFile().getPath(); - if (path.endsWith(".001")) { - String zeroX3_path = StringUtils.removeEnd(path, ".001") + ".000"; - if (new File(zeroX3_path).exists()) { - int showConfirmDialog = JOptionPane.showConfirmDialog(this, - Bundle.LogicalImagerPanel_000_confirmationMessage(), - "Choose .001 file?", JOptionPane.YES_NO_OPTION); - if (showConfirmDialog == JOptionPane.YES_OPTION) { - path = zeroX3_path; + choosenImagePath = Paths.get(path); + messageLabel.setText(SELECTED_IMAGE_STR + " " + path); + firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); + } + }//GEN-LAST:event_browseButtonActionPerformed + + private void imageTableSelect() { + int index = imageTable.getSelectedRow(); + if (index != -1) { + choosenImagePath = Paths.get((String) imageTableModel.getValueAt(index, 2)); + messageLabel.setText(SELECTED_IMAGE_STR + " " + choosenImagePath.toString()); + firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); + } else { + messageLabel.setText(NO_IMAGE_SELECTED_STR); + } + } + + private void imageTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_imageTableMouseClicked + imageTableSelect(); + }//GEN-LAST:event_imageTableMouseClicked + + private void driveListSelect() { + String selectedStr = driveList.getSelectedValue(); + String choosenDriveLetter = selectedStr.substring(0, 3); + // Logical_Imager_DESKTOP-O71K0LB_20190506_18_46_54 + File directory = new File(choosenDriveLetter); + // Get all files from a directory. + File[] fList = directory.listFiles(); + if (fList != null) { + imageTableModel = new ImageTableModel(); + int row = 0; + for (File file : fList) { + if (file.isDirectory()) { + String dir = file.getName(); + Matcher m = regex.matcher(dir); + if (m.find()) { + String imagePath = choosenDriveLetter + dir + "/sparse_image.vhd"; + String hostname = m.group(1); + String year = m.group(2); + String month = m.group(3); + String day = m.group(4); + String hour = m.group(5); + String minute = m.group(6); + String second = m.group(7); + String extractDate = year + "/" + month + "/" + day + + " " + hour + ":" + minute + ":" + second; + imageTableModel.setValueAt(hostname, row, 0); + imageTableModel.setValueAt(extractDate, row, 1); + imageTableModel.setValueAt(imagePath, row, 2); + row++; } } } - - setContentPath(path); - - /** - * Automatically clear out the hash values if a new image was - * selected. - */ - if (!oldText.equals(getContentPaths())) { - md5HashTextField.setText(null); - sha1HashTextField.setText(null); - sha256HashTextField.setText(null); + String label = NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectAcquisitionFromDriveLabel.text") + + " " + choosenDriveLetter; + selectAcquisitionFromDriveLabel.setText(label); + imageTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + imageTable.setModel(imageTableModel); + // If there are any images, let's select the first one + if (imageTable.getRowCount() > 0) { + imageTable.setRowSelectionInterval(0, 0); + imageTableSelect(); } - } + } + } + + private void driveListMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_driveListMouseClicked + driveListSelect(); + }//GEN-LAST:event_driveListMouseClicked - updateHelper(); - }//GEN-LAST:event_browseButtonActionPerformed + private void driveListKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_driveListKeyReleased + driveListSelect(); + }//GEN-LAST:event_driveListKeyReleased + + private void imageTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_imageTableKeyReleased + imageTableSelect(); + }//GEN-LAST:event_imageTableKeyReleased // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton browseButton; - private javax.swing.JLabel errorLabel; - private javax.swing.JLabel hashValuesLabel; - private javax.swing.JLabel hashValuesNoteLabel; - private javax.swing.JLabel md5HashLabel; - private javax.swing.JTextField md5HashTextField; - private javax.swing.JCheckBox noFatOrphansCheckbox; - private javax.swing.JLabel pathLabel; - private javax.swing.JTextField pathTextField; - private javax.swing.JComboBox sectorSizeComboBox; - private javax.swing.JLabel sectorSizeLabel; - private javax.swing.JLabel sha1HashLabel; - private javax.swing.JTextField sha1HashTextField; - private javax.swing.JLabel sha256HashLabel; - private javax.swing.JTextField sha256HashTextField; - private javax.swing.JComboBox timeZoneComboBox; - private javax.swing.JLabel timeZoneLabel; + private javax.swing.JList driveList; + private javax.swing.JScrollPane imageScrollPane; + private javax.swing.JTable imageTable; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel6; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JLabel messageLabel; + private javax.swing.JButton scanButton; + private javax.swing.JLabel selectAcquisitionFromDriveLabel; + private javax.swing.JLabel selectDriveLabel; + private javax.swing.JLabel topLabel; // End of variables declaration//GEN-END:variables - /** - * Enable or disable all of the hash values components. - * - * @param enabled Enable components if true; otherwise disable. - */ - private void setHashValuesComponentsEnabled(boolean enabled) { - hashValuesLabel.setEnabled(enabled); - hashValuesNoteLabel.setEnabled(enabled); - - md5HashLabel.setEnabled(enabled); - md5HashTextField.setEnabled(enabled); - - sha1HashLabel.setEnabled(enabled); - sha1HashTextField.setEnabled(enabled); - - sha256HashLabel.setEnabled(enabled); - sha256HashTextField.setEnabled(enabled); - } - - /** - * Get the path of the user selected image. - * - * @return the image path - */ - public String getContentPaths() { - return pathTextField.getText(); - } - - /** - * Set the path of the image file. - * - * @param s path of the image file - */ - public void setContentPath(String s) { - pathTextField.setText(s); - } - - /** - * Get the sector size. - * - * @return 0 if autodetect; otherwise the value selected. - */ - public int getSectorSize() { - int sectorSizeSelectionIndex = sectorSizeComboBox.getSelectedIndex(); - - if (sectorSizeSelectionIndex == 0) { - return 0; - } - - return Integer.valueOf((String) sectorSizeComboBox.getSelectedItem()); - } - - public String getTimeZone() { - String tz = timeZoneComboBox.getSelectedItem().toString(); - return tz.substring(tz.indexOf(')') + 2).trim(); - } - - public boolean getNoFatOrphans() { - return noFatOrphansCheckbox.isSelected(); - } - - String getMd5() { - return this.md5HashTextField.getText(); - } - - String getSha1() { - return this.sha1HashTextField.getText(); - } - - String getSha256() { - return this.sha256HashTextField.getText(); - } - public void reset() { - //reset the UI elements to default - pathTextField.setText(null); - this.md5HashTextField.setText(null); - this.sha1HashTextField.setText(null); - this.sha256HashTextField.setText(null); + //reset the UI elements to default + driveList.setListData(EMPTY_LIST_DATA); + messageLabel.setText(""); } /** @@ -432,68 +377,18 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener { * * @return true if a proper image has been selected, false otherwise */ - @NbBundle.Messages({ - "LogicalImagerPanel.validatePanel.dataSourceOnCDriveError=Warning: Path to multi-user data source is on \"C:\" drive", - "LogicalImagerPanel.validatePanel.invalidMD5=Invalid MD5 hash", - "LogicalImagerPanel.validatePanel.invalidSHA1=Invalid SHA1 hash", - "LogicalImagerPanel.validatePanel.invalidSHA256=Invalid SHA256 hash",}) public boolean validatePanel() { - errorLabel.setVisible(false); - - String path = getContentPaths(); - if (!isImagePathValid()) { + if (choosenImagePath != null && choosenImagePath.toFile().exists()) { + return true; + } else { return false; } - - if (!StringUtils.isBlank(getMd5()) && !HashUtility.isValidMd5Hash(getMd5())) { - errorLabel.setVisible(true); - errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_invalidMD5()); - return false; - } - - if (!StringUtils.isBlank(getSha1()) && !HashUtility.isValidSha1Hash(getSha1())) { - errorLabel.setVisible(true); - errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_invalidSHA1()); - return false; - } - - if (!StringUtils.isBlank(getSha256()) && !HashUtility.isValidSha256Hash(getSha256())) { - errorLabel.setVisible(true); - errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_invalidSHA256()); - return false; - } - - if (!PathValidator.isValidForMultiUserCase(path, Case.getCurrentCase().getCaseType())) { - errorLabel.setVisible(true); - errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_dataSourceOnCDriveError()); - } - - return true; } - private boolean isImagePathValid() { - String path = getContentPaths(); - - if (StringUtils.isBlank(path) || (!(new File(path).isFile() || DriveUtils.isPhysicalDrive(path) || DriveUtils.isPartition(path)))) { - return false; - } - - return true; - } - public void storeSettings() { - String imagePathName = getContentPaths(); - if (null != imagePathName) { - String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1); - ModuleSettings.setConfigSetting(contextName, PROP_LASTIMAGE_PATH, imagePath); - } } public void readSettings() { - String lastImagePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTIMAGE_PATH); - if (StringUtils.isNotBlank(lastImagePath)) { - setContentPath(lastImagePath); - } } @Override @@ -521,19 +416,92 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener { "LogicalImagerPanel.moduleErr.msg=A module caused an error listening to LogicalImagerPanel updates." + " See log to determine which module. Some data could be incomplete.\n"}) private void updateHelper() { - if (isImagePathValid() && !getContentPaths().toLowerCase().endsWith(".e01")) { - setHashValuesComponentsEnabled(true); - } else { - setHashValuesComponentsEnabled(false); - } - - firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); } /** * Set the focus to the pathTextField. */ public void select() { - pathTextField.requestFocusInWindow(); + } + + Path getImagePath() { + return choosenImagePath; + } + + private class ImageTableModel extends AbstractTableModel { + private List hostnames = new ArrayList<>(); + private List extractDates = new ArrayList<>(); + private List imagePaths = new ArrayList<>(); + + @Override + public int getRowCount() { + return hostnames.size(); + } + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public String getColumnName(int column) { + String colName = null; + switch (column) { + case 0: + colName = NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.imageTable.columnModel.title0"); + break; + case 1: + colName = NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.imageTable.columnModel.title1"); + break; + default: + break; + } + return colName; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + Object ret = null; + switch (columnIndex) { + case 0: + ret = hostnames.get(rowIndex); + break; + case 1: + ret = extractDates.get(rowIndex); + break; + case 2: + ret = imagePaths.get(rowIndex); + break; + default: + throw new UnsupportedOperationException("Invalid table column index: " + columnIndex); + } + return ret; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + hostnames.add((String) aValue); + break; + case 1: + extractDates.add((String) aValue); + break; + case 2: + imagePaths.add((String) aValue); + break; + default: + throw new UnsupportedOperationException("Invalid table column index: " + columnIndex); + } + // Only show the hostname and extractDates column + if (columnIndex < 2) { + super.setValueAt(aValue, rowIndex, columnIndex); + } + } } }