5187 add drive list to logical imager config panel 1

This commit is contained in:
William Schaefer 2019-06-20 18:52:58 -04:00
parent d51d5d25b6
commit 37ebeeeaec
8 changed files with 320 additions and 91 deletions

View File

@ -119,3 +119,4 @@ NewRulePanel.chooseLabel.text=Choose the type of rule
ConfigVisualPanel1.configureDriveRadioButton.text_1=Configure selected external drive:
ConfigVisualPanel1.configureFolderRadioButton.text_1=Configure in a folder:
ConfigVisualPanel1.descriptionTextArea.text=Select a location you will configure for use by the Logical Imager. A config file will be created if one does not already exist, and a copy of the Logical Imager executable will copied to this location. This will also be the location where the Logical Imager executable creates folders containing output.
ConfigVisualPanel1.refreshButton.text=Refresh

View File

@ -29,6 +29,7 @@ ConfigVisualPanel1.configFileIsEmpty=Configuration file {0} is empty
ConfigVisualPanel1.configurationError=Configuration error
ConfigVisualPanel1.fileNameExtensionFilter=Configuration JSON File
ConfigVisualPanel1.invalidConfigJson=Invalid config JSON:
ConfigVisualPanel1.messageLabel.noExternalDriveFound=No drive found
ConfigVisualPanel1.selectConfigurationFile=Select configuration file
ConfigVisualPanel2.cancel=Cancel
ConfigVisualPanel2.deleteRuleSet=Delete rule
@ -172,9 +173,10 @@ LogicalImagerConfigDeserializer.missingRuleSetException=Missing rule-set
# {0} - key
LogicalImagerConfigDeserializer.unsupportedKeyException=Unsupported key: {0}
NewRulePanel.chooseLabel.text=Choose the type of rule
ConfigVisualPanel1.jTextArea1.text=Select a location you will configure for use by the Logical Imager. A config file will be created if one does not already exist, and a copy of the Logical Imager executable will copied to this location. This will also be the location where the Logical Imager executable creates folders containing its output.
ConfigVisualPanel1.configureDriveRadioButton.text_1=Configure selected external drive:
ConfigVisualPanel1.configureFolderRadioButton.text_1=Configure in a folder:
ConfigVisualPanel1.descriptionTextArea.text=Select a location you will configure for use by the Logical Imager. A config file will be created if one does not already exist, and a copy of the Logical Imager executable will copied to this location. This will also be the location where the Logical Imager executable creates folders containing output.
ConfigVisualPanel1.refreshButton.text=Refresh
NewRuleSetPanel.attributeRule.description=Search for files based on one or more attributes or metadata fields.
NewRuleSetPanel.attributeRule.name=Attribute
NewRuleSetPanel.fullPathRule.description=Search for files based on full exact match path.

View File

@ -23,27 +23,29 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
<Component id="configFileTextField" min="-2" pref="281" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="11" max="32767" attributes="0"/>
<Component id="warningLabel" max="32767" attributes="0"/>
<Component id="descriptionScrollPane" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="driveListScrollPane" alignment="1" pref="281" max="32767" attributes="0"/>
<Component id="configFileTextField" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="refreshButton" pref="87" max="32767" attributes="0"/>
<Component id="browseButton" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="descriptionScrollPane" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="configureDriveRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="configureFolderRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="configureDriveRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="configureFolderRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -54,14 +56,24 @@
<Component id="descriptionScrollPane" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
<Component id="configureDriveRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="60" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="driveListScrollPane" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="46" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="configureFolderRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="configFileTextField" min="-2" max="-2" attributes="0"/>
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="78" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="warningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="70" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -73,6 +85,7 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.configFileTextField.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="browseButton">
@ -83,6 +96,7 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.browseButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
@ -126,6 +140,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.configureDriveRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="configureDriveRadioButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="configureFolderRadioButton">
<Properties>
@ -136,6 +153,52 @@
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.configureFolderRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="configureFolderRadioButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="driveListScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JList" name="driveList">
<Properties>
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
<StringArray count="0"/>
</Property>
<Property name="selectionMode" type="int" value="0"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="driveListMouseReleasedSelection"/>
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="driveListKeyReleasedSelection"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="refreshButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="refreshButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="warningLabel">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,14 +28,22 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.logicalimager.dsp.DriveListUtils;
/**
* Configuration Visual Panel 1
@ -43,6 +51,7 @@ import org.openide.util.NbBundle;
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final class ConfigVisualPanel1 extends JPanel {
private static final long serialVersionUID = 1L;
private LogicalImagerConfig config;
private String configFilename;
private boolean newFile = true;
@ -53,6 +62,10 @@ final class ConfigVisualPanel1 extends JPanel {
ConfigVisualPanel1() {
initComponents();
configFileTextField.getDocument().addDocumentListener(new MyDocumentListener(this));
SwingUtilities.invokeLater(() -> {
updateControls();
});
refreshDriveList();
}
@NbBundle.Messages({
@ -78,12 +91,18 @@ final class ConfigVisualPanel1 extends JPanel {
descriptionTextArea = new javax.swing.JTextArea();
configureDriveRadioButton = new javax.swing.JRadioButton();
configureFolderRadioButton = new javax.swing.JRadioButton();
driveListScrollPane = new javax.swing.JScrollPane();
driveList = new javax.swing.JList<>();
refreshButton = new javax.swing.JButton();
warningLabel = new javax.swing.JLabel();
configFileTextField.setEditable(false);
configFileTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.configFileTextField.text_1")); // NOI18N
configFileTextField.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.browseButton.text")); // NOI18N
browseButton.setToolTipText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.browseButton.toolTipText")); // NOI18N
browseButton.setEnabled(false);
browseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseButtonActionPerformed(evt);
@ -104,9 +123,43 @@ final class ConfigVisualPanel1 extends JPanel {
configurationLocationButtonGroup.add(configureDriveRadioButton);
configureDriveRadioButton.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(configureDriveRadioButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.configureDriveRadioButton.text_1")); // NOI18N
configureDriveRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
configureDriveRadioButtonActionPerformed(evt);
}
});
configurationLocationButtonGroup.add(configureFolderRadioButton);
org.openide.awt.Mnemonics.setLocalizedText(configureFolderRadioButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.configureFolderRadioButton.text_1")); // NOI18N
configureFolderRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
configureFolderRadioButtonActionPerformed(evt);
}
});
driveList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
driveList.setEnabled(false);
driveList.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(java.awt.event.MouseEvent evt) {
driveListMouseReleasedSelection(evt);
}
});
driveList.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
driveListKeyReleasedSelection(evt);
}
});
driveListScrollPane.setViewportView(driveList);
org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.refreshButton.text")); // NOI18N
refreshButton.setEnabled(false);
refreshButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
refreshButtonActionPerformed(evt);
}
});
warningLabel.setForeground(new java.awt.Color(255, 0, 0));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@ -115,21 +168,23 @@ final class ConfigVisualPanel1 extends JPanel {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(warningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(descriptionScrollPane)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addComponent(configFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 281, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
.addComponent(configFileTextField, javax.swing.GroupLayout.Alignment.LEADING))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(browseButton)
.addContainerGap(11, Short.MAX_VALUE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(refreshButton, javax.swing.GroupLayout.DEFAULT_SIZE, 87, Short.MAX_VALUE)
.addComponent(browseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(descriptionScrollPane)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(configureDriveRadioButton)
.addComponent(configureFolderRadioButton))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())))
.addComponent(configureDriveRadioButton)
.addComponent(configureFolderRadioButton))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -138,13 +193,21 @@ final class ConfigVisualPanel1 extends JPanel {
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(13, 13, 13)
.addComponent(configureDriveRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 60, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(driveListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(refreshButton)
.addGap(0, 46, Short.MAX_VALUE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(configureFolderRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(configFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseButton))
.addGap(78, 78, 78))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(warningLabel)
.addContainerGap(70, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
@ -152,21 +215,82 @@ final class ConfigVisualPanel1 extends JPanel {
"ConfigVisualPanel1.chooseFileTitle=Select a Logical Imager configuration"
})
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
chooseFile(Bundle.ConfigVisualPanel1_chooseFileTitle());
chooseFile(Bundle.ConfigVisualPanel1_chooseFileTitle());
}//GEN-LAST:event_browseButtonActionPerformed
private void configureFolderRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configureFolderRadioButtonActionPerformed
updateControls();
}//GEN-LAST:event_configureFolderRadioButtonActionPerformed
private void configureDriveRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configureDriveRadioButtonActionPerformed
updateControls();
}//GEN-LAST:event_configureDriveRadioButtonActionPerformed
private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
refreshDriveList();
}//GEN-LAST:event_refreshButtonActionPerformed
private void driveListKeyReleasedSelection(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_driveListKeyReleasedSelection
// TODO add your handling code here:
}//GEN-LAST:event_driveListKeyReleasedSelection
private void driveListMouseReleasedSelection(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_driveListMouseReleasedSelection
// TODO add your handling code here:
}//GEN-LAST:event_driveListMouseReleasedSelection
@Messages({"ConfigVisualPanel1.messageLabel.noExternalDriveFound=No drive found"})
private void refreshDriveList() {
List<String> listData = new ArrayList<>();
File[] roots = File.listRoots();
int firstRemovableDrive = -1;
int i = 0;
for (File root : roots) {
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
long spaceInBytes = root.getTotalSpace();
String sizeWithUnit = DriveListUtils.humanReadableByteCount(spaceInBytes, false);
listData.add(root + " (" + description + ") (" + sizeWithUnit + ")");
if (firstRemovableDrive == -1) {
try {
FileStore fileStore = Files.getFileStore(root.toPath());
if ((boolean) fileStore.getAttribute("volume:isRemovable")) { //NON-NLS
firstRemovableDrive = i;
}
} catch (IOException ignored)
}
}
i++;
}
driveList.setListData(listData.toArray(new String[listData.size()]));
if (!listData.isEmpty()) {
// auto-select the first external drive, if any
driveList.setSelectedIndex(firstRemovableDrive == -1 ? 0 : firstRemovableDrive);
driveListMouseReleasedSelection(null);
driveList.requestFocusInWindow();
warningLabel.setText("");
} else {
warningLabel.setText(Bundle.ConfigVisualPanel1_messageLabel_noExternalDriveFound());
}
}
private void updateControls() {
browseButton.setEnabled(configureFolderRadioButton.isSelected());
driveList.setEnabled(configureDriveRadioButton.isSelected());
driveListScrollPane.setEnabled(configureDriveRadioButton.isSelected());
}
@NbBundle.Messages({
"ConfigVisualPanel1.fileNameExtensionFilter=Configuration JSON File",
"ConfigVisualPanel1.invalidConfigJson=Invalid config JSON: ",
"ConfigVisualPanel1.configurationError=Configuration error",
})
"ConfigVisualPanel1.configurationError=Configuration error",})
private void chooseFile(String title) {
final String jsonExt = ".json"; // NON-NLS
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle(title);
fileChooser.setDragEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
FileFilter filter = new FileNameExtensionFilter(Bundle.ConfigVisualPanel1_fileNameExtensionFilter(), new String[] {"json"}); // NON-NLS
FileFilter filter = new FileNameExtensionFilter(Bundle.ConfigVisualPanel1_fileNameExtensionFilter(), new String[]{"json"}); // NON-NLS
fileChooser.setFileFilter(filter);
fileChooser.setSelectedFile(new File("logical-imager-config.json")); // default
fileChooser.setMultiSelectionEnabled(false);
@ -179,10 +303,10 @@ final class ConfigVisualPanel1 extends JPanel {
configFileTextField.setText(path);
newFile = false;
} catch (JsonIOException | JsonSyntaxException | IOException ex) {
JOptionPane.showMessageDialog(this,
Bundle.ConfigVisualPanel1_invalidConfigJson() + ex.getMessage() ,
Bundle.ConfigVisualPanel1_configurationError(),
JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(this,
Bundle.ConfigVisualPanel1_invalidConfigJson() + ex.getMessage(),
Bundle.ConfigVisualPanel1_configurationError(),
JOptionPane.ERROR_MESSAGE);
}
} else {
if (!path.endsWith(jsonExt)) {
@ -195,7 +319,7 @@ final class ConfigVisualPanel1 extends JPanel {
}
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton browseButton;
private javax.swing.JTextField configFileTextField;
@ -204,12 +328,15 @@ final class ConfigVisualPanel1 extends JPanel {
private javax.swing.JRadioButton configureFolderRadioButton;
private javax.swing.JScrollPane descriptionScrollPane;
private javax.swing.JTextArea descriptionTextArea;
private javax.swing.JList<String> driveList;
private javax.swing.JScrollPane driveListScrollPane;
private javax.swing.JButton refreshButton;
private javax.swing.JLabel warningLabel;
// End of variables declaration//GEN-END:variables
@NbBundle.Messages({
"# {0} - filename",
"ConfigVisualPanel1.configFileIsEmpty=Configuration file {0} is empty",
})
"ConfigVisualPanel1.configFileIsEmpty=Configuration file {0} is empty",})
private void loadConfigFile(String path) throws FileNotFoundException, JsonIOException, JsonSyntaxException, IOException {
try (FileInputStream is = new FileInputStream(path)) {
InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
@ -241,7 +368,8 @@ final class ConfigVisualPanel1 extends JPanel {
}
boolean isPanelValid() {
return (newFile || !configFileTextField.getText().isEmpty());
return (configureDriveRadioButton.isSelected() && driveList.getSelectedIndex() >= 0)
|| (configureFolderRadioButton.isSelected() && (newFile || !configFileTextField.getText().isEmpty()));
}
/**
@ -250,7 +378,7 @@ final class ConfigVisualPanel1 extends JPanel {
private static class MyDocumentListener implements DocumentListener {
private final ConfigVisualPanel1 panel;
MyDocumentListener(ConfigVisualPanel1 aThis) {
this.panel = aThis;
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -42,12 +42,13 @@ import org.openide.util.NbBundle;
final class ConfigVisualPanel2 extends JPanel {
private static final List<String> EMPTY_LIST = new ArrayList<>();
private static final long serialVersionUID = 1L;
private String configFilename;
private LogicalImagerConfig config = null;
private final JButton okButton = new JButton(Bundle.ConfigVisualPanel2_ok());
private final JButton cancelButton = new JButton(Bundle.ConfigVisualPanel2_cancel());
private boolean flagEncryptionPrograms = false;
/**
* Creates new form ConfigVisualPanel2
*/
@ -431,9 +432,9 @@ final class ConfigVisualPanel2 extends JPanel {
editPanel.setVisible(true);
while (true) {
int option = JOptionPane.showOptionDialog(this, editPanel.getPanel(), Bundle.ConfigVisualPanel2_editRuleSet(),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
int option = JOptionPane.showOptionDialog(this, editPanel.getPanel(), Bundle.ConfigVisualPanel2_editRuleSet(),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
if (option == JOptionPane.OK_OPTION) {
try {
ImmutablePair<String, LogicalImagerRule> ruleMap = editPanel.toRule();
@ -441,16 +442,16 @@ final class ConfigVisualPanel2 extends JPanel {
break;
} catch (IOException | NumberFormatException ex) {
JOptionPane.showMessageDialog(this,
ex.getMessage(),
Bundle.ConfigVisualPanel2_editRuleError(),
JOptionPane.ERROR_MESSAGE);
ex.getMessage(),
Bundle.ConfigVisualPanel2_editRuleError(),
JOptionPane.ERROR_MESSAGE);
// let user fix the error
}
} else {
break;
}
}
}
}
}//GEN-LAST:event_editRuleButtonActionPerformed
private void newRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRuleButtonActionPerformed
@ -460,9 +461,9 @@ final class ConfigVisualPanel2 extends JPanel {
panel.setVisible(true);
while (true) {
int option = JOptionPane.showOptionDialog(this, panel, "New rule",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
int option = JOptionPane.showOptionDialog(this, panel, "New rule",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
if (option == JOptionPane.OK_OPTION) {
try {
// Save the new rule
@ -471,30 +472,29 @@ final class ConfigVisualPanel2 extends JPanel {
break;
} catch (IOException | NumberFormatException ex) {
JOptionPane.showMessageDialog(this,
ex.getMessage(),
"New rule error",
JOptionPane.ERROR_MESSAGE);
ex.getMessage(),
"New rule error",
JOptionPane.ERROR_MESSAGE);
// let user fix the error
}
} else {
break;
}
}
}
}//GEN-LAST:event_newRuleButtonActionPerformed
@NbBundle.Messages({
"ConfigVisualPanel2.deleteRuleSet=Delete rule ",
"ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule confirmation",
})
"ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule confirmation",})
private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed
int index = rulesTable.getSelectedRow();
if (index != -1) {
String ruleName = (String) rulesTable.getModel().getValueAt(index, 0);
int option = JOptionPane.showOptionDialog(this,
Bundle.ConfigVisualPanel2_deleteRuleSet() + ruleName,
Bundle.ConfigVisualPanel2_deleteRuleSetConfirmation(),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
int option = JOptionPane.showOptionDialog(this,
Bundle.ConfigVisualPanel2_deleteRuleSet() + ruleName,
Bundle.ConfigVisualPanel2_deleteRuleSetConfirmation(),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
if (option == JOptionPane.NO_OPTION) {
return;
}
@ -521,7 +521,7 @@ final class ConfigVisualPanel2 extends JPanel {
if (flagEncryptionPrograms) {
// add the special rule
ImmutablePair<String, LogicalImagerRule> ruleMap = createEncryptionProgramsRule();
appendRow(ruleMap);
appendRow(ruleMap);
} else {
// remove it
int index = ((RulesTableModel) rulesTable.getModel()).findRow(EncryptionProgramsRule.getName());
@ -535,7 +535,7 @@ final class ConfigVisualPanel2 extends JPanel {
}
}
}
/*
* Create an encryption programs rule
*/
@ -596,7 +596,7 @@ final class ConfigVisualPanel2 extends JPanel {
}
return config.getRuleSets().get(0);
}
private void updatePanel(String configFilePath, LogicalImagerConfig config, String rowSelectionkey) {
configFileTextField.setText(configFilePath);
finalizeImageWriter.setSelected(config.isFinalizeImageWriter());
@ -607,7 +607,7 @@ final class ConfigVisualPanel2 extends JPanel {
int selectThisRow = 0;
Collections.sort(ruleSet.getRules(), new SortRuleByName());
for (LogicalImagerRule rule : ruleSet.getRules()) {
rulesTableModel.setValueAt(rule.getName(), row, 0);
if (rowSelectionkey != null && rowSelectionkey.equals(rule.getName())) {
@ -627,7 +627,7 @@ final class ConfigVisualPanel2 extends JPanel {
updateRuleButtons(false);
}
}
private void updatePanel(String configFilePath, LogicalImagerConfig config) {
updatePanel(configFilePath, config, null);
}
@ -638,9 +638,9 @@ final class ConfigVisualPanel2 extends JPanel {
String ruleName = (String) rulesTable.getModel().getValueAt(index, 0);
String description = (String) rulesTable.getModel().getValueAt(index, 1);
updateRuleDetails(ruleName, description, config);
updateRuleButtons(ruleName.equals(EncryptionProgramsRule.getName()) ? false : true);
updateRuleButtons(!ruleName.equals(EncryptionProgramsRule.getName()));
} else {
updateRuleButtons(false);
updateRuleButtons(false);
}
}
@ -685,7 +685,7 @@ final class ConfigVisualPanel2 extends JPanel {
}
String content = "";
boolean first = true;
for (String ext : extensions) {
for (String ext : extensions) {
content += (first ? "" : ",") + ext;
first = false;
}
@ -750,6 +750,7 @@ final class ConfigVisualPanel2 extends JPanel {
*/
private class SortRuleByName implements Comparator<LogicalImagerRule> {
@Override
public int compare(LogicalImagerRule a, LogicalImagerRule b) {
return a.getName().compareToIgnoreCase(b.getName());
}
@ -760,6 +761,7 @@ final class ConfigVisualPanel2 extends JPanel {
*/
private class RulesTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final List<String> ruleName = new ArrayList<>();
private final List<String> ruleDescription = new ArrayList<>();
private final List<LogicalImagerRule> rule = new ArrayList<>();
@ -767,7 +769,7 @@ final class ConfigVisualPanel2 extends JPanel {
int findRow(String name) {
return ruleName.indexOf(name);
}
@Override
public int getRowCount() {
return ruleName.size();
@ -849,6 +851,8 @@ final class ConfigVisualPanel2 extends JPanel {
*/
private class SingleColumnTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final List<String> list = new ArrayList<>();
@Override

View File

@ -0,0 +1,39 @@
/*
* Autopsy
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.logicalimager.dsp;
public final class DriveListUtils {
public static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) {
return bytes + " B"; //NON-NLS
}
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); //NON-NLS
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); //NON-NLS
}
/**
* Empty private constructor for util class
*/
private DriveListUtils() {
//empty private constructor for util class
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -288,15 +288,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
);
}// </editor-fold>//GEN-END:initComponents
private static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) {
return bytes + " B"; //NON-NLS
}
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); //NON-NLS
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); //NON-NLS
}
@Messages({
"# {0} - sparseImageDirectory",
@ -490,7 +482,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
for (File root : roots) {
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
long spaceInBytes = root.getTotalSpace();
String sizeWithUnit = humanReadableByteCount(spaceInBytes, false);
String sizeWithUnit = DriveListUtils.humanReadableByteCount(spaceInBytes, false);
listData.add(root + " (" + description + ") (" + sizeWithUnit + ")");
if (firstRemovableDrive == -1) {
try {