diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form
index f5a370ae4c..afc1a07d2b 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form
@@ -72,7 +72,7 @@
-
+
@@ -89,7 +89,7 @@
-
+
@@ -294,9 +294,6 @@
-
-
-
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java
index b54d468d34..492cbb7d3a 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java
@@ -100,7 +100,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
*/
// //GEN-BEGIN:initComponents
private void initComponents() {
- bindingGroup = new org.jdesktop.beansbinding.BindingGroup();
buttonGroup1 = new javax.swing.ButtonGroup();
browseButton = new javax.swing.JButton();
@@ -219,10 +218,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
messageTextArea.setDisabledTextColor(java.awt.Color.red);
messageTextArea.setEnabled(false);
messageTextArea.setMargin(new java.awt.Insets(0, 0, 0, 0));
-
- org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, messageTextArea, org.jdesktop.beansbinding.ELProperty.create("false"), messageTextArea, org.jdesktop.beansbinding.BeanProperty.create("editable"));
- bindingGroup.addBinding(binding);
-
jScrollPane1.setViewportView(messageTextArea);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
@@ -262,7 +257,7 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 568, javax.swing.GroupLayout.PREFERRED_SIZE)))
- .addContainerGap(14, Short.MAX_VALUE))
+ .addContainerGap(338, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -276,7 +271,7 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
- .addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 186, Short.MAX_VALUE))
+ .addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 461, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(refreshButton)
.addGap(18, 18, 18)
@@ -293,8 +288,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(6, 6, 6))
);
-
- bindingGroup.bind();
}// //GEN-END:initComponents
public static String humanReadableByteCount(long bytes, boolean si) {
@@ -555,7 +548,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
private javax.swing.JLabel selectDriveLabel;
private javax.swing.JLabel selectFolderLabel;
private javax.swing.JLabel selectFromDriveLabel;
- private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration//GEN-END:variables
public void reset() {
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties
new file mode 100644
index 0000000000..11fbe567a5
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties
@@ -0,0 +1,129 @@
+ConfigureLogicalImagerDialog.loadButton.text=Load
+ConfigureLogicalImagerDialog.newButton.text=New
+ConfigureLogicalImagerDialog.title=Configure Logical Imager
+ConfigureLogicalImagerDialog.saveButton.text=Save
+ConfigureLogicalImagerDialog.configFile.text=
+ConfigureLogicalImagerDialog.configFile.toolTipText=
+ConfigureLogicalImagerDialog.jLabel1.text=Rule Set:
+ConfigureLogicalImagerDialog.finalizeImageWriter.text=Finalize Image Writer
+ConfigureLogicalImagerDialog.newRuleButton.text=New Rule
+ConfigureLogicalImagerDialog.editRuleButton.text=Edit Rule
+ConfigureLogicalImagerDialog.deleteRuleButton.text=Delete Rule
+ConfigureLogicalImagerDialog.jLabel2.text=Rule Details
+ConfigureLogicalImagerDialog.shouldSaveCheckBox.text=Should Save
+ConfigureLogicalImagerDialog.shouldAlertCheckBox.text=Should Alert
+ConfigureLogicalImagerDialog.jLabel3.text=Extensions:
+ConfigureLogicalImagerDialog.extensionsTextField.text=
+ConfigureLogicalImagerDialog.filenamesLabel.text=File names:
+ConfigureLogicalImagerDialog.folderNamesLabel.text=Folder names:
+ConfigureLogicalImagerDialog.jLabel4.text=File size:
+ConfigureLogicalImagerDialog.daysIncludedLabel.text=day(s)
+ConfigureLogicalImagerDialog.daysIncludedTextField.text=
+ConfigureLogicalImagerDialog.modifiedDateLabel.text=Modified Within:
+ConfigureLogicalImagerDialog.fullPathsLabel.text=Full paths:
+ConfigureLogicalImagerDialog.flagEncryptionProgramsCheckBox.text=Flag encryption programs
+EditRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
+EditRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
+EditRulePanel.fullPathsLabel.text=Full paths:
+EditRulePanel.daysIncludedLabel.text=day(s)
+EditRulePanel.daysIncludedTextField.text=
+EditRulePanel.modifiedDateLabel.text=Modified Within:
+EditRulePanel.folderNamesLabel.text=Folder names:
+EditRulePanel.filenamesLabel.text=File names:
+EditRulePanel.extensionsTextField.text=
+ConfigureLogicalImagerDialog.jLabel5.text=Rule Name:
+ConfigureLogicalImagerDialog.jLabel6.text=Description:
+ConfigureLogicalImagerDialog.ruleNameEditTextField.text=
+ConfigureLogicalImagerDialog.descriptionEditTextField.text=
+ConfigureLogicalImagerDialog.fullPathsTable.columnModel.title0=
+ConfigVisualPanel1.jTextField1.text=
+ConfigVisualPanel1.jLabel1.text=Configuration file
+ConfigVisualPanel2.jCheckBox1.text=jCheckBox1
+ConfigVisualPanel2.jCheckBox2.text=jCheckBox2
+ConfigVisualPanel2.jTextField1.text=jTextField1
+ConfigVisualPanel1.jRadioButton1.text=Create new configuration
+ConfigVisualPanel1.jRadioButton2.text=Open existing configuration
+ConfigVisualPanel1.jLabel1.text_1=Configuration file:
+ConfigVisualPanel1.configFileTextField.text_1=
+ConfigVisualPanel2.modifiedDateLabel.text=Modified Within:
+ConfigVisualPanel2.folderNamesLabel.text=Folder names:
+ConfigVisualPanel2.finalizeImageWriter.text=Continue imaging after searches are performed
+ConfigVisualPanel2.filenamesLabel.text=File names:
+ConfigVisualPanel2.extensionsTextField.text=
+ConfigVisualPanel2.shouldAlertCheckBox.text=Alert in imager console if rule matches
+ConfigVisualPanel2.shouldSaveCheckBox.text=Extract file if it matches a rule
+ConfigVisualPanel2.deleteRuleButton.text=Delete Rule
+ConfigVisualPanel2.descriptionEditTextField.text=
+ConfigVisualPanel2.editRuleButton.text=Edit Rule
+ConfigVisualPanel2.newRuleButton.text=New Rule
+ConfigVisualPanel2.ruleNameEditTextField.text=
+ConfigVisualPanel2.flagEncryptionProgramsCheckBox.text=Alert if encryption programs are found
+ConfigVisualPanel2.fullPathsLabel.text=Full paths:
+ConfigVisualPanel2.daysIncludedLabel.text=day(s)
+ConfigVisualPanel2.daysIncludedTextField.text=
+ConfigVisualPanel2.configFileTextField.toolTipText=
+ConfigVisualPanel2.configFileTextField.text=
+ConfigVisualPanel2.filenamesTable.columnModel.title0=
+ConfigVisualPanel2.fileSizeLabel.text=File size in bytes:
+ConfigVisualPanel2.extensionsLabel.text=Extensions:
+ConfigVisualPanel2.descriptionLabel.text=Description:
+ConfigVisualPanel2.ruleNameLabel.text=Rule Name:
+ConfigVisualPanel2.ruleSetFileLabel.text=Configuration rule file:
+EditRulePanel.ruleNameLabel.text=Rule Set:
+EditRulePanel.descriptionTextField.text=
+EditRulePanel.extensionsLabel.text=Extensions:
+EditRulePanel.ruleNameTextField.text=
+EditRulePanel.extensionsCheckBox.text=
+EditRulePanel.filenamesCheckBox.text=
+EditRulePanel.folderNamesCheckBox.text=
+EditRulePanel.fullPathsCheckBox.text=
+EditRulePanel.fileSizeCheckBox.text=
+EditRulePanel.minDaysCheckBox.text=
+EditRulePanel.fileSizeLabel.text=File size:
+EditRulePanel.descriptionLabel.text=Description:
+EditRulePanel.jTable1.columnModel.title3=Title 4
+EditRulePanel.jTable1.columnModel.title2=Title 3
+EditRulePanel.jTable1.columnModel.title1=Title 2
+EditRulePanel.shouldAlertCheckBox.actionCommand=
+EditFullPathsRulePanel.ruleNameLabel.text=Rule Name:
+EditFullPathsRulePanel.descriptionLabel.text=Description:
+EditFullPathsRulePanel.descriptionTextField.text=
+EditFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
+EditFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
+EditFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
+EditFullPathsRulePanel.ruleNameTextField.text=
+EditFullPathsRulePanel.fullPathsLabel.text=Full paths:
+EditFullPathsRulePanel.fullPathsLabel.toolTipText=
+EditNonFullPathsRulePanel.ruleNameTextField.text=
+EditNonFullPathsRulePanel.ruleNameLabel.text=Rule Name:
+EditNonFullPathsRulePanel.descriptionLabel.text=Description:
+EditNonFullPathsRulePanel.descriptionTextField.text=
+EditNonFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
+EditNonFullPathsRulePanel.daysIncludedLabel.text=day(s)
+EditNonFullPathsRulePanel.modifiedDateLabel.text=Modified Within:
+EditNonFullPathsRulePanel.fileSizeLabel.text=File size (bytes):
+EditNonFullPathsRulePanel.folderNamesLabel.text=Folder names:
+EditNonFullPathsRulePanel.filenamesLabel.text=File names:
+EditNonFullPathsRulePanel.extensionsTextField.text=
+EditNonFullPathsRulePanel.extensionsLabel.text=Extensions:
+EditNonFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
+EditNonFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
+ConfigVisualPanel1.browseButton.text=Browse
+ConfigVisualPanel2.fullPathsTable.columnModel.title0=
+ConfigVisualPanel2.folderNamesTable.columnModel.title0=
+ConfigVisualPanel2.shouldSaveCheckBox.toolTipText=
+NewRuleSetPanel.chooseLabel.text=Choose the type of rule
+EditNonFullPathsRulePanel.minSizeLabel.text=Minimum:
+EditNonFullPathsRulePanel.maxSizeLabel.text=Maximum:
+EditNonFullPathsRulePanel.minSizeTextField.text=
+EditNonFullPathsRulePanel.maxSizeTextField.text=
+ConfigVisualPanel2.maxSizeTextField.text=
+ConfigVisualPanel2.maxSizeLabel.text=Maximum:
+ConfigVisualPanel2.minSizeTextField.text=
+ConfigVisualPanel2.minSizeLabel.text=Minimum:
+EditNonFullPathsRulePanel.minDaysTextField.text=jFormattedTextField1
+ConfigVisualPanel1.browseButton.toolTipText=
+EditNonFullPathsRulePanel.extensionsRadioButton.text=
+EditNonFullPathsRulePanel.filenamesRadioButton.text=
+EditNonFullPathsRulePanel.extensionsRadioButton.toolTipText=Extensions and File names are mutually exclusive
+EditNonFullPathsRulePanel.filenamesRadioButton.toolTipText=Extensions and File names are mutually exclusive
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties-MERGED
new file mode 100644
index 0000000000..2828435b1a
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties-MERGED
@@ -0,0 +1,180 @@
+ConfigureLogicalImager.title=Configure Logical Imager
+ConfigureLogicalImagerDialog.loadButton.text=Load
+ConfigureLogicalImagerDialog.newButton.text=New
+ConfigureLogicalImagerDialog.title=Configure Logical Imager
+ConfigureLogicalImagerDialog.saveButton.text=Save
+ConfigureLogicalImagerDialog.configFile.text=
+ConfigureLogicalImagerDialog.configFile.toolTipText=
+ConfigureLogicalImagerDialog.jLabel1.text=Rule Set:
+ConfigureLogicalImagerDialog.finalizeImageWriter.text=Finalize Image Writer
+ConfigureLogicalImagerDialog.newRuleButton.text=New Rule
+ConfigureLogicalImagerDialog.editRuleButton.text=Edit Rule
+ConfigureLogicalImagerDialog.deleteRuleButton.text=Delete Rule
+ConfigureLogicalImagerDialog.jLabel2.text=Rule Details
+ConfigureLogicalImagerDialog.shouldSaveCheckBox.text=Should Save
+ConfigureLogicalImagerDialog.shouldAlertCheckBox.text=Should Alert
+ConfigureLogicalImagerDialog.jLabel3.text=Extensions:
+ConfigureLogicalImagerDialog.extensionsTextField.text=
+ConfigureLogicalImagerDialog.filenamesLabel.text=File names:
+ConfigureLogicalImagerDialog.folderNamesLabel.text=Folder names:
+ConfigureLogicalImagerDialog.jLabel4.text=File size:
+ConfigureLogicalImagerDialog.daysIncludedLabel.text=day(s)
+ConfigureLogicalImagerDialog.daysIncludedTextField.text=
+ConfigureLogicalImagerDialog.modifiedDateLabel.text=Modified Within:
+ConfigureLogicalImagerDialog.fullPathsLabel.text=Full paths:
+ConfigureLogicalImagerDialog.flagEncryptionProgramsCheckBox.text=Flag encryption programs
+ConfigVisualPanel1.chooseFileTitle=Select a Logical Imager configuration
+# {0} - filename
+ConfigVisualPanel1.configFileIsEmpty=Configuration file {0} is empty
+ConfigVisualPanel1.configurationError=Configuration error
+ConfigVisualPanel1.fileNameExtensionFilter=Configuration JSON File
+ConfigVisualPanel1.invalidConfigJson=Invalid config JSON:
+ConfigVisualPanel1.selectConfigurationFile=Select configuration file
+ConfigVisualPanel2.cancel=Cancel
+ConfigVisualPanel2.deleteRuleSet=Delete rule
+ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule confirmation
+ConfigVisualPanel2.editConfiguration=Edit configuration
+ConfigVisualPanel2.editRuleError=Edit rule error
+ConfigVisualPanel2.editRuleSet=Edit rule
+ConfigVisualPanel2.ok=OK
+ConfigVisualPanel2.rulesTable.columnModel.title0=Rule Name
+ConfigVisualPanel2.rulesTable.columnModel.title1=Description
+# {0} - configFilename
+ConfigWizardPanel2.failedToSaveConfigMsg=Failed to save configuration file: {0}
+ConfigWizardPanel2.failedToSaveExeMsg=Failed to save tsk_logical_imager.exe file
+# {0} - reason
+ConfigWizardPanel2.reason=\nReason:
+CTL_ConfigureLogicalImager=Configure Logical Imager
+EditFullPathsRulePanel.example=Example:
+EditFullPathsRulePanel.fullPaths=Full paths
+EditNonFullPathsRulePanel.emptyExtensionException=Extensions cannot have an empty entry
+EditNonFullPathsRulePanel.example=Example:
+EditNonFullPathsRulePanel.fileNames=File names
+EditNonFullPathsRulePanel.folderNames=Folder names
+# {0} - message
+EditNonFullPathsRulePanel.maxFileSizeMustBeNumberException=Maximum file size must be a number: {0}
+EditNonFullPathsRulePanel.maxFileSizeNotPositiveException=Maximum file size must be a positive
+# {0} - maxFileSize
+# {1} - minFileSize
+EditNonFullPathsRulePanel.maxFileSizeSmallerThanMinException=Maximum file size: {0} must be bigger than minimum file size: {1}
+# {0} - message
+EditNonFullPathsRulePanel.minFileSizeMustBeNumberException=Minimum file size must be a number: {0}
+EditNonFullPathsRulePanel.minFileSizeNotPositiveException=Minimum file size must be a positive
+# {0} - message
+EditNonFullPathsRulePanel.modifiedDaysMustBeNumberException=Modified days must be a number: {0}
+EditNonFullPathsRulePanel.modifiedDaysNotPositiveException=Modified days must be a positive
+EditNonFullPathsRulePanel.note=NOTE: A special [USER_FOLDER] token at the the start of a folder name to allow matches of all user folders in the file system.
+# {0} - fieldName
+EditRulePanel.blankLineException={0} cannot have a blank line
+EditRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
+EditRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
+EditRulePanel.fullPathsLabel.text=Full paths:
+EditRulePanel.daysIncludedLabel.text=day(s)
+EditRulePanel.daysIncludedTextField.text=
+EditRulePanel.modifiedDateLabel.text=Modified Within:
+EditRulePanel.folderNamesLabel.text=Folder names:
+EditRulePanel.filenamesLabel.text=File names:
+EditRulePanel.extensionsTextField.text=
+ConfigureLogicalImagerDialog.jLabel5.text=Rule Name:
+ConfigureLogicalImagerDialog.jLabel6.text=Description:
+ConfigureLogicalImagerDialog.ruleNameEditTextField.text=
+ConfigureLogicalImagerDialog.descriptionEditTextField.text=
+ConfigureLogicalImagerDialog.fullPathsTable.columnModel.title0=
+ConfigVisualPanel1.jTextField1.text=
+ConfigVisualPanel1.jLabel1.text=Configuration file
+ConfigVisualPanel2.jCheckBox1.text=jCheckBox1
+ConfigVisualPanel2.jCheckBox2.text=jCheckBox2
+ConfigVisualPanel2.jTextField1.text=jTextField1
+ConfigVisualPanel1.jRadioButton1.text=Create new configuration
+ConfigVisualPanel1.jRadioButton2.text=Open existing configuration
+ConfigVisualPanel1.jLabel1.text_1=Configuration file:
+ConfigVisualPanel1.configFileTextField.text_1=
+ConfigVisualPanel2.modifiedDateLabel.text=Modified Within:
+ConfigVisualPanel2.folderNamesLabel.text=Folder names:
+ConfigVisualPanel2.finalizeImageWriter.text=Continue imaging after searches are performed
+ConfigVisualPanel2.filenamesLabel.text=File names:
+ConfigVisualPanel2.extensionsTextField.text=
+ConfigVisualPanel2.shouldAlertCheckBox.text=Alert in imager console if rule matches
+ConfigVisualPanel2.shouldSaveCheckBox.text=Extract file if it matches a rule
+ConfigVisualPanel2.deleteRuleButton.text=Delete Rule
+ConfigVisualPanel2.descriptionEditTextField.text=
+ConfigVisualPanel2.editRuleButton.text=Edit Rule
+ConfigVisualPanel2.newRuleButton.text=New Rule
+ConfigVisualPanel2.ruleNameEditTextField.text=
+ConfigVisualPanel2.flagEncryptionProgramsCheckBox.text=Alert if encryption programs are found
+ConfigVisualPanel2.fullPathsLabel.text=Full paths:
+ConfigVisualPanel2.daysIncludedLabel.text=day(s)
+ConfigVisualPanel2.daysIncludedTextField.text=
+ConfigVisualPanel2.configFileTextField.toolTipText=
+ConfigVisualPanel2.configFileTextField.text=
+ConfigVisualPanel2.filenamesTable.columnModel.title0=
+ConfigVisualPanel2.fileSizeLabel.text=File size in bytes:
+ConfigVisualPanel2.extensionsLabel.text=Extensions:
+ConfigVisualPanel2.descriptionLabel.text=Description:
+ConfigVisualPanel2.ruleNameLabel.text=Rule Name:
+ConfigVisualPanel2.ruleSetFileLabel.text=Configuration rule file:
+EditRulePanel.ruleNameLabel.text=Rule Set:
+EditRulePanel.descriptionTextField.text=
+EditRulePanel.extensionsLabel.text=Extensions:
+EditRulePanel.ruleNameTextField.text=
+EditRulePanel.extensionsCheckBox.text=
+EditRulePanel.filenamesCheckBox.text=
+EditRulePanel.folderNamesCheckBox.text=
+EditRulePanel.fullPathsCheckBox.text=
+EditRulePanel.fileSizeCheckBox.text=
+EditRulePanel.minDaysCheckBox.text=
+EditRulePanel.fileSizeLabel.text=File size:
+EditRulePanel.descriptionLabel.text=Description:
+EditRulePanel.jTable1.columnModel.title3=Title 4
+EditRulePanel.jTable1.columnModel.title2=Title 3
+EditRulePanel.jTable1.columnModel.title1=Title 2
+EditRulePanel.shouldAlertCheckBox.actionCommand=
+EditFullPathsRulePanel.ruleNameLabel.text=Rule Name:
+EditFullPathsRulePanel.descriptionLabel.text=Description:
+EditFullPathsRulePanel.descriptionTextField.text=
+EditFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
+EditFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
+EditFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
+EditFullPathsRulePanel.ruleNameTextField.text=
+EditFullPathsRulePanel.fullPathsLabel.text=Full paths:
+EditFullPathsRulePanel.fullPathsLabel.toolTipText=
+EditNonFullPathsRulePanel.ruleNameTextField.text=
+EditNonFullPathsRulePanel.ruleNameLabel.text=Rule Name:
+EditNonFullPathsRulePanel.descriptionLabel.text=Description:
+EditNonFullPathsRulePanel.descriptionTextField.text=
+EditNonFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
+EditNonFullPathsRulePanel.daysIncludedLabel.text=day(s)
+EditNonFullPathsRulePanel.modifiedDateLabel.text=Modified Within:
+EditNonFullPathsRulePanel.fileSizeLabel.text=File size (bytes):
+EditNonFullPathsRulePanel.folderNamesLabel.text=Folder names:
+EditNonFullPathsRulePanel.filenamesLabel.text=File names:
+EditNonFullPathsRulePanel.extensionsTextField.text=
+EditNonFullPathsRulePanel.extensionsLabel.text=Extensions:
+EditNonFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
+EditNonFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
+ConfigVisualPanel1.browseButton.text=Browse
+ConfigVisualPanel2.fullPathsTable.columnModel.title0=
+ConfigVisualPanel2.folderNamesTable.columnModel.title0=
+ConfigVisualPanel2.shouldSaveCheckBox.toolTipText=
+EditRulePanel.validateRuleNameExceptionMsg=Rule name cannot be empty
+EncryptionProgramsRule.encryptionProgramsRuleDescription=Find encryption programs
+EncryptionProgramsRule.encryptionProgramsRuleName=Encryption Programs
+LogicalImagerConfigDeserializer.fullPathsException=A rule with full-paths cannot have other rule definitions
+LogicalImagerConfigDeserializer.missingRuleSetException=Missing rule-set
+# {0} - key
+LogicalImagerConfigDeserializer.unsupportedKeyException=Unsupported key: {0}
+NewRuleSetPanel.chooseLabel.text=Choose the type of rule
+EditNonFullPathsRulePanel.minSizeLabel.text=Minimum:
+EditNonFullPathsRulePanel.maxSizeLabel.text=Maximum:
+EditNonFullPathsRulePanel.minSizeTextField.text=
+EditNonFullPathsRulePanel.maxSizeTextField.text=
+ConfigVisualPanel2.maxSizeTextField.text=
+ConfigVisualPanel2.maxSizeLabel.text=Maximum:
+ConfigVisualPanel2.minSizeTextField.text=
+ConfigVisualPanel2.minSizeLabel.text=Minimum:
+EditNonFullPathsRulePanel.minDaysTextField.text=jFormattedTextField1
+ConfigVisualPanel1.browseButton.toolTipText=
+EditNonFullPathsRulePanel.extensionsRadioButton.text=
+EditNonFullPathsRulePanel.filenamesRadioButton.text=
+EditNonFullPathsRulePanel.extensionsRadioButton.toolTipText=Extensions and File names are mutually exclusive
+EditNonFullPathsRulePanel.filenamesRadioButton.toolTipText=Extensions and File names are mutually exclusive
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.form b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.form
new file mode 100644
index 0000000000..64ff17f7fe
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.form
@@ -0,0 +1,80 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.java
new file mode 100644
index 0000000000..a32c9f3a92
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.java
@@ -0,0 +1,242 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+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.filechooser.FileFilter;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import org.openide.util.NbBundle;
+
+/**
+ * Configuration Visual Panel 1
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+public final class ConfigVisualPanel1 extends JPanel {
+
+ private LogicalImagerConfig config;
+ private String configFilename;
+ private boolean newFile = true;
+
+ /**
+ * Creates new form ConfigVisualPanel1
+ */
+ public ConfigVisualPanel1() {
+ initComponents();
+ configFileTextField.getDocument().addDocumentListener(new MyDocumentListener(this));
+ }
+
+ @NbBundle.Messages({
+ "ConfigVisualPanel1.selectConfigurationFile=Select configuration file"
+ })
+ @Override
+ public String getName() {
+ return Bundle.ConfigVisualPanel1_selectConfigurationFile();
+ }
+
+ /**
+ * 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
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ buttonGroup1 = new javax.swing.ButtonGroup();
+ jLabel1 = new javax.swing.JLabel();
+ configFileTextField = new javax.swing.JTextField();
+ browseButton = new javax.swing.JButton();
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.jLabel1.text_1")); // NOI18N
+
+ configFileTextField.setEditable(false);
+ configFileTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.configFileTextField.text_1")); // NOI18N
+
+ 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.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ browseButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(38, 38, 38)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel1)
+ .addComponent(configFileTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(browseButton)
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(116, 116, 116)
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(configFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(browseButton))
+ .addContainerGap(141, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ @NbBundle.Messages({
+ "ConfigVisualPanel1.chooseFileTitle=Select a Logical Imager configuration"
+ })
+ private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
+ chooseFile(Bundle.ConfigVisualPanel1_chooseFileTitle());
+ }//GEN-LAST:event_browseButtonActionPerformed
+
+ @NbBundle.Messages({
+ "ConfigVisualPanel1.fileNameExtensionFilter=Configuration JSON File",
+ "ConfigVisualPanel1.invalidConfigJson=Invalid config JSON: ",
+ "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
+ fileChooser.setFileFilter(filter);
+ fileChooser.setSelectedFile(new File("config.json")); // default
+ fileChooser.setMultiSelectionEnabled(false);
+ if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+ String path = fileChooser.getSelectedFile().getPath();
+ if (new File(path).exists()) {
+ try {
+ loadConfigFile(path);
+ configFilename = path;
+ configFileTextField.setText(path);
+ newFile = false;
+ } catch (JsonIOException | JsonSyntaxException | IOException ex) {
+ JOptionPane.showMessageDialog(this,
+ Bundle.ConfigVisualPanel1_invalidConfigJson() + ex.getMessage() ,
+ Bundle.ConfigVisualPanel1_configurationError(),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ } else {
+ if (!path.endsWith(jsonExt)) {
+ path += jsonExt;
+ }
+ configFilename = path;
+ configFileTextField.setText(path);
+ config = new LogicalImagerConfig();
+ newFile = true;
+ }
+ }
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton browseButton;
+ private javax.swing.ButtonGroup buttonGroup1;
+ private javax.swing.JTextField configFileTextField;
+ private javax.swing.JLabel jLabel1;
+ // End of variables declaration//GEN-END:variables
+
+ @NbBundle.Messages({
+ "# {0} - filename",
+ "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);
+ GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting();
+ gsonBuilder.registerTypeAdapter(LogicalImagerConfig.class, new LogicalImagerConfigDeserializer());
+ Gson gson = gsonBuilder.create();
+ config = gson.fromJson(reader, LogicalImagerConfig.class);
+ if (config == null) {
+ // This happens if the file is empty. Gson doesn't call the deserializer and doesn't throw any exception.
+ throw new IOException(Bundle.ConfigVisualPanel1_configFileIsEmpty(path));
+ }
+ }
+ }
+
+ public LogicalImagerConfig getConfig() {
+ return config;
+ }
+
+ public String getConfigFilename() {
+ return configFilename;
+ }
+
+ public boolean isNewFile() {
+ return newFile;
+ }
+
+ void setConfigFilename(String filename) {
+ configFileTextField.setText(filename);
+ }
+
+ public boolean isPanelValid() {
+ return (newFile || !configFileTextField.getText().isEmpty());
+ }
+
+ /**
+ * Document Listener for textfield
+ */
+ private static class MyDocumentListener implements DocumentListener {
+
+ private final ConfigVisualPanel1 panel;
+
+ public MyDocumentListener(ConfigVisualPanel1 aThis) {
+ this.panel = aThis;
+ }
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ fireChange();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ fireChange();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ fireChange();
+ }
+
+ private void fireChange() {
+ panel.firePropertyChange("UPDATE_UI", false, true); // NON-NLS
+ }
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.form b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.form
new file mode 100644
index 0000000000..a6231e1120
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.form
@@ -0,0 +1,604 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.java
new file mode 100644
index 0000000000..31bd583be1
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.java
@@ -0,0 +1,900 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openide.util.NbBundle;
+
+/**
+ * Configuration Visual Panel 2
+ */
+@NbBundle.Messages({
+ "ConfigVisualPanel2.ok=OK",
+ "ConfigVisualPanel2.cancel=Cancel"
+})
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+public final class ConfigVisualPanel2 extends JPanel {
+
+ private static final List EMPTY_LIST = new ArrayList<>();
+ 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
+ */
+ public ConfigVisualPanel2() {
+ initComponents();
+ if (config != null) {
+ updatePanel(configFilename, config);
+ }
+ }
+
+ @NbBundle.Messages({
+ "ConfigVisualPanel2.editConfiguration=Edit configuration"
+ })
+ @Override
+ public String getName() {
+ return Bundle.ConfigVisualPanel2_editConfiguration();
+ }
+
+ /**
+ * 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
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ modifiedDateLabel = new javax.swing.JLabel();
+ daysIncludedTextField = new javax.swing.JTextField();
+ daysIncludedLabel = new javax.swing.JLabel();
+ fullPathsLabel = new javax.swing.JLabel();
+ flagEncryptionProgramsCheckBox = new javax.swing.JCheckBox();
+ ruleNameLabel = new javax.swing.JLabel();
+ ruleNameEditTextField = new javax.swing.JTextField();
+ newRuleButton = new javax.swing.JButton();
+ descriptionLabel = new javax.swing.JLabel();
+ editRuleButton = new javax.swing.JButton();
+ descriptionEditTextField = new javax.swing.JTextField();
+ deleteRuleButton = new javax.swing.JButton();
+ jScrollPane5 = new javax.swing.JScrollPane();
+ fullPathsTable = new javax.swing.JTable();
+ jScrollPane6 = new javax.swing.JScrollPane();
+ filenamesTable = new javax.swing.JTable();
+ shouldSaveCheckBox = new javax.swing.JCheckBox();
+ shouldAlertCheckBox = new javax.swing.JCheckBox();
+ jScrollPane7 = new javax.swing.JScrollPane();
+ folderNamesTable = new javax.swing.JTable();
+ extensionsLabel = new javax.swing.JLabel();
+ extensionsTextField = new javax.swing.JTextField();
+ filenamesLabel = new javax.swing.JLabel();
+ configFileTextField = new javax.swing.JTextField();
+ ruleSetFileLabel = new javax.swing.JLabel();
+ finalizeImageWriter = new javax.swing.JCheckBox();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ rulesTable = new javax.swing.JTable();
+ folderNamesLabel = new javax.swing.JLabel();
+ fileSizeLabel = new javax.swing.JLabel();
+ jSeparator1 = new javax.swing.JSeparator();
+ minSizeLabel = new javax.swing.JLabel();
+ minSizeTextField = new javax.swing.JFormattedTextField();
+ maxSizeLabel = new javax.swing.JLabel();
+ maxSizeTextField = new javax.swing.JFormattedTextField();
+
+ org.openide.awt.Mnemonics.setLocalizedText(modifiedDateLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.modifiedDateLabel.text")); // NOI18N
+
+ daysIncludedTextField.setEditable(false);
+ daysIncludedTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
+ daysIncludedTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.daysIncludedTextField.text")); // NOI18N
+ daysIncludedTextField.setEnabled(false);
+ daysIncludedTextField.setMinimumSize(new java.awt.Dimension(60, 20));
+ daysIncludedTextField.setPreferredSize(new java.awt.Dimension(60, 20));
+
+ org.openide.awt.Mnemonics.setLocalizedText(daysIncludedLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.daysIncludedLabel.text")); // NOI18N
+ daysIncludedLabel.setEnabled(false);
+
+ org.openide.awt.Mnemonics.setLocalizedText(fullPathsLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.fullPathsLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(flagEncryptionProgramsCheckBox, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.flagEncryptionProgramsCheckBox.text")); // NOI18N
+ flagEncryptionProgramsCheckBox.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ flagEncryptionProgramsCheckBoxActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.ruleNameLabel.text")); // NOI18N
+
+ ruleNameEditTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.ruleNameEditTextField.text")); // NOI18N
+ ruleNameEditTextField.setEnabled(false);
+
+ newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.newRuleButton.text")); // NOI18N
+ newRuleButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ newRuleButtonActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.descriptionLabel.text")); // NOI18N
+
+ editRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(editRuleButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.editRuleButton.text")); // NOI18N
+ editRuleButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ editRuleButtonActionPerformed(evt);
+ }
+ });
+
+ descriptionEditTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.descriptionEditTextField.text")); // NOI18N
+ descriptionEditTextField.setEnabled(false);
+
+ deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.deleteRuleButton.text")); // NOI18N
+ deleteRuleButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ deleteRuleButtonActionPerformed(evt);
+ }
+ });
+
+ fullPathsTable.setColumnSelectionAllowed(true);
+ fullPathsTable.setEnabled(false);
+ fullPathsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ fullPathsTable.setShowHorizontalLines(false);
+ fullPathsTable.setShowVerticalLines(false);
+ fullPathsTable.getTableHeader().setReorderingAllowed(false);
+ jScrollPane5.setViewportView(fullPathsTable);
+ fullPathsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
+ if (fullPathsTable.getColumnModel().getColumnCount() > 0) {
+ fullPathsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.fullPathsTable.columnModel.title0")); // NOI18N
+ }
+
+ filenamesTable.setEnabled(false);
+ filenamesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ filenamesTable.setShowHorizontalLines(false);
+ filenamesTable.setShowVerticalLines(false);
+ filenamesTable.getTableHeader().setReorderingAllowed(false);
+ jScrollPane6.setViewportView(filenamesTable);
+ if (filenamesTable.getColumnModel().getColumnCount() > 0) {
+ filenamesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.filenamesTable.columnModel.title0")); // NOI18N
+ }
+
+ shouldSaveCheckBox.setSelected(true);
+ org.openide.awt.Mnemonics.setLocalizedText(shouldSaveCheckBox, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.shouldSaveCheckBox.text")); // NOI18N
+ shouldSaveCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.shouldSaveCheckBox.toolTipText")); // NOI18N
+ shouldSaveCheckBox.setEnabled(false);
+
+ shouldAlertCheckBox.setSelected(true);
+ org.openide.awt.Mnemonics.setLocalizedText(shouldAlertCheckBox, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.shouldAlertCheckBox.text")); // NOI18N
+ shouldAlertCheckBox.setEnabled(false);
+
+ folderNamesTable.setEnabled(false);
+ folderNamesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ folderNamesTable.setShowHorizontalLines(false);
+ folderNamesTable.setShowVerticalLines(false);
+ folderNamesTable.getTableHeader().setReorderingAllowed(false);
+ jScrollPane7.setViewportView(folderNamesTable);
+ if (folderNamesTable.getColumnModel().getColumnCount() > 0) {
+ folderNamesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.folderNamesTable.columnModel.title0")); // NOI18N
+ }
+
+ org.openide.awt.Mnemonics.setLocalizedText(extensionsLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.extensionsLabel.text")); // NOI18N
+
+ extensionsTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.extensionsTextField.text")); // NOI18N
+ extensionsTextField.setEnabled(false);
+
+ org.openide.awt.Mnemonics.setLocalizedText(filenamesLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.filenamesLabel.text")); // NOI18N
+
+ configFileTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.configFileTextField.text")); // NOI18N
+ configFileTextField.setToolTipText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.configFileTextField.toolTipText")); // NOI18N
+ configFileTextField.setEnabled(false);
+
+ org.openide.awt.Mnemonics.setLocalizedText(ruleSetFileLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.ruleSetFileLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(finalizeImageWriter, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.finalizeImageWriter.text")); // NOI18N
+ finalizeImageWriter.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ finalizeImageWriterActionPerformed(evt);
+ }
+ });
+
+ rulesTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
+ rulesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ rulesTable.setShowHorizontalLines(false);
+ rulesTable.setShowVerticalLines(false);
+ rulesTable.getTableHeader().setReorderingAllowed(false);
+ rulesTable.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseReleased(java.awt.event.MouseEvent evt) {
+ rulesTableMouseReleased(evt);
+ }
+ });
+ rulesTable.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyReleased(java.awt.event.KeyEvent evt) {
+ rulesTableKeyReleased(evt);
+ }
+ });
+ jScrollPane1.setViewportView(rulesTable);
+ if (rulesTable.getColumnModel().getColumnCount() > 0) {
+ rulesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.rulesTable.columnModel.title0")); // NOI18N
+ rulesTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.rulesTable.columnModel.title1")); // NOI18N
+ }
+
+ org.openide.awt.Mnemonics.setLocalizedText(folderNamesLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.folderNamesLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(fileSizeLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.fileSizeLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(minSizeLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.minSizeLabel.text")); // NOI18N
+
+ minSizeTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#,###; "))));
+ minSizeTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.minSizeTextField.text")); // NOI18N
+ minSizeTextField.setEnabled(false);
+
+ org.openide.awt.Mnemonics.setLocalizedText(maxSizeLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.maxSizeLabel.text")); // NOI18N
+
+ maxSizeTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#,###; "))));
+ maxSizeTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.maxSizeTextField.text")); // NOI18N
+ maxSizeTextField.setEnabled(false);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(480, 480, 480)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(daysIncludedLabel))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(ruleNameEditTextField, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(descriptionEditTextField, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(extensionsTextField, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane6, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane7, javax.swing.GroupLayout.Alignment.LEADING))
+ .addContainerGap())))
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 377, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(newRuleButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(editRuleButton)
+ .addGap(37, 37, 37)
+ .addComponent(deleteRuleButton)))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(flagEncryptionProgramsCheckBox)
+ .addComponent(finalizeImageWriter)))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(393, 393, 393)
+ .addComponent(shouldSaveCheckBox))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(397, 397, 397)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(extensionsLabel)
+ .addComponent(filenamesLabel)
+ .addComponent(descriptionLabel)
+ .addComponent(ruleNameLabel)))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(397, 397, 397)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(modifiedDateLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(fileSizeLabel)
+ .addComponent(fullPathsLabel)
+ .addComponent(folderNamesLabel))
+ .addGap(4, 4, 4)
+ .addComponent(minSizeLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(minSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addComponent(maxSizeLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(maxSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(393, 393, 393)
+ .addComponent(shouldAlertCheckBox)))
+ .addContainerGap())
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(17, 17, 17)
+ .addComponent(ruleSetFileLabel)
+ .addGap(18, 18, 18)
+ .addComponent(configFileTextField))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(397, 397, 397)
+ .addComponent(jSeparator1)))
+ .addGap(10, 10, 10))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(configFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(ruleSetFileLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 527, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(newRuleButton)
+ .addComponent(editRuleButton)
+ .addComponent(deleteRuleButton)))
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(30, 30, 30)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(descriptionEditTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(descriptionLabel))
+ .addGap(9, 9, 9)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(extensionsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(extensionsLabel)))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(ruleNameEditTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(ruleNameLabel)))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane6, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(filenamesLabel)
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane7, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(folderNamesLabel)
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(fullPathsLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGap(11, 11, 11)))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(minSizeLabel)
+ .addComponent(minSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(maxSizeLabel)
+ .addComponent(maxSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(fileSizeLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(modifiedDateLabel)
+ .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(daysIncludedLabel))
+ .addGap(3, 3, 3)
+ .addComponent(shouldAlertCheckBox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(shouldSaveCheckBox)
+ .addGap(18, 18, 18)
+ .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(flagEncryptionProgramsCheckBox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(finalizeImageWriter)))
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+ private void finalizeImageWriterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_finalizeImageWriterActionPerformed
+ config.setFinalizeImageWriter(finalizeImageWriter.isSelected());
+ }//GEN-LAST:event_finalizeImageWriterActionPerformed
+
+ private void rulesTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_rulesTableKeyReleased
+ rulesTableSelect();
+ }//GEN-LAST:event_rulesTableKeyReleased
+
+ @NbBundle.Messages({
+ "ConfigVisualPanel2.editRuleSet=Edit rule",
+ "ConfigVisualPanel2.editRuleError=Edit rule error"
+ })
+ private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed
+ int row = rulesTable.getSelectedRow();
+ if (row != -1) {
+ String ruleName = (String) rulesTable.getModel().getValueAt(row, 0);
+ LogicalImagerRule rule = getFirstRuleSet().getRules().get(row);
+ EditRulePanel editPanel = new EditRulePanel(okButton, cancelButton, ruleName, rule);
+ editPanel.setEnabled(true);
+ 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);
+ if (option == JOptionPane.OK_OPTION) {
+ try {
+ ImmutablePair ruleMap = editPanel.toRule();
+ updateRow(row, ruleMap);
+ break;
+ } catch (IOException | NumberFormatException ex) {
+ JOptionPane.showMessageDialog(this,
+ 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
+ NewRuleSetPanel panel;
+ panel = new NewRuleSetPanel(okButton, cancelButton);
+ panel.setEnabled(true);
+ 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);
+ if (option == JOptionPane.OK_OPTION) {
+ try {
+ // Save the new rule
+ ImmutablePair ruleMap = panel.toRule();
+ appendRow(ruleMap);
+ break;
+ } catch (IOException | NumberFormatException ex) {
+ JOptionPane.showMessageDialog(this,
+ 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",
+ })
+ 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);
+ if (option == JOptionPane.NO_OPTION) {
+ return;
+ }
+
+ getFirstRuleSet().getRules().remove(index);
+ updatePanel(configFilename, config);
+ if (rulesTable.getRowCount() > 0) {
+ rulesTable.setRowSelectionInterval(0, 0);
+ rulesTableSelect();
+ }
+ }
+ }//GEN-LAST:event_deleteRuleButtonActionPerformed
+
+ private void flagEncryptionProgramsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_flagEncryptionProgramsCheckBoxActionPerformed
+ flagEncryptionPrograms = flagEncryptionProgramsCheckBox.isSelected();
+ toggleEncryptionProgramsRule(flagEncryptionPrograms);
+ }//GEN-LAST:event_flagEncryptionProgramsCheckBoxActionPerformed
+
+ private void rulesTableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rulesTableMouseReleased
+ rulesTableSelect();
+ }//GEN-LAST:event_rulesTableMouseReleased
+
+ private void toggleEncryptionProgramsRule(boolean flagEncryptionPrograms) {
+ if (flagEncryptionPrograms) {
+ // add the special rule
+ ImmutablePair ruleMap = createEncryptionProgramsRule();
+ appendRow(ruleMap);
+ } else {
+ // remove it
+ int index = ((RulesTableModel) rulesTable.getModel()).findRow(EncryptionProgramsRule.getName());
+ if (index != -1) {
+ getFirstRuleSet().getRules().remove(index);
+ updatePanel(configFilename, config);
+ if (rulesTable.getRowCount() > 0) {
+ rulesTable.setRowSelectionInterval(0, 0);
+ rulesTableSelect();
+ }
+ }
+ }
+ }
+
+ /*
+ * Create an encryption programs rule
+ */
+ private ImmutablePair createEncryptionProgramsRule() {
+ LogicalImagerRule.Builder builder = new LogicalImagerRule.Builder();
+ builder.getName(EncryptionProgramsRule.getName())
+ .getDescription(EncryptionProgramsRule.getDescription())
+ .getShouldAlert(true)
+ .getShouldSave(true)
+ .getFilenames(EncryptionProgramsRule.getFilenames());
+ LogicalImagerRule rule = builder.build();
+ return new ImmutablePair<>(EncryptionProgramsRule.getName(), rule);
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextField configFileTextField;
+ private javax.swing.JLabel daysIncludedLabel;
+ private javax.swing.JTextField daysIncludedTextField;
+ private javax.swing.JButton deleteRuleButton;
+ private javax.swing.JTextField descriptionEditTextField;
+ private javax.swing.JLabel descriptionLabel;
+ private javax.swing.JButton editRuleButton;
+ private javax.swing.JLabel extensionsLabel;
+ private javax.swing.JTextField extensionsTextField;
+ private javax.swing.JLabel fileSizeLabel;
+ private javax.swing.JLabel filenamesLabel;
+ private javax.swing.JTable filenamesTable;
+ private javax.swing.JCheckBox finalizeImageWriter;
+ private javax.swing.JCheckBox flagEncryptionProgramsCheckBox;
+ private javax.swing.JLabel folderNamesLabel;
+ private javax.swing.JTable folderNamesTable;
+ private javax.swing.JLabel fullPathsLabel;
+ private javax.swing.JTable fullPathsTable;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JScrollPane jScrollPane5;
+ private javax.swing.JScrollPane jScrollPane6;
+ private javax.swing.JScrollPane jScrollPane7;
+ private javax.swing.JSeparator jSeparator1;
+ private javax.swing.JLabel maxSizeLabel;
+ private javax.swing.JFormattedTextField maxSizeTextField;
+ private javax.swing.JLabel minSizeLabel;
+ private javax.swing.JFormattedTextField minSizeTextField;
+ private javax.swing.JLabel modifiedDateLabel;
+ private javax.swing.JButton newRuleButton;
+ private javax.swing.JTextField ruleNameEditTextField;
+ private javax.swing.JLabel ruleNameLabel;
+ private javax.swing.JLabel ruleSetFileLabel;
+ private javax.swing.JTable rulesTable;
+ private javax.swing.JCheckBox shouldAlertCheckBox;
+ private javax.swing.JCheckBox shouldSaveCheckBox;
+ // End of variables declaration//GEN-END:variables
+
+ private LogicalImagerRuleSet getFirstRuleSet() {
+ if (config.getRuleSets().isEmpty()) {
+ List ruleSets = new ArrayList<>();
+ ruleSets.add(new LogicalImagerRuleSet("no-set-name", new ArrayList<>())); // NON-NLS
+ config.setRuleSet(ruleSets);
+ }
+ return config.getRuleSets().get(0);
+ }
+
+ private void updatePanel(String configFilePath, LogicalImagerConfig config, String rowSelectionkey) {
+ configFileTextField.setText(configFilePath);
+ finalizeImageWriter.setSelected(config.isFinalizeImageWriter());
+ LogicalImagerRuleSet ruleSet = getFirstRuleSet();
+ flagEncryptionProgramsCheckBox.setSelected(ruleSet.find(EncryptionProgramsRule.getName()) != null);
+ RulesTableModel rulesTableModel = new RulesTableModel();
+ int row = 0;
+ 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())) {
+ selectThisRow = row;
+ }
+ rulesTableModel.setValueAt(rule.getDescription(), row, 1);
+ rulesTableModel.setValueAt(rule, row, 2);
+ row++;
+ }
+ rulesTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+ rulesTable.setModel(rulesTableModel);
+ // If there are any rules, select the first one
+ if (rulesTableModel.getRowCount() > 0) {
+ rulesTable.setRowSelectionInterval(selectThisRow, selectThisRow);
+ rulesTableSelect();
+ } else {
+ updateRuleSetButtons(false);
+ }
+ }
+
+ private void updatePanel(String configFilePath, LogicalImagerConfig config) {
+ updatePanel(configFilePath, config, null);
+ }
+
+ private void rulesTableSelect() {
+ int index = rulesTable.getSelectedRow();
+ if (index != -1) {
+ String ruleName = (String) rulesTable.getModel().getValueAt(index, 0);
+ String description = (String) rulesTable.getModel().getValueAt(index, 1);
+ updateRuleDetails(ruleName, description, config);
+ updateRuleSetButtons(ruleName.equals(EncryptionProgramsRule.getName()) ? false : true);
+ } else {
+ updateRuleSetButtons(false);
+ }
+ }
+
+ private void updateRuleDetails(String ruleName, String description, LogicalImagerConfig config) {
+ clearRuleDetails();
+ LogicalImagerRule rule = getFirstRuleSet().find(ruleName);
+ shouldAlertCheckBox.setSelected(rule.isShouldAlert());
+ shouldSaveCheckBox.setSelected(rule.isShouldSave());
+ ruleNameEditTextField.setText(ruleName);
+ descriptionEditTextField.setText(description);
+ updateExtensions(rule.getExtensions());
+ updateList(filenamesTable, rule.getFilenames());
+ updateList(folderNamesTable, rule.getPaths());
+ updateList(fullPathsTable, rule.getFullPaths());
+ if (rule.getMinFileSize() == null) {
+ minSizeTextField.setText("");
+ } else {
+ minSizeTextField.setText(rule.getMinFileSize().toString());
+ }
+ if (rule.getMaxFileSize() == null) {
+ maxSizeTextField.setText("");
+ } else {
+ maxSizeTextField.setText(rule.getMaxFileSize().toString());
+ }
+ if (rule.getMinDays() == null) {
+ daysIncludedTextField.setText("");
+ } else {
+ daysIncludedTextField.setText(Integer.toString(rule.getMinDays()));
+ }
+ }
+
+ private void clearRuleDetails() {
+ extensionsTextField.setText("");
+ shouldAlertCheckBox.setSelected(false);
+ shouldSaveCheckBox.setSelected(true);
+ }
+
+ private void updateExtensions(List extensions) {
+ extensionsTextField.setText("");
+ if (extensions == null) {
+ return;
+ }
+ String content = "";
+ boolean first = true;
+ for (String ext : extensions) {
+ content += (first ? "" : ",") + ext;
+ first = false;
+ }
+ extensionsTextField.setText(content);
+ }
+
+ private void updateList(javax.swing.JTable jTable, List set) {
+ SingleColumnTableModel tableModel = new SingleColumnTableModel();
+ jTable.setTableHeader(null);
+ if (set == null) {
+ jTable.setModel(tableModel);
+ return;
+ }
+ int row = 0;
+ for (String s : set) {
+ tableModel.setValueAt(s, row, 0);
+ row++;
+ }
+ jTable.setModel(tableModel);
+ }
+
+ void setConfiguration(String configFilename, LogicalImagerConfig config, boolean newFile) {
+ this.configFilename = configFilename;
+ this.config = config;
+ if (newFile) {
+ initPanel();
+ }
+ updatePanel(configFilename, config);
+ }
+
+ private void initPanel() {
+ configFileTextField.setText("");
+ rulesTable.setModel(new RulesTableModel());
+ shouldAlertCheckBox.setSelected(false);
+ shouldSaveCheckBox.setSelected(true);
+ ruleNameEditTextField.setText("");
+ descriptionEditTextField.setText("");
+ extensionsTextField.setText("");
+ updateList(filenamesTable, EMPTY_LIST);
+ updateList(folderNamesTable, EMPTY_LIST);
+ }
+
+ private void updateRow(int index, ImmutablePair ruleMap) {
+ getFirstRuleSet().getRules().remove(index);
+ getFirstRuleSet().getRules().add(ruleMap.getValue());
+ updatePanel(configFilename, config, ruleMap.getKey());
+ }
+
+ private void appendRow(ImmutablePair ruleMap) {
+ getFirstRuleSet().getRules().add(ruleMap.getValue());
+ updatePanel(configFilename, config, ruleMap.getKey());
+ }
+
+ private void updateRuleSetButtons(boolean isRowSelected) {
+ newRuleButton.setEnabled(true);
+ editRuleButton.setEnabled(isRowSelected);
+ deleteRuleButton.setEnabled(isRowSelected);
+ }
+
+ /**
+ * Sort rule by name
+ */
+ private class SortRuleByName implements Comparator {
+
+ public int compare(LogicalImagerRule a, LogicalImagerRule b) {
+ return a.getName().compareToIgnoreCase(b.getName());
+ }
+ }
+
+ /**
+ * RulesTableModel for rules table
+ */
+ private class RulesTableModel extends AbstractTableModel {
+
+ private final List ruleName = new ArrayList<>();
+ private final List ruleDescription = new ArrayList<>();
+ private final List rule = new ArrayList<>();
+
+ public int findRow(String name) {
+ return ruleName.indexOf(name);
+ }
+
+ @Override
+ public int getRowCount() {
+ return ruleName.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @NbBundle.Messages({
+ "ConfigVisualPanel2.rulesTable.columnModel.title0=Rule Name",
+ "ConfigVisualPanel2.rulesTable.columnModel.title1=Description"
+ })
+ @Override
+ public String getColumnName(int column) {
+ String colName = null;
+ switch (column) {
+ case 0:
+ colName = Bundle.ConfigVisualPanel2_rulesTable_columnModel_title0();
+ break;
+ case 1:
+ colName = Bundle.ConfigVisualPanel2_rulesTable_columnModel_title1();
+ break;
+ default:
+ break;
+ }
+ return colName;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Object ret = null;
+ switch (columnIndex) {
+ case 0:
+ ret = ruleName.get(rowIndex);
+ break;
+ case 1:
+ ret = ruleDescription.get(rowIndex);
+ break;
+ case 2:
+ ret = rule.get(rowIndex);
+ break;
+ default:
+ throw new UnsupportedOperationException("Invalid table column index: " + columnIndex); //NON-NLS
+ }
+ 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:
+ ruleName.add((String) aValue);
+ break;
+ case 1:
+ ruleDescription.add((String) aValue);
+ break;
+ case 2:
+ rule.add((LogicalImagerRule) aValue);
+ break;
+ default:
+ throw new UnsupportedOperationException("Invalid table column index: " + columnIndex); //NON-NLS
+ }
+ // Only show the name and description column
+ if (columnIndex < 2) {
+ super.setValueAt(aValue, rowIndex, columnIndex);
+ }
+ }
+ }
+
+ /**
+ * Table model for single column list table.
+ */
+ private class SingleColumnTableModel extends AbstractTableModel {
+
+ private final List list = new ArrayList<>();
+
+ @Override
+ public int getRowCount() {
+ return list.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 1;
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ return "";
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Object ret = null;
+ if (columnIndex == 0) {
+ ret = list.get(rowIndex);
+ } else {
+ throw new UnsupportedOperationException("Invalid table column index: " + columnIndex); //NON-NLS
+ }
+ return ret;
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return true;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ if (columnIndex == 0) {
+ list.add((String) aValue);
+ } else {
+ throw new UnsupportedOperationException("Invalid table column index: " + columnIndex); //NON-NLS
+ }
+ }
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel1.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel1.java
new file mode 100644
index 0000000000..d7035c3ddd
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel1.java
@@ -0,0 +1,143 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.openide.WizardDescriptor;
+import org.openide.WizardValidationException;
+import org.openide.util.HelpCtx;
+
+/**
+ * Configuration Wizard Panel 1
+ */
+public class ConfigWizardPanel1 implements WizardDescriptor.ValidatingPanel {
+
+ /**
+ * The visual component that displays this panel. If you need to access the
+ * component from this class, just use getComponent().
+ */
+ private ConfigVisualPanel1 component;
+ private boolean valid = false;
+
+ // Get the visual component for the panel. In this template, the component
+ // is kept separate. This can be more efficient: if the wizard is created
+ // but never displayed, or not all panels are displayed, it is better to
+ // create only those which really need to be visible.
+ @Override
+ public ConfigVisualPanel1 getComponent() {
+ if (component == null) {
+ component = new ConfigVisualPanel1();
+ component.addPropertyChangeListener(new PropertyChangeListener() {
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals("UPDATE_UI")) { // NON-NLS
+ valid = component.isPanelValid();
+ fireChangeEvent();
+ }
+ }
+ });
+
+ }
+ return component;
+ }
+
+ @Override
+ public HelpCtx getHelp() {
+ // Show no Help button for this panel:
+ return HelpCtx.DEFAULT_HELP;
+ // If you have context help:
+ // return new HelpCtx("help.key.here");
+ }
+
+ @Override
+ public boolean isValid() {
+ return valid;
+ // If it depends on some condition (form filled out...) and
+ // this condition changes (last form field filled in...) then
+ // use ChangeSupport to implement add/removeChangeListener below.
+ // WizardDescriptor.ERROR/WARNING/INFORMATION_MESSAGE will also be useful.
+ }
+
+ private final Set listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
+
+ /**
+ * Adds a listener to changes of the panel's validity.
+ *
+ * @param l the change listener to add
+ */
+ @Override
+ public final void addChangeListener(ChangeListener l) {
+ synchronized (listeners) {
+ listeners.add(l);
+ }
+ }
+
+ /**
+ * Removes a listener to changes of the panel's validity.
+ *
+ * @param l the change listener to move
+ */
+ @Override
+ public final void removeChangeListener(ChangeListener l) {
+ synchronized (listeners) {
+ listeners.remove(l);
+ }
+ }
+
+ /**
+ * This method is auto-generated. It seems that this method is used to
+ * listen to any change in this wizard panel.
+ */
+ protected final void fireChangeEvent() {
+ Iterator it;
+ synchronized (listeners) {
+ it = new HashSet<>(listeners).iterator();
+ }
+ ChangeEvent ev = new ChangeEvent(this);
+ while (it.hasNext()) {
+ it.next().stateChanged(ev);
+ }
+ }
+
+ @Override
+ public void readSettings(WizardDescriptor wiz) {
+ // use wiz.getProperty to retrieve previous panel state
+ component.setConfigFilename((String) wiz.getProperty("configFilename")); // NON-NLS
+ }
+
+ @Override
+ public void storeSettings(WizardDescriptor wiz) {
+ // use wiz.putProperty to remember current panel state
+ wiz.putProperty("configFilename", component.getConfigFilename()); // NON-NLS
+ wiz.putProperty("config", component.getConfig()); // NON-NLS
+ wiz.putProperty("newFile", component.isNewFile()); // NON-NLS
+ }
+
+ @Override
+ public void validate() throws WizardValidationException {
+ valid = component.isPanelValid();
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel2.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel2.java
new file mode 100644
index 0000000000..10865bb8cc
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel2.java
@@ -0,0 +1,149 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonIOException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Level;
+import javax.swing.JOptionPane;
+import javax.swing.event.ChangeListener;
+import org.apache.commons.io.FileUtils;
+import org.openide.WizardDescriptor;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.coreutils.Logger;
+
+/**
+ * Configuration Wizard Panel 2
+ */
+public class ConfigWizardPanel2 implements WizardDescriptor.Panel {
+
+ private static final Logger LOGGER = Logger.getLogger(ConfigWizardPanel2.class.getName());
+
+ /**
+ * The visual component that displays this panel. If you need to access the
+ * component from this class, just use getComponent().
+ */
+ private ConfigVisualPanel2 component;
+ private String configFilename;
+ private LogicalImagerConfig config;
+
+ // Get the visual component for the panel. In this template, the component
+ // is kept separate. This can be more efficient: if the wizard is created
+ // but never displayed, or not all panels are displayed, it is better to
+ // create only those which really need to be visible.
+ @Override
+ public ConfigVisualPanel2 getComponent() {
+ if (component == null) {
+ component = new ConfigVisualPanel2();
+ }
+ return component;
+ }
+
+ @Override
+ public HelpCtx getHelp() {
+ // Show no Help button for this panel:
+ return HelpCtx.DEFAULT_HELP;
+ // If you have context help:
+ // return new HelpCtx("help.key.here");
+ }
+
+ @Override
+ public boolean isValid() {
+ // If it is always OK to press Next or Finish, then:
+ return true;
+ // If it depends on some condition (form filled out...) and
+ // this condition changes (last form field filled in...) then
+ // use ChangeSupport to implement add/removeChangeListener below.
+ // WizardDescriptor.ERROR/WARNING/INFORMATION_MESSAGE will also be useful.
+ }
+
+ @Override
+ public void readSettings(WizardDescriptor wiz) {
+ // use wiz.getProperty to retrieve previous panel state
+ configFilename = (String) wiz.getProperty("configFilename"); // NON-NLS
+ config = (LogicalImagerConfig) wiz.getProperty("config"); // NON-NLS
+ component.setConfiguration(configFilename, config, (boolean) wiz.getProperty("newFile"));
+ }
+
+ @Override
+ public void storeSettings(WizardDescriptor wiz) {
+ // use wiz.putProperty to remember current panel state
+ }
+
+ @NbBundle.Messages({
+ "# {0} - configFilename",
+ "ConfigWizardPanel2.failedToSaveConfigMsg=Failed to save configuration file: {0}",
+ "# {0} - reason",
+ "ConfigWizardPanel2.reason=\nReason: ",
+ "ConfigWizardPanel2.failedToSaveExeMsg=Failed to save tsk_logical_imager.exe file",
+ })
+ public void saveConfigFile() {
+ GsonBuilder gsonBuilder = new GsonBuilder()
+ .setPrettyPrinting()
+ .excludeFieldsWithoutExposeAnnotation()
+ .disableHtmlEscaping();
+ Gson gson = gsonBuilder.create();
+ String toJson = gson.toJson(config);
+ try {
+ List lines = Arrays.asList(toJson.split("\\n"));
+ FileUtils.writeLines(new File(configFilename), "UTF-8", lines, System.getProperty("line.separator")); // NON-NLS
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(component, Bundle.ConfigWizardPanel2_failedToSaveConfigMsg(configFilename)
+ + Bundle.ConfigWizardPanel2_reason(ex.getMessage()));
+ } catch (JsonIOException jioe) {
+ LOGGER.log(Level.SEVERE, "Failed to save configuration file: " + configFilename, jioe); // NON-NLS
+ JOptionPane.showMessageDialog(component, Bundle.ConfigWizardPanel2_failedToSaveConfigMsg(configFilename)
+ + Bundle.ConfigWizardPanel2_reason(jioe.getMessage()));
+ }
+ try {
+ writeTskLogicalImagerExe(Paths.get(configFilename).getParent());
+ } catch (IOException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to save tsk_logical_imager.exe file", ex); // NON-NLS
+ JOptionPane.showMessageDialog(component, Bundle.ConfigWizardPanel2_failedToSaveExeMsg()
+ + Bundle.ConfigWizardPanel2_reason(ex.getMessage()));
+ }
+ }
+
+ private void writeTskLogicalImagerExe(Path destDir) throws IOException {
+ try (InputStream in = getClass().getResourceAsStream("tsk_logical_imager.exe")) { // NON-NLS
+ File destFile = Paths.get(destDir.toString(), "tsk_logical_imager.exe").toFile(); // NON-NLS
+ FileUtils.copyInputStreamToFile(in, destFile);
+ }
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener cl) {
+ // Not used
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener cl) {
+ // Not used
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigureLogicalImager.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigureLogicalImager.java
new file mode 100644
index 0000000000..dff2c48e95
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigureLogicalImager.java
@@ -0,0 +1,83 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JComponent;
+import org.openide.DialogDisplayer;
+import org.openide.WizardDescriptor;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
+
+/**
+ * Configuration Logical Imager
+ */
+
+@ActionID(
+ category = "Tools",
+ id = "org.sleuthkit.autopsy.configurelogicalimager.ConfigureLogicalImager"
+)
+@ActionRegistration(
+ displayName = "#CTL_ConfigureLogicalImager"
+)
+@ActionReference(path = "Menu/Tools", position = 2000, separatorBefore = 1999)
+@Messages("CTL_ConfigureLogicalImager=Configure Logical Imager")
+public final class ConfigureLogicalImager implements ActionListener {
+
+ @NbBundle.Messages({
+ "ConfigureLogicalImager.title=Configure Logical Imager"
+ })
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ List> panels = new ArrayList<>();
+ panels.add(new ConfigWizardPanel1());
+ panels.add(new ConfigWizardPanel2());
+ String[] steps = new String[panels.size()];
+ for (int i = 0; i < panels.size(); i++) {
+ Component c = panels.get(i).getComponent();
+ // Default step name to component name of panel.
+ steps[i] = c.getName();
+ if (c instanceof JComponent) { // assume Swing components
+ JComponent jc = (JComponent) c;
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
+ jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
+ }
+ }
+ WizardDescriptor wiz = new WizardDescriptor(new WizardDescriptor.ArrayIterator<>(panels));
+ // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
+ wiz.setTitleFormat(new MessageFormat("{0}")); // NON-NLS
+ wiz.setTitle(Bundle.ConfigureLogicalImager_title());
+ if ((DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) &&
+ (panels.get(1) instanceof ConfigWizardPanel2)) {
+ ConfigWizardPanel2 panel = (ConfigWizardPanel2) panels.get(1);
+ panel.saveConfigFile();
+ }
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.form b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.form
new file mode 100644
index 0000000000..6a5ebc9e77
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.form
@@ -0,0 +1,134 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.java
new file mode 100644
index 0000000000..3210028f53
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.java
@@ -0,0 +1,260 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.util.List;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openide.util.NbBundle;
+
+/**
+ * Edit full paths rule panel
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+public class EditFullPathsRulePanel extends javax.swing.JPanel {
+
+ private JButton okButton;
+ private JButton cancelButton;
+ private final JTextArea fullPathsTextArea;
+
+ /**
+ * Creates new form EditFullPathsRulePanel
+ */
+ @NbBundle.Messages({
+ "EditFullPathsRulePanel.example=Example: "
+ })
+ public EditFullPathsRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule, boolean editing) {
+ initComponents();
+
+ if (editing) {
+ ruleNameTextField.setEnabled(!editing);
+ }
+
+ this.setRule(ruleName, rule);
+ this.setButtons(okButton, cancelButton);
+
+ fullPathsTextArea = new JTextArea();
+ initTextArea(fullPathsScrollPane, fullPathsTextArea);
+ setTextArea(fullPathsTextArea, rule.getFullPaths());
+
+ EditRulePanel.setTextFieldPrompts(fullPathsTextArea,
+ "" + Bundle.EditFullPathsRulePanel_example() + "
/Program Files/Common Files/system/wab32.dll
/Windows/System32/1033/VsGraphicsResources.dll"); // NON-NLS
+ ruleNameTextField.requestFocus();
+ validate();
+ repaint();
+ }
+
+ private void initTextArea(JScrollPane pane, JTextArea textArea) {
+ textArea.setColumns(20);
+ textArea.setRows(5);
+ pane.setViewportView(textArea);
+ textArea.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_TAB) {
+ if (e.getModifiers() > 0) {
+ textArea.transferFocusBackward();
+ } else {
+ textArea.transferFocus();
+ }
+ e.consume();
+ }
+ }
+ });
+ }
+
+ /**
+ * 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
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ shouldSaveCheckBox = new javax.swing.JCheckBox();
+ shouldAlertCheckBox = new javax.swing.JCheckBox();
+ fullPathsLabel = new javax.swing.JLabel();
+ descriptionTextField = new javax.swing.JTextField();
+ descriptionLabel = new javax.swing.JLabel();
+ ruleNameLabel = new javax.swing.JLabel();
+ ruleNameTextField = new javax.swing.JTextField();
+ fullPathsScrollPane = new javax.swing.JScrollPane();
+
+ shouldSaveCheckBox.setSelected(true);
+ org.openide.awt.Mnemonics.setLocalizedText(shouldSaveCheckBox, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.shouldSaveCheckBox.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(shouldAlertCheckBox, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.shouldAlertCheckBox.text")); // NOI18N
+ shouldAlertCheckBox.setActionCommand(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.shouldAlertCheckBox.actionCommand")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(fullPathsLabel, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.fullPathsLabel.text")); // NOI18N
+ fullPathsLabel.setToolTipText(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.fullPathsLabel.toolTipText")); // NOI18N
+
+ descriptionTextField.setText(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.descriptionTextField.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.descriptionLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.ruleNameLabel.text")); // NOI18N
+
+ ruleNameTextField.setText(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.ruleNameTextField.text")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(shouldSaveCheckBox)
+ .addComponent(shouldAlertCheckBox)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(ruleNameLabel)
+ .addComponent(descriptionLabel)
+ .addComponent(fullPathsLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(ruleNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 519, Short.MAX_VALUE)
+ .addComponent(descriptionTextField)
+ .addComponent(fullPathsScrollPane))))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(ruleNameLabel)
+ .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(descriptionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(descriptionLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(fullPathsLabel)
+ .addGap(0, 167, Short.MAX_VALUE))
+ .addComponent(fullPathsScrollPane))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(shouldAlertCheckBox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(shouldSaveCheckBox)
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel descriptionLabel;
+ private javax.swing.JTextField descriptionTextField;
+ private javax.swing.JLabel fullPathsLabel;
+ private javax.swing.JScrollPane fullPathsScrollPane;
+ private javax.swing.JLabel ruleNameLabel;
+ private javax.swing.JTextField ruleNameTextField;
+ private javax.swing.JCheckBox shouldAlertCheckBox;
+ private javax.swing.JCheckBox shouldSaveCheckBox;
+ // End of variables declaration//GEN-END:variables
+
+ /**
+ * Sets whether or not the OK button should be enabled based upon other UI
+ * elements
+ */
+ private void setOkButton() {
+ if (this.okButton != null) {
+ this.okButton.setEnabled(true);
+ }
+ }
+
+ /**
+ * Gets the JOptionPane that is used to contain this panel if there is one
+ *
+ * @param parent
+ *
+ * @return
+ */
+ private JOptionPane getOptionPane(JComponent parent) {
+ JOptionPane pane;
+ if (!(parent instanceof JOptionPane)) {
+ pane = getOptionPane((JComponent) parent.getParent());
+ } else {
+ pane = (JOptionPane) parent;
+ }
+ return pane;
+ }
+
+ /**
+ * Sets the buttons for ending the panel
+ *
+ * @param ok The ok button
+ * @param cancel The cancel button
+ */
+ private void setButtons(JButton ok, JButton cancel) {
+ this.okButton = ok;
+ this.cancelButton = cancel;
+ okButton.addActionListener((ActionEvent e) -> {
+ JOptionPane pane = getOptionPane(okButton);
+ pane.setValue(okButton);
+ });
+ cancelButton.addActionListener((ActionEvent e) -> {
+ JOptionPane pane = getOptionPane(cancelButton);
+ pane.setValue(cancelButton);
+ });
+ this.setOkButton();
+ }
+
+ private void setRule(String ruleName, LogicalImagerRule rule) {
+ ruleNameTextField.setText(ruleName);
+ descriptionTextField.setText(rule.getDescription());
+ shouldAlertCheckBox.setSelected(rule.isShouldAlert());
+ shouldSaveCheckBox.setSelected(rule.isShouldSave());
+ }
+
+ private void setTextArea(JTextArea textArea, List set) {
+ String text = "";
+ for (String s : set) {
+ text += s + System.getProperty("line.separator"); // NON-NLS
+ }
+ textArea.setText(text);
+ }
+
+ @NbBundle.Messages({
+ "EditFullPathsRulePanel.fullPaths=Full paths",
+ })
+ public ImmutablePair toRule() throws IOException {
+ List fullPaths = EditRulePanel.validateTextList(fullPathsTextArea, Bundle.EditFullPathsRulePanel_fullPaths());
+ String ruleName = EditRulePanel.validRuleName(ruleNameTextField.getText());
+ LogicalImagerRule.Builder builder = new LogicalImagerRule.Builder();
+ builder.getShouldAlert(shouldAlertCheckBox.isSelected())
+ .getShouldSave(shouldSaveCheckBox.isSelected())
+ .getName(ruleName)
+ .getDescription(descriptionTextField.getText())
+ .getFullPaths(fullPaths);
+ LogicalImagerRule rule = builder.build();
+ return new ImmutablePair<>(ruleName, rule);
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.form b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.form
new file mode 100644
index 0000000000..d272445de0
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.form
@@ -0,0 +1,322 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.java
new file mode 100644
index 0000000000..e1db95494c
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.java
@@ -0,0 +1,546 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.strip;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openide.util.NbBundle;
+
+/**
+ * Edit non-full paths rule panel
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+public class EditNonFullPathsRulePanel extends javax.swing.JPanel {
+
+ private JButton okButton;
+ private JButton cancelButton;
+ private final javax.swing.JTextArea filenamesTextArea;
+ private final javax.swing.JTextArea folderNamesTextArea;
+
+ /**
+ * Creates new form EditRulePanel
+ */
+ @NbBundle.Messages({
+ "EditNonFullPathsRulePanel.example=Example: ",
+ "EditNonFullPathsRulePanel.note=NOTE: A special [USER_FOLDER] token at the the start of a folder name to allow matches of all user folders in the file system."
+ })
+ EditNonFullPathsRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule, boolean editing) {
+ initComponents();
+
+ if (editing) {
+ ruleNameTextField.setEnabled(!editing);
+ }
+
+ this.setRule(ruleName, rule);
+ this.setButtons(okButton, cancelButton);
+
+ setExtensions(rule.getExtensions());
+
+ filenamesTextArea = new JTextArea();
+ initTextArea(filenamesScrollPane, filenamesTextArea);
+ setTextArea(filenamesTextArea, rule.getFilenames());
+
+ if (rule.getExtensions() == null) {
+ extensionsRadioButton.setSelected(false);
+ filenamesRadioButton.setSelected(true);
+ } else {
+ extensionsRadioButton.setSelected(true);
+ filenamesRadioButton.setSelected(false);
+ }
+
+ folderNamesTextArea = new JTextArea();
+ initTextArea(folderNamesScrollPane, folderNamesTextArea);
+ setTextArea(folderNamesTextArea, rule.getPaths());
+
+ setMinDays(rule.getMinDays());
+
+ minSizeTextField.setText(rule.getMinFileSize() == null ? "" : rule.getMinFileSize().toString());
+ maxSizeTextField.setText(rule.getMaxFileSize() == null ? "" : rule.getMaxFileSize().toString());
+ ruleNameTextField.requestFocus();
+
+ EditRulePanel.setTextFieldPrompts(extensionsTextField, Bundle.EditNonFullPathsRulePanel_example() + "gif,jpg,png"); // NON-NLS
+ EditRulePanel.setTextFieldPrompts(filenamesTextArea, ""
+ + Bundle.EditNonFullPathsRulePanel_example()
+ + "
filename.txt
readme.txt"); // NON-NLS
+ EditRulePanel.setTextFieldPrompts(folderNamesTextArea, ""
+ + Bundle.EditNonFullPathsRulePanel_example()
+ + "
[USER_FOLDER]/My Documents/Downloads"
+ + "
/Program Files/Common Files"
+ + "
"
+ + Bundle.EditNonFullPathsRulePanel_note()
+ + ""); // NON-NLS
+ validate();
+ repaint();
+ }
+
+ private void initTextArea(JScrollPane pane, JTextArea textArea) {
+ textArea.setColumns(20);
+ textArea.setRows(5);
+ pane.setViewportView(textArea);
+ textArea.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_TAB) {
+ if (e.getModifiers() > 0) {
+ textArea.transferFocusBackward();
+ } else {
+ textArea.transferFocus();
+ }
+ e.consume();
+ }
+ }
+ });
+ }
+
+ private void setMinDays(Integer minDays) {
+ minDaysTextField.setText(minDays == null ? "" : minDays.toString());
+ }
+
+ private void setTextArea(JTextArea textArea, List set) {
+ String text = "";
+ if (set != null) {
+ for (String s : set) {
+ text += s + System.getProperty("line.separator"); // NON-NLS
+ }
+ }
+ textArea.setText(text);
+ }
+
+ private void setExtensions(List extensions) {
+ extensionsTextField.setText("");
+ String content = "";
+ if (extensions != null) {
+ boolean first = true;
+ for (String ext : extensions) {
+ content += (first ? "" : ",") + ext;
+ first = false;
+ }
+ }
+ extensionsTextField.setText(content);
+ }
+ /**
+ * 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
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ buttonGroup = new javax.swing.ButtonGroup();
+ modifiedDateLabel = new javax.swing.JLabel();
+ daysIncludedLabel = new javax.swing.JLabel();
+ shouldSaveCheckBox = new javax.swing.JCheckBox();
+ shouldAlertCheckBox = new javax.swing.JCheckBox();
+ extensionsLabel = new javax.swing.JLabel();
+ extensionsTextField = new javax.swing.JTextField();
+ filenamesLabel = new javax.swing.JLabel();
+ folderNamesLabel = new javax.swing.JLabel();
+ fileSizeLabel = new javax.swing.JLabel();
+ descriptionTextField = new javax.swing.JTextField();
+ descriptionLabel = new javax.swing.JLabel();
+ ruleNameLabel = new javax.swing.JLabel();
+ ruleNameTextField = new javax.swing.JTextField();
+ filenamesScrollPane = new javax.swing.JScrollPane();
+ folderNamesScrollPane = new javax.swing.JScrollPane();
+ minSizeLabel = new javax.swing.JLabel();
+ minSizeTextField = new javax.swing.JFormattedTextField();
+ maxSizeLabel = new javax.swing.JLabel();
+ maxSizeTextField = new javax.swing.JFormattedTextField();
+ minDaysTextField = new javax.swing.JFormattedTextField();
+ extensionsRadioButton = new javax.swing.JRadioButton();
+ filenamesRadioButton = new javax.swing.JRadioButton();
+
+ org.openide.awt.Mnemonics.setLocalizedText(modifiedDateLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.modifiedDateLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(daysIncludedLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.daysIncludedLabel.text")); // NOI18N
+
+ shouldSaveCheckBox.setSelected(true);
+ org.openide.awt.Mnemonics.setLocalizedText(shouldSaveCheckBox, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.shouldSaveCheckBox.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(shouldAlertCheckBox, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.shouldAlertCheckBox.text")); // NOI18N
+ shouldAlertCheckBox.setActionCommand(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.shouldAlertCheckBox.actionCommand")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(extensionsLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.extensionsLabel.text")); // NOI18N
+
+ extensionsTextField.setText(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.extensionsTextField.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(filenamesLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.filenamesLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(folderNamesLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.folderNamesLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(fileSizeLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.fileSizeLabel.text")); // NOI18N
+
+ descriptionTextField.setText(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.descriptionTextField.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.descriptionLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.ruleNameLabel.text")); // NOI18N
+
+ ruleNameTextField.setText(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.ruleNameTextField.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(minSizeLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.minSizeLabel.text")); // NOI18N
+
+ minSizeTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#,###; "))));
+ minSizeTextField.setText(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.minSizeTextField.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(maxSizeLabel, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.maxSizeLabel.text")); // NOI18N
+
+ maxSizeTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#,###; "))));
+ maxSizeTextField.setText(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.maxSizeTextField.text")); // NOI18N
+
+ minDaysTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("####; "))));
+
+ buttonGroup.add(extensionsRadioButton);
+ extensionsRadioButton.setSelected(true);
+ org.openide.awt.Mnemonics.setLocalizedText(extensionsRadioButton, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.extensionsRadioButton.text")); // NOI18N
+ extensionsRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.extensionsRadioButton.toolTipText")); // NOI18N
+ extensionsRadioButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ extensionsRadioButtonActionPerformed(evt);
+ }
+ });
+
+ buttonGroup.add(filenamesRadioButton);
+ org.openide.awt.Mnemonics.setLocalizedText(filenamesRadioButton, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.filenamesRadioButton.text")); // NOI18N
+ filenamesRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.filenamesRadioButton.toolTipText")); // NOI18N
+ filenamesRadioButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ filenamesRadioButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(extensionsRadioButton)
+ .addComponent(filenamesRadioButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(ruleNameLabel)
+ .addComponent(descriptionLabel)
+ .addComponent(extensionsLabel)
+ .addComponent(filenamesLabel)
+ .addComponent(folderNamesLabel)
+ .addComponent(fileSizeLabel)
+ .addComponent(modifiedDateLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(folderNamesScrollPane, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(filenamesScrollPane, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(extensionsTextField, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(descriptionTextField, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(ruleNameTextField, javax.swing.GroupLayout.Alignment.TRAILING)))
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(23, 23, 23)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(shouldSaveCheckBox)
+ .addComponent(shouldAlertCheckBox)))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(108, 108, 108)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(minDaysTextField)
+ .addComponent(minSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(minSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addComponent(maxSizeLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(maxSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(daysIncludedLabel))))
+ .addGap(0, 236, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(ruleNameLabel)
+ .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(descriptionLabel)
+ .addComponent(descriptionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(extensionsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(extensionsLabel)
+ .addComponent(extensionsRadioButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(filenamesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 70, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(filenamesLabel)
+ .addComponent(filenamesRadioButton))
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(folderNamesLabel)
+ .addComponent(folderNamesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 71, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(fileSizeLabel)
+ .addComponent(minSizeLabel)
+ .addComponent(minSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(maxSizeLabel)
+ .addComponent(maxSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(6, 6, 6)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(modifiedDateLabel)
+ .addComponent(daysIncludedLabel)
+ .addComponent(minDaysTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(14, 14, 14)
+ .addComponent(shouldAlertCheckBox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(shouldSaveCheckBox)
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+ private void extensionsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_extensionsRadioButtonActionPerformed
+ filenamesTextArea.setEnabled(false);
+ filenamesTextArea.setForeground(Color.LIGHT_GRAY);
+ extensionsTextField.setEnabled(true);
+ extensionsTextField.setForeground(Color.BLACK);
+ }//GEN-LAST:event_extensionsRadioButtonActionPerformed
+
+ private void filenamesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filenamesRadioButtonActionPerformed
+ filenamesTextArea.setEnabled(true);
+ filenamesTextArea.setForeground(Color.BLACK);
+ extensionsTextField.setEnabled(false);
+ extensionsTextField.setForeground(Color.LIGHT_GRAY);
+ }//GEN-LAST:event_filenamesRadioButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.ButtonGroup buttonGroup;
+ private javax.swing.JLabel daysIncludedLabel;
+ private javax.swing.JLabel descriptionLabel;
+ private javax.swing.JTextField descriptionTextField;
+ private javax.swing.JLabel extensionsLabel;
+ private javax.swing.JRadioButton extensionsRadioButton;
+ private javax.swing.JTextField extensionsTextField;
+ private javax.swing.JLabel fileSizeLabel;
+ private javax.swing.JLabel filenamesLabel;
+ private javax.swing.JRadioButton filenamesRadioButton;
+ private javax.swing.JScrollPane filenamesScrollPane;
+ private javax.swing.JLabel folderNamesLabel;
+ private javax.swing.JScrollPane folderNamesScrollPane;
+ private javax.swing.JLabel maxSizeLabel;
+ private javax.swing.JFormattedTextField maxSizeTextField;
+ private javax.swing.JFormattedTextField minDaysTextField;
+ private javax.swing.JLabel minSizeLabel;
+ private javax.swing.JFormattedTextField minSizeTextField;
+ private javax.swing.JLabel modifiedDateLabel;
+ private javax.swing.JLabel ruleNameLabel;
+ private javax.swing.JTextField ruleNameTextField;
+ private javax.swing.JCheckBox shouldAlertCheckBox;
+ private javax.swing.JCheckBox shouldSaveCheckBox;
+ // End of variables declaration//GEN-END:variables
+
+ private void setRule(String ruleName, LogicalImagerRule rule) {
+ ruleNameTextField.setText(ruleName);
+ descriptionTextField.setText(rule.getDescription());
+ shouldAlertCheckBox.setSelected(rule.isShouldAlert());
+ shouldSaveCheckBox.setSelected(rule.isShouldSave());
+ }
+
+ /**
+ * Sets whether or not the OK button should be enabled based upon other UI
+ * elements
+ */
+ private void setOkButton() {
+ if (this.okButton != null) {
+ this.okButton.setEnabled(true);
+ }
+ }
+
+ /**
+ * Gets the JOptionPane that is used to contain this panel if there is one
+ *
+ * @param parent
+ *
+ * @return
+ */
+ private JOptionPane getOptionPane(JComponent parent) {
+ JOptionPane pane;
+ if (!(parent instanceof JOptionPane)) {
+ pane = getOptionPane((JComponent) parent.getParent());
+ } else {
+ pane = (JOptionPane) parent;
+ }
+ return pane;
+ }
+
+ /**
+ * Sets the buttons for ending the panel
+ *
+ * @param ok The ok button
+ * @param cancel The cancel button
+ */
+ private void setButtons(JButton ok, JButton cancel) {
+ this.okButton = ok;
+ this.cancelButton = cancel;
+ okButton.addActionListener((ActionEvent e) -> {
+ JOptionPane pane = getOptionPane(okButton);
+ pane.setValue(okButton);
+ });
+ cancelButton.addActionListener((ActionEvent e) -> {
+ JOptionPane pane = getOptionPane(cancelButton);
+ pane.setValue(cancelButton);
+ });
+ this.setOkButton();
+ }
+
+ @NbBundle.Messages({
+ "EditNonFullPathsRulePanel.modifiedDaysNotPositiveException=Modified days must be a positive",
+ "# {0} - message",
+ "EditNonFullPathsRulePanel.modifiedDaysMustBeNumberException=Modified days must be a number: {0}",
+ "EditNonFullPathsRulePanel.minFileSizeNotPositiveException=Minimum file size must be a positive",
+ "# {0} - message",
+ "EditNonFullPathsRulePanel.minFileSizeMustBeNumberException=Minimum file size must be a number: {0}",
+ "EditNonFullPathsRulePanel.maxFileSizeNotPositiveException=Maximum file size must be a positive",
+ "# {0} - message",
+ "EditNonFullPathsRulePanel.maxFileSizeMustBeNumberException=Maximum file size must be a number: {0}",
+ "# {0} - maxFileSize",
+ "# {1} - minFileSize",
+ "EditNonFullPathsRulePanel.maxFileSizeSmallerThanMinException=Maximum file size: {0} must be bigger than minimum file size: {1}",
+ "EditNonFullPathsRulePanel.fileNames=File names",
+ "EditNonFullPathsRulePanel.folderNames=Folder names",
+ })
+ ImmutablePair toRule() throws IOException {
+ String ruleName = EditRulePanel.validRuleName(ruleNameTextField.getText());
+ List extensions = validateExtensions(extensionsTextField);
+ List filenames = EditRulePanel.validateTextList(filenamesTextArea, Bundle.EditNonFullPathsRulePanel_fileNames());
+ List folderNames = EditRulePanel.validateTextList(folderNamesTextArea, Bundle.EditNonFullPathsRulePanel_folderNames());
+
+ LogicalImagerRule.Builder builder = new LogicalImagerRule.Builder();
+ builder.getName(ruleName)
+ .getDescription(descriptionTextField.getText())
+ .getShouldAlert(shouldAlertCheckBox.isSelected())
+ .getShouldSave(shouldSaveCheckBox.isSelected())
+ .getPaths(folderNames);
+
+ if (extensionsRadioButton.isSelected()) {
+ builder.getExtensions(extensions);
+ } else {
+ builder.getFilenames(filenames);
+ }
+
+ int minDays;
+ if (!isBlank(minDaysTextField.getText())) {
+ try {
+ minDaysTextField.commitEdit();
+ minDays = ((Number)minDaysTextField.getValue()).intValue();
+ if (minDays < 0) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_modifiedDaysNotPositiveException());
+ }
+ builder.getMinDays(minDays);
+ } catch (NumberFormatException | ParseException ex) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_modifiedDaysMustBeNumberException(ex.getMessage()), ex);
+ }
+ }
+
+ int minFileSize = 0;
+ if (!isBlank(minSizeTextField.getText())) {
+ try {
+ minSizeTextField.commitEdit();
+ minFileSize = ((Number)minSizeTextField.getValue()).intValue();
+ if (minFileSize < 0) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_minFileSizeNotPositiveException());
+ }
+ } catch (NumberFormatException | ParseException ex) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_minFileSizeMustBeNumberException(ex.getMessage()), ex);
+ }
+ }
+
+ int maxFileSize = 0;
+ if (!isBlank(maxSizeTextField.getText())) {
+ try {
+ maxSizeTextField.commitEdit();
+ maxFileSize = ((Number)maxSizeTextField.getValue()).intValue();
+ if (maxFileSize < 0) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_maxFileSizeNotPositiveException());
+ }
+ } catch (NumberFormatException | ParseException ex) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_maxFileSizeMustBeNumberException(ex.getMessage()), ex);
+ }
+ }
+
+ if (maxFileSize != 0 && (maxFileSize < minFileSize)) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_maxFileSizeSmallerThanMinException(maxFileSize, minFileSize));
+ }
+ if (minFileSize != 0) {
+ builder.getMinFileSize(minFileSize);
+ }
+ if (maxFileSize != 0) {
+ builder.getMaxFileSize(maxFileSize);
+ }
+
+ LogicalImagerRule rule = builder.build();
+ return new ImmutablePair<>(ruleName, rule);
+ }
+
+ @NbBundle.Messages({
+ "EditNonFullPathsRulePanel.emptyExtensionException=Extensions cannot have an empty entry",
+ })
+ private List validateExtensions(JTextField textField) throws IOException {
+ if (isBlank(textField.getText())) {
+ return null;
+ }
+ List extensions = new ArrayList<>();
+ for (String extension : textField.getText().split(",")) {
+ extension = strip(extension);
+ if (extension.isEmpty()) {
+ throw new IOException(Bundle.EditNonFullPathsRulePanel_emptyExtensionException());
+ }
+ extensions.add(extension);
+ }
+ if (extensions.isEmpty()) {
+ return null;
+ }
+ return extensions;
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditRulePanel.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditRulePanel.java
new file mode 100644
index 0000000000..f969d9236d
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditRulePanel.java
@@ -0,0 +1,123 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.text.JTextComponent;
+import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.strip;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.corecomponents.TextPrompt;
+
+/**
+ * Edit rule panel
+ */
+public class EditRulePanel extends JPanel {
+
+ private EditFullPathsRulePanel editFullPathsRulePanel = null;
+ private EditNonFullPathsRulePanel editNonFullPathsRulePanel = null;
+
+ /**
+ * Creates new form EditRulePanel
+ */
+ public EditRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule) {
+ if (rule.getFullPaths() != null && rule.getFullPaths().size() > 0) {
+ editFullPathsRulePanel = new EditFullPathsRulePanel(okButton, cancelButton, ruleName, rule, true);
+ } else {
+ editNonFullPathsRulePanel = new EditNonFullPathsRulePanel(okButton, cancelButton, ruleName, rule, true);
+ }
+ }
+
+ JPanel getPanel() {
+ if (editFullPathsRulePanel != null) {
+ return editFullPathsRulePanel;
+ } else {
+ return editNonFullPathsRulePanel;
+ }
+ }
+
+ ImmutablePair toRule() throws IOException, NumberFormatException {
+ ImmutablePair ruleMap;
+ if (editFullPathsRulePanel != null) {
+ ruleMap = editFullPathsRulePanel.toRule();
+ } else {
+ ruleMap = editNonFullPathsRulePanel.toRule();
+ }
+ return ruleMap;
+ }
+
+ static void setTextFieldPrompts(JTextComponent textField, String text) {
+ /**
+ * Add text prompt to the text field.
+ */
+ TextPrompt textPrompt;
+ if (textField instanceof JTextArea) {
+ textPrompt = new TextPrompt(text, textField, BorderLayout.NORTH);
+ } else {
+ textPrompt = new TextPrompt(text, textField);
+ }
+
+ /**
+ * Sets the foreground color and transparency of the text prompt.
+ */
+ textPrompt.setForeground(Color.LIGHT_GRAY);
+ textPrompt.changeAlpha(0.9f); // Mostly opaque
+ }
+
+ @NbBundle.Messages({
+ "EditRulePanel.validateRuleNameExceptionMsg=Rule name cannot be empty"
+ })
+ static public String validRuleName(String name) throws IOException {
+ if (name.isEmpty()) {
+ throw new IOException(Bundle.EditRulePanel_validateRuleNameExceptionMsg());
+ }
+ return name;
+ }
+
+ @NbBundle.Messages({
+ "# {0} - fieldName",
+ "EditRulePanel.blankLineException={0} cannot have a blank line",
+ })
+ static public List validateTextList(JTextArea textArea, String fieldName) throws IOException {
+ if (isBlank(textArea.getText())) {
+ return null;
+ }
+ List list = new ArrayList<>();
+ for (String line : textArea.getText().split("\\n")) { // NON-NLS
+ line = strip(line);
+ if (line.isEmpty()) {
+ throw new IOException(Bundle.EditRulePanel_blankLineException(fieldName));
+ }
+ list.add(line);
+ }
+ if (list.isEmpty()) {
+ return null;
+ }
+ return list;
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EncryptionProgramsRule.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EncryptionProgramsRule.java
new file mode 100644
index 0000000000..954adbc785
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EncryptionProgramsRule.java
@@ -0,0 +1,94 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.openide.util.NbBundle;
+
+/**
+ * Encryption programs rule
+ */
+@NbBundle.Messages({
+ "EncryptionProgramsRule.encryptionProgramsRuleName=Encryption Programs",
+ "EncryptionProgramsRule.encryptionProgramsRuleDescription=Find encryption programs"
+})
+public final class EncryptionProgramsRule {
+
+ private static final String ENCRYPTION_PROGRAMS_RULE_NAME = Bundle.EncryptionProgramsRule_encryptionProgramsRuleName();
+ private static final String ENCRYPTION_PROGRAMS_RULE_DESCRIPTION = Bundle.EncryptionProgramsRule_encryptionProgramsRuleDescription();
+ private static final List FILENAMES = new ArrayList<>();
+
+ private EncryptionProgramsRule() {}
+
+ // TODO: Add more files here
+ static {
+ // Truecrypt
+ FILENAMES.add("truecrypt.exe"); // NON-NLS
+
+ // AxCrypt
+ FILENAMES.add("AxCrypt.exe"); // NON-NLS
+
+ // VeraCrypt
+ FILENAMES.add("VeraCrypt.exe"); // NON-NLS
+ FILENAMES.add("VeraCrypt Format.exe"); // NON-NLS
+ FILENAMES.add("VeraCrypt Setup.exe"); // NON-NLS
+ FILENAMES.add("VeraCryptExpander.exe"); // NON-NLS
+
+ // GnuPG
+ FILENAMES.add("gpg-agent.exe"); // NON-NLS
+ FILENAMES.add("gpg-connect-agent.exe"); // NON-NLS
+ FILENAMES.add("gpg-preset-passphrase.exe"); // NON-NLS
+ FILENAMES.add("gpg-wks-client.exe"); // NON-NLS
+ FILENAMES.add("gpg.exe"); // NON-NLS
+ FILENAMES.add("gpgconf.exe"); // NON-NLS
+ FILENAMES.add("gpgme-w32spawn.exe"); // NON-NLS
+ FILENAMES.add("gpgsm.exe"); // NON-NLS
+ FILENAMES.add("gpgtar.exe"); // NON-NLS
+ FILENAMES.add("gpgv.exe"); // NON-NLS
+
+ // Symantec Encryption Desktop aka PGP
+ FILENAMES.add("PGP Viewer.exe"); // NON-NLS
+ FILENAMES.add("PGPcbt64.exe"); // NON-NLS
+ FILENAMES.add("PGPdesk.exe"); // NON-NLS
+ FILENAMES.add("PGPfsd.exe"); // NON-NLS
+ FILENAMES.add("PGPmnApp.exe"); // NON-NLS
+ FILENAMES.add("pgpnetshare.exe"); // NON-NLS
+ FILENAMES.add("pgpp.exe"); // NON-NLS
+ FILENAMES.add("PGPpdCreate.exe"); // NON-NLS
+ FILENAMES.add("pgppe.exe"); // NON-NLS
+ FILENAMES.add("pgpstart.exe"); // NON-NLS
+ FILENAMES.add("PGPtray.exe"); // NON-NLS
+ FILENAMES.add("PGPwde.exe"); // NON-NLS
+ FILENAMES.add("PGP Portable.exe"); // NON-NLS
+
+ }
+
+ public static String getName() {
+ return ENCRYPTION_PROGRAMS_RULE_NAME;
+ }
+
+ public static String getDescription() {
+ return ENCRYPTION_PROGRAMS_RULE_DESCRIPTION;
+ }
+
+ public static List getFilenames() {
+ return FILENAMES;
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfig.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfig.java
new file mode 100644
index 0000000000..5cbed2921c
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfig.java
@@ -0,0 +1,67 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Logical Imager Configuration file JSON
+ */
+public class LogicalImagerConfig {
+
+ @SerializedName("finalize-image-writer")
+ @Expose(serialize = true)
+ private boolean finalizeImageWriter;
+
+ @SerializedName("rule-sets")
+ @Expose(serialize = true)
+ private List ruleSets;
+
+ public LogicalImagerConfig() {
+ this.finalizeImageWriter = false;
+ this.ruleSets = new ArrayList<>();
+ }
+
+ public LogicalImagerConfig(
+ boolean finalizeImageWriter,
+ List ruleSets
+ ) {
+ this.finalizeImageWriter = finalizeImageWriter;
+ this.ruleSets = ruleSets;
+ }
+
+ public boolean isFinalizeImageWriter() {
+ return finalizeImageWriter;
+ }
+
+ public void setFinalizeImageWriter(boolean finalizeImageWriter) {
+ this.finalizeImageWriter = finalizeImageWriter;
+ }
+
+ public List getRuleSets() {
+ return ruleSets;
+ }
+
+ public void setRuleSet(List ruleSets) {
+ this.ruleSets = ruleSets;
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfigDeserializer.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfigDeserializer.java
new file mode 100644
index 0000000000..e6f7df7170
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfigDeserializer.java
@@ -0,0 +1,212 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.openide.util.NbBundle;
+
+/**
+ * Logical Imager Configuration JSON deserializer
+ */
+@NbBundle.Messages({
+ "LogicalImagerConfigDeserializer.missingRuleSetException=Missing rule-set",
+ "# {0} - key",
+ "LogicalImagerConfigDeserializer.unsupportedKeyException=Unsupported key: {0}",
+ "LogicalImagerConfigDeserializer.fullPathsException=A rule with full-paths cannot have other rule definitions",
+})
+public class LogicalImagerConfigDeserializer implements JsonDeserializer {
+
+ @Override
+ public LogicalImagerConfig deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
+ boolean finalizeImageWriter = false;
+
+ final JsonObject jsonObject = je.getAsJsonObject();
+ final JsonElement jsonFinalizeImageWriter = jsonObject.get("finalize-image-writer"); // NON-NLS
+ if (jsonFinalizeImageWriter != null) {
+ finalizeImageWriter = jsonFinalizeImageWriter.getAsBoolean();
+ }
+
+ JsonArray asJsonArray = jsonObject.get("rule-sets").getAsJsonArray(); // NON-NLS
+ if (asJsonArray == null) {
+ throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_missingRuleSetException());
+ }
+
+ List ruleSets = new ArrayList<>();
+ for (JsonElement element: asJsonArray) {
+ String setName = null;
+ List rules = null;
+ JsonObject asJsonObject = element.getAsJsonObject();
+ JsonElement setNameElement = asJsonObject.get("set-name");
+ setName = setNameElement.getAsString();
+ JsonElement rulesElement = asJsonObject.get("rules");
+ rules = parseRules(rulesElement.getAsJsonArray());
+ LogicalImagerRuleSet ruleSet = new LogicalImagerRuleSet(setName, rules);
+ ruleSets.add(ruleSet);
+ }
+ return new LogicalImagerConfig(finalizeImageWriter, ruleSets);
+ }
+
+ private List parseRules(JsonArray asJsonArray) {
+ List rules = new ArrayList<>();
+
+ for (JsonElement element: asJsonArray) {
+ String key1;
+ Boolean shouldSave = false;
+ Boolean shouldAlert = true;
+ String name = null;
+ String description = null;
+ List extensions = null;
+ List paths = null;
+ List fullPaths = null;
+ List filenames = null;
+ Integer minFileSize = null;
+ Integer maxFileSize = null;
+ Integer minDays = null;
+ Integer minDate = null;
+ Integer maxDate = null;
+
+ Set> entrySet = element.getAsJsonObject().entrySet();
+
+ for (Map.Entry entry1 : entrySet) {
+ key1 = entry1.getKey();
+ switch (key1) {
+ case "shouldAlert": // NON-NLS
+ shouldAlert = entry1.getValue().getAsBoolean();
+ break;
+ case "shouldSave": // NON-NLS
+ shouldSave = entry1.getValue().getAsBoolean();
+ break;
+ case "name": // NON-NLS
+ name = entry1.getValue().getAsString();
+ break;
+ case "description": // NON-NLS
+ description = entry1.getValue().getAsString();
+ break;
+ case "extensions": // NON-NLS
+ JsonArray extensionsArray = entry1.getValue().getAsJsonArray();
+ extensions = new ArrayList<>();
+ for (JsonElement e : extensionsArray) {
+ extensions.add(e.getAsString());
+ }
+ break;
+ case "folder-names": // NON-NLS
+ JsonArray pathsArray = entry1.getValue().getAsJsonArray();
+ paths = new ArrayList<>();
+ for (JsonElement e : pathsArray) {
+ paths.add(e.getAsString());
+ }
+ break;
+ case "file-names": // NON-NLS
+ JsonArray filenamesArray = entry1.getValue().getAsJsonArray();
+ filenames = new ArrayList<>();
+ for (JsonElement e : filenamesArray) {
+ filenames.add(e.getAsString());
+ }
+ break;
+ case "full-paths": // NON-NLS
+ JsonArray fullPathsArray = entry1.getValue().getAsJsonArray();
+ fullPaths = new ArrayList<>();
+ for (JsonElement e : fullPathsArray) {
+ fullPaths.add(e.getAsString());
+ }
+ break;
+ case "size-range": // NON-NLS
+ JsonObject sizeRangeObject = entry1.getValue().getAsJsonObject();
+ Set> entrySet1 = sizeRangeObject.entrySet();
+ for (Map.Entry entry2 : entrySet1) {
+ String sizeKey = entry2.getKey();
+ switch (sizeKey) {
+ case "min": // NON-NLS
+ minFileSize = entry2.getValue().getAsInt();
+ break;
+ case "max": // NON-NLS
+ maxFileSize = entry2.getValue().getAsInt();
+ break;
+ default:
+ throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_unsupportedKeyException(sizeKey));
+ }
+ }
+ break;
+ case "date-range": // NON-NLS
+ JsonObject dateRangeObject = entry1.getValue().getAsJsonObject();
+ Set> entrySet2 = dateRangeObject.entrySet();
+ for (Map.Entry entry2 : entrySet2) {
+ String dateKey = entry2.getKey();
+ switch (dateKey) {
+ case "min": // NON-NLS
+ minDate = entry2.getValue().getAsInt();
+ break;
+ case "max": // NON-NLS
+ maxDate = entry2.getValue().getAsInt();
+ break;
+ case "min-days": // NON-NLS
+ minDays = entry2.getValue().getAsInt();
+ break;
+ default:
+ throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_unsupportedKeyException(dateKey));
+ }
+ }
+ break;
+ default:
+ throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_unsupportedKeyException(key1));
+ }
+ }
+
+ // A rule with full-paths cannot have other rule definitions
+ if ((fullPaths != null && !fullPaths.isEmpty()) && ((extensions != null && !extensions.isEmpty())
+ || (paths != null && !paths.isEmpty())
+ || (filenames != null && !filenames.isEmpty()))) {
+ throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_fullPathsException());
+ }
+
+ LogicalImagerRule rule = new LogicalImagerRule.Builder()
+ .getShouldAlert(shouldAlert)
+ .getShouldSave(shouldSave)
+ .getName(name)
+ .getDescription(description)
+ .getExtensions(extensions)
+ .getPaths(paths)
+ .getFullPaths(fullPaths)
+ .getFilenames(filenames)
+ .getMinFileSize(minFileSize)
+ .getMaxFileSize(maxFileSize)
+ .getMinDays(minDays)
+ .getMinDate(minDate)
+ .getMaxDate(maxDate)
+ .build();
+ rules.add(rule);
+ } // for
+
+ return rules;
+ }
+}
+
+
+
+
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRule.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRule.java
new file mode 100644
index 0000000000..e1a966d4b9
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRule.java
@@ -0,0 +1,254 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * The class definition for the Logical Imager Rule.
+ */
+public class LogicalImagerRule {
+
+ @Expose(serialize = true)
+ private final Boolean shouldAlert;
+ @Expose(serialize = true)
+ private final Boolean shouldSave;
+ @Expose(serialize = true)
+ private final String name;
+ @Expose(serialize = true)
+ private final String description;
+ @Expose(serialize = true)
+ private List extensions = new ArrayList<>();
+ @SerializedName("file-names")
+ @Expose(serialize = true)
+ private List filenames = new ArrayList<>();
+ @SerializedName("folder-names")
+ @Expose(serialize = true)
+ private List paths = new ArrayList<>();
+ @SerializedName("full-paths")
+ @Expose(serialize = true)
+ private List fullPaths = new ArrayList<>();
+ @SerializedName("size-range")
+ @Expose(serialize = true)
+ final private Map sizeRange = new HashMap<>();
+ @SerializedName("date-range")
+ @Expose(serialize = true)
+ final private Map dateRange = new HashMap<>();
+
+ // The following fields should not be serialized, internal use only
+ @Expose(serialize = false)
+ private Integer minFileSize;
+ @Expose(serialize = false)
+ private Integer maxFileSize;
+ @Expose(serialize = false)
+ private Integer minDays;
+ @Expose(serialize = false)
+ private Integer minDate;
+ @Expose(serialize = false)
+ private Integer maxDate;
+
+ private LogicalImagerRule(Boolean shouldAlert, Boolean shouldSave, String name, String description,
+ List extensions,
+ List filenames,
+ List paths,
+ List fullPaths,
+ Integer minFileSize,
+ Integer maxFileSize,
+ Integer minDays,
+ Integer minDate,
+ Integer maxDate
+ ) {
+ this.shouldAlert = shouldAlert;
+ this.shouldSave = shouldSave;
+ this.name = name;
+ this.description = description;
+ this.extensions = extensions;
+ this.filenames = filenames;
+ this.paths = paths;
+ this.fullPaths = fullPaths;
+
+ this.sizeRange.put("min", minFileSize); // NON-NLS
+ this.minFileSize = minFileSize;
+ this.sizeRange.put("max", maxFileSize); // NON-NLS
+ this.maxFileSize = maxFileSize;
+ this.dateRange.put("min-days", minDays); // NON-NLS
+ this.minDays = minDays;
+ this.dateRange.put("min-date", minDate); // NON-NLS
+ this.minDate = minDate;
+ this.dateRange.put("max-date", maxDate); // NON-NLS
+ this.maxDate = maxDate;
+ }
+
+ public LogicalImagerRule() {
+ this.shouldAlert = false; // default
+ this.shouldSave = true; // default
+ this.description = null;
+ this.name = null;
+ }
+
+ public Boolean isShouldAlert() {
+ return shouldAlert;
+ }
+
+ public Boolean isShouldSave() {
+ return shouldSave;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List getExtensions() {
+ return extensions;
+ }
+
+ public List getFilenames() {
+ return filenames;
+ }
+
+ public List getPaths() {
+ return paths;
+ }
+
+ public List getFullPaths() {
+ return fullPaths;
+ }
+
+ public Integer getMinFileSize() {
+ return minFileSize;
+ }
+
+ public Integer getMaxFileSize() {
+ return maxFileSize;
+ }
+
+ public Integer getMinDays() {
+ return minDays;
+ }
+
+ public Integer getMinDate() {
+ return minDate;
+ }
+
+ public Integer getMaxDate() {
+ return maxDate;
+ }
+
+ /**
+ * Builder class
+ */
+ public static class Builder {
+ private Boolean shouldAlert = null;
+ private Boolean shouldSave = null;
+ private String name = null;
+ private String description = null;
+ private List extensions = null;
+ private List filenames = null;
+ private List paths = null;
+ private List fullPaths = null;
+ private Integer minFileSize = null;
+ private Integer maxFileSize = null;
+ private Integer minDays = null;
+ private Integer minDate = null;
+ private Integer maxDate = null;
+
+ public Builder getShouldAlert(boolean shouldAlert) {
+ this.shouldAlert = shouldAlert;
+ return this;
+ }
+
+ public Builder getShouldSave(boolean shouldSave) {
+ this.shouldSave = shouldSave;
+ return this;
+ }
+
+ public Builder getName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder getDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder getExtensions(List extensions) {
+ this.extensions = extensions;
+ return this;
+ }
+
+ public Builder getFilenames(List filenames) {
+ this.filenames = filenames;
+ return this;
+ }
+
+ public Builder getPaths(List paths) {
+ this.paths = paths;
+ return this;
+ }
+
+ public Builder getFullPaths(List fullPaths) {
+ this.fullPaths = fullPaths;
+ return this;
+ }
+
+ public Builder getMinFileSize(Integer minFileSize) {
+ this.minFileSize = minFileSize;
+ return this;
+ }
+
+ public Builder getMaxFileSize(Integer maxFileSize) {
+ this.maxFileSize = maxFileSize;
+ return this;
+ }
+
+ public Builder getMinDays(Integer minDays) {
+ this.minDays = minDays;
+ return this;
+ }
+
+ public Builder getMinDate(Integer minDate) {
+ this.minDate = minDate;
+ return this;
+ }
+
+ public Builder getMaxDate(Integer maxDate) {
+ this.maxDate = maxDate;
+ return this;
+ }
+
+ public LogicalImagerRule build() {
+ return new LogicalImagerRule(shouldAlert, shouldSave, name, description,
+ extensions, filenames, paths, fullPaths,
+ minFileSize, maxFileSize,
+ minDays, minDate, maxDate
+ );
+ }
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRuleSet.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRuleSet.java
new file mode 100644
index 0000000000..ba08d9a16b
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRuleSet.java
@@ -0,0 +1,63 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import java.util.List;
+
+/**
+ * Logical Imager Rule Set
+ */
+public class LogicalImagerRuleSet {
+
+ @SerializedName("set-name")
+ @Expose(serialize = true)
+ final private String setName;
+
+ @SerializedName("rules")
+ @Expose(serialize = true)
+ private final List rules;
+
+ public LogicalImagerRuleSet(String setName, List rules) {
+ this.setName = setName;
+ this.rules = rules;
+ }
+
+ public String getSetName() {
+ return setName;
+ }
+
+ public List getRules() {
+ return rules;
+ }
+
+ /*
+ * Find a rule with the given name. Return null if not found.
+ */
+ LogicalImagerRule find(String name) {
+ for (LogicalImagerRule rule : rules) {
+ if (rule.getName().equals(name)) {
+ return rule;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.form b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.form
new file mode 100644
index 0000000000..a0eaa284ef
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.form
@@ -0,0 +1,89 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.java b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.java
new file mode 100644
index 0000000000..cce14680c0
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.java
@@ -0,0 +1,153 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011-2019 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.configurelogicalimager;
+
+import java.awt.BorderLayout;
+import java.io.IOException;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+/**
+ * New rule set panel
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+public class NewRuleSetPanel extends javax.swing.JPanel {
+
+ private final JPanel nonFullPathsJPanel;
+ private final EditNonFullPathsRulePanel editNonFullPathsRulePanel;
+ private final JPanel fullPathsPanel;
+ private final EditFullPathsRulePanel editFullPathsRulePanel;
+
+ /**
+ * Creates new form NewRuleSetPanel
+ */
+ public NewRuleSetPanel(JButton okButton, JButton cancelButton) {
+ initComponents();
+
+ nonFullPathsJPanel = createPanel();
+ editNonFullPathsRulePanel = new EditNonFullPathsRulePanel(okButton, cancelButton, "", new LogicalImagerRule(), false);
+ nonFullPathsJPanel.add(editNonFullPathsRulePanel, BorderLayout.NORTH);
+
+ fullPathsPanel = createPanel();
+ editFullPathsRulePanel = new EditFullPathsRulePanel(okButton, cancelButton, "", new LogicalImagerRule(), false);
+ fullPathsPanel.add(editFullPathsRulePanel, BorderLayout.NORTH);
+
+ sharedLayeredPane.add(nonFullPathsJPanel, Integer.valueOf(0));
+ sharedLayeredPane.add(fullPathsPanel, Integer.valueOf(1));
+ nonFullPathsJPanel.setVisible(true);
+ fullPathsPanel.setVisible(false);
+ }
+
+ private JPanel createPanel() {
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.setSize(800, 640);
+ return panel;
+ }
+
+ /**
+ * 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
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ chooseLabel = new javax.swing.JLabel();
+ chooseComboBox = new javax.swing.JComboBox<>();
+ sharedLayeredPane = new javax.swing.JLayeredPane();
+
+ org.openide.awt.Mnemonics.setLocalizedText(chooseLabel, org.openide.util.NbBundle.getMessage(NewRuleSetPanel.class, "NewRuleSetPanel.chooseLabel.text")); // NOI18N
+
+ chooseComboBox.setMaximumRowCount(2);
+ chooseComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "By Attribute", "By Full Path" }));
+ chooseComboBox.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ chooseComboBoxActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout sharedLayeredPaneLayout = new javax.swing.GroupLayout(sharedLayeredPane);
+ sharedLayeredPane.setLayout(sharedLayeredPaneLayout);
+ sharedLayeredPaneLayout.setHorizontalGroup(
+ sharedLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 0, Short.MAX_VALUE)
+ );
+ sharedLayeredPaneLayout.setVerticalGroup(
+ sharedLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 373, Short.MAX_VALUE)
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(10, 10, 10)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(chooseLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(chooseComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap(716, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(sharedLayeredPane)
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(chooseLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(chooseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(sharedLayeredPane)
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+ private void chooseComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseComboBoxActionPerformed
+ int index = chooseComboBox.getSelectedIndex();
+ if (index == 0) {
+ nonFullPathsJPanel.setVisible(true);
+ fullPathsPanel.setVisible(false);
+ } else {
+ nonFullPathsJPanel.setVisible(false);
+ fullPathsPanel.setVisible(true);
+ }
+ }//GEN-LAST:event_chooseComboBoxActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JComboBox chooseComboBox;
+ private javax.swing.JLabel chooseLabel;
+ private javax.swing.JLayeredPane sharedLayeredPane;
+ // End of variables declaration//GEN-END:variables
+
+ ImmutablePair toRule() throws IOException, NumberFormatException {
+ ImmutablePair ruleMap;
+ if (chooseComboBox.getSelectedIndex() == 0) {
+ ruleMap = editNonFullPathsRulePanel.toRule();
+ } else {
+ ruleMap = editFullPathsRulePanel.toRule();
+ }
+ return ruleMap;
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/configurelogicalimager/tsk_logical_imager.exe b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/tsk_logical_imager.exe
new file mode 100644
index 0000000000..3a3523cf35
Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/tsk_logical_imager.exe differ
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTag.java b/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTag.java
old mode 100755
new mode 100644
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagControls.java b/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagControls.java
old mode 100755
new mode 100644
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagCreator.java b/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagCreator.java
old mode 100755
new mode 100644
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagRegion.java b/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagRegion.java
old mode 100755
new mode 100644
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsGroup.java b/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsGroup.java
old mode 100755
new mode 100644
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsUtility.java b/Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsUtility.java
old mode 100755
new mode 100644
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/TextPrompt.java b/Core/src/org/sleuthkit/autopsy/corecomponents/TextPrompt.java
index 1a34609627..05699059e6 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/TextPrompt.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/TextPrompt.java
@@ -35,10 +35,18 @@ public final class TextPrompt extends JLabel
private int focusLost;
public TextPrompt(String text, JTextComponent component) {
- this(text, component, Show.ALWAYS);
+ this(text, component, Show.ALWAYS, null);
}
public TextPrompt(String text, JTextComponent component, Show show) {
+ this(text, component, show, null);
+ }
+
+ public TextPrompt(String text, JTextComponent component, String layoutConstraint) {
+ this(text, component, Show.ALWAYS, layoutConstraint);
+ }
+
+ public TextPrompt(String text, JTextComponent component, Show show, String layoutConstraint) {
this.component = component;
component.removeAll();
setShow(show);
@@ -49,15 +57,19 @@ public final class TextPrompt extends JLabel
setForeground(component.getForeground());
setBorder(new EmptyBorder(component.getInsets()));
setHorizontalAlignment(JLabel.LEADING);
-
+
component.addFocusListener(this);
document.addDocumentListener(this);
component.setLayout(new BorderLayout());
- component.add(this);
+ if (layoutConstraint == null) {
+ component.add(this);
+ } else {
+ component.add(this, layoutConstraint);
+ }
checkForPrompt();
}
-
+
/**
* Convenience method to change the alpha value of the current foreground
* Color to the specifice value.
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/WrapLayout.java b/Core/src/org/sleuthkit/autopsy/corecomponents/WrapLayout.java
old mode 100755
new mode 100644