From 05bd31ed90feb7c951795ace5b71513061c67b18 Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Wed, 5 Jun 2019 14:34:35 -0400 Subject: [PATCH 01/21] Add new files for PR --- .../configurelogicalimager/Bundle.properties | 126 +++ .../Bundle.properties-MERGED | 176 ++++ .../ConfigVisualPanel1.form | 119 +++ .../ConfigVisualPanel1.java | 288 ++++++ .../ConfigVisualPanel2.form | 616 ++++++++++++ .../ConfigVisualPanel2.java | 952 ++++++++++++++++++ .../ConfigWizardPanel1.java | 149 +++ .../ConfigWizardPanel2.java | 158 +++ .../ConfigureLogicalImager.java | 85 ++ .../EditFullPathsRulePanel.form | 138 +++ .../EditFullPathsRulePanel.java | 265 +++++ .../EditNonFullPathsRulePanel.form | 280 ++++++ .../EditNonFullPathsRulePanel.java | 482 +++++++++ .../configurelogicalimager/EditRulePanel.java | 127 +++ .../EncryptionProgramsRule.java | 54 + .../LogicalImagerConfig.java | 67 ++ .../LogicalImagerConfigDeserializer.java | 187 ++++ .../LogicalImagerRule.java | 239 +++++ .../NewRuleSetPanel.form | 89 ++ .../NewRuleSetPanel.java | 153 +++ .../tsk_logical_imager.exe | Bin 0 -> 1398272 bytes .../autopsy/corecomponents/TextPrompt.java | 16 +- 22 files changed, 4762 insertions(+), 4 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties-MERGED create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.form create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.form create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel1.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel2.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigureLogicalImager.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditRulePanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/EncryptionProgramsRule.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfig.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfigDeserializer.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRule.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/NewRuleSetPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/configurelogicalimager/tsk_logical_imager.exe 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..093d91ffab --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties @@ -0,0 +1,126 @@ +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.newRadioButton.text_1=Create a new configuration +ConfigVisualPanel1.loadRadioButton.text_1=Open an existing configuration +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 Set +ConfigVisualPanel2.descriptionEditTextField.text= +ConfigVisualPanel2.editRuleButton.text=Edit Rule Set +ConfigVisualPanel2.newRuleButton.text=New Rule Set +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 Set: +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 Set: +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 Set: +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=Open +ConfigVisualPanel2.fullPathsTable.columnModel.title0= +ConfigVisualPanel2.folderNamesTable.columnModel.title0= +ConfigVisualPanel2.shouldSaveCheckBox.toolTipText= +NewRuleSetPanel.chooseLabel.text=Choose type of file 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 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..57a5c6954c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties-MERGED @@ -0,0 +1,176 @@ +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 json file +# {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 set +ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule set confirmation +ConfigVisualPanel2.editConfiguration=Edit configuration +ConfigVisualPanel2.editRuleError=Edit rule error +ConfigVisualPanel2.editRuleSet=Edit rule set +ConfigVisualPanel2.ok=OK +ConfigVisualPanel2.rulesTable.columnModel.title0=Rule set +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 +# ({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.newRadioButton.text_1=Create a new configuration +ConfigVisualPanel1.loadRadioButton.text_1=Open an existing configuration +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 Set +ConfigVisualPanel2.descriptionEditTextField.text= +ConfigVisualPanel2.editRuleButton.text=Edit Rule Set +ConfigVisualPanel2.newRuleButton.text=New Rule Set +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 Set: +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 Set: +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 Set: +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=Open +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 type of file 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 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..4df1ad428f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.form @@ -0,0 +1,119 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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..795559ca92 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel1.java @@ -0,0 +1,288 @@ +/* + * 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 + */ +public final class ConfigVisualPanel1 extends JPanel implements DocumentListener { + + 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(); + newRadioButton = new javax.swing.JRadioButton(); + loadRadioButton = new javax.swing.JRadioButton(); + jLabel1 = new javax.swing.JLabel(); + configFileTextField = new javax.swing.JTextField(); + browseButton = new javax.swing.JButton(); + + buttonGroup1.add(newRadioButton); + newRadioButton.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(newRadioButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.newRadioButton.text_1")); // NOI18N + newRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + newRadioButtonActionPerformed(evt); + } + }); + + buttonGroup1.add(loadRadioButton); + org.openide.awt.Mnemonics.setLocalizedText(loadRadioButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.loadRadioButton.text_1")); // NOI18N + loadRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + loadRadioButtonActionPerformed(evt); + } + }); + + 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.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() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(30, 30, 30) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(loadRadioButton) + .addComponent(newRadioButton))) + .addGroup(layout.createSequentialGroup() + .addGap(38, 38, 38) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(configFileTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 287, 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(30, 30, 30) + .addComponent(newRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(loadRadioButton) + .addGap(37, 37, 37) + .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 + + private void newRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRadioButtonActionPerformed + configFileTextField.setText(""); + }//GEN-LAST:event_newRadioButtonActionPerformed + + private void loadRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadRadioButtonActionPerformed + configFileTextField.setText(""); + }//GEN-LAST:event_loadRadioButtonActionPerformed + + @NbBundle.Messages({ + "ConfigVisualPanel1.chooseFileTitle=Select a Logical Imager configuration json file" + }) + 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.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 (Exception 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; + private javax.swing.JRadioButton loadRadioButton; + private javax.swing.JRadioButton newRadioButton; + // 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); + } + + @Override + public void insertUpdate(DocumentEvent e) { + } + + @Override + public void removeUpdate(DocumentEvent e) { + } + + @Override + public void changedUpdate(DocumentEvent e) { + } + + public boolean isPanelValid() { + return (newFile || !configFileTextField.getText().isEmpty()); + } + + 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..26255667c4 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.form @@ -0,0 +1,616 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + <ResourceString bundle="org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties" key="ConfigVisualPanel2.fullPathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + +
+
+ + + + + <ResourceString bundle="org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties" key="ConfigVisualPanel2.filenamesTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + <ResourceString bundle="org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties" key="ConfigVisualPanel2.folderNamesTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + <ResourceString bundle="org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties" key="ConfigVisualPanel2.rulesTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + <ResourceString bundle="org/sleuthkit/autopsy/configurelogicalimager/Bundle.properties" key="ConfigVisualPanel2.rulesTable.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + + + + + + +
+ + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
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..5f7ed7bf54 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigVisualPanel2.java @@ -0,0 +1,952 @@ +/* + * 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 java.util.Map; +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" +}) +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(); + } + + public boolean isFlagEncryptionPrograms() { + return flagEncryptionPrograms; + } + + /** + * 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.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "" + } + ) { + Class[] types = new Class [] { + java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + 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.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "" + } + ) { + Class[] types = new Class [] { + java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + 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.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "" + } + ) { + Class[] types = new Class [] { + java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + 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.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Rule Set", "Description" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + 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 mouseClicked(java.awt.event.MouseEvent evt) { + rulesTableMouseClicked(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.UNRELATED) + .addComponent(editRuleButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .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 rulesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rulesTableMouseClicked + rulesTableSelect(); + }//GEN-LAST:event_rulesTableMouseClicked + + private void rulesTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_rulesTableKeyReleased + rulesTableSelect(); + }//GEN-LAST:event_rulesTableKeyReleased + + @NbBundle.Messages({ + "ConfigVisualPanel2.editRuleSet=Edit rule set", + "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 = config.getRuleSet().get(ruleName); + 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(); + appendRow(ruleMap); + break; + } catch (Exception 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 set", + 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 (Exception 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 set ", + "ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule set 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; + } + + config.getRuleSet().remove(ruleName); + 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 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) { + config.getRuleSet().remove(EncryptionProgramsRule.getName()); + 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.description(EncryptionProgramsRule.getDescription()) + .shouldAlert(true) + .shouldSave(true) + .filenames(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 void updatePanel(String configFilePath, LogicalImagerConfig config, String rowSelectionkey) { + configFileTextField.setText(configFilePath); + finalizeImageWriter.setSelected(config.isFinalizeImageWriter()); + Map ruleSet = config.getRuleSet(); + flagEncryptionProgramsCheckBox.setSelected(ruleSet.get(EncryptionProgramsRule.getName()) != null); + RulesTableModel rulesTableModel = new RulesTableModel(); + int row = 0; + int selectThisRow = 0; + for (Map.Entry rule : ruleSet.entrySet()) { + rulesTableModel.setValueAt(rule.getKey(), row, 0); + if (rowSelectionkey != null && rule.getKey().equals(rowSelectionkey)) { + selectThisRow = row; + } + rulesTableModel.setValueAt(rule.getValue().getDescription(), row, 1); + rulesTableModel.setValueAt(rule.getValue(), 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(true); + } else { + updateRuleSetButtons(false); + } + } + + private void updateRuleDetails(String ruleName, String description, LogicalImagerConfig config) { + clearRuleDetails(); + LogicalImagerRule rule = config.getRuleSet().get(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(false); + } + + 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(true); + shouldSaveCheckBox.setSelected(false); + ruleNameEditTextField.setText(""); + descriptionEditTextField.setText(""); + extensionsTextField.setText(""); + updateList(filenamesTable, EMPTY_LIST); + updateList(folderNamesTable, EMPTY_LIST); + } + + boolean isPanelValid() { + return true; + } + + private void appendRow(ImmutablePair ruleMap) { + config.getRuleSet().put(ruleMap.getKey(), ruleMap.getValue()); + updatePanel(configFilename, config, ruleMap.getKey()); + } + + private void updateRuleSetButtons(boolean isRowSelected) { + newRuleButton.setEnabled(true); + editRuleButton.setEnabled(isRowSelected); + deleteRuleButton.setEnabled(isRowSelected); + } + + 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 set", + "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); + } + } + } + + 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; + switch (columnIndex) { + case 0: + ret = list.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 true; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + list.add((String) aValue); + break; + default: + 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..727880b1d5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel1.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 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 String configFilename = null; + private LogicalImagerConfig config = null; + boolean isValid = false; + private boolean newFile = true; + + // 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 + isValid = 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 isValid; + // 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 + configFilename = component.getConfigFilename(); + config = component.getConfig(); + newFile = component.isNewFile(); + wiz.putProperty("configFilename", configFilename); // NON-NLS + wiz.putProperty("config", config); // NON-NLS + wiz.putProperty("newFile", newFile); // NON-NLS + } + + @Override + public void validate() throws WizardValidationException { + isValid = 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..f9fde8c9a8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigWizardPanel2.java @@ -0,0 +1,158 @@ +/* + * 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; + private boolean newFile; + boolean isValid = 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 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 + newFile = (boolean) wiz.getProperty("newFile"); // NON-NLS + component.setConfiguration(configFilename, config, newFile); + } + + @Override + public void storeSettings(WizardDescriptor wiz) { + // use wiz.putProperty to remember current panel state + } + + @Override + public void addChangeListener(ChangeListener cl) { + } + + @Override + public void removeChangeListener(ChangeListener cl) { + } + + public String getConfigFilename() { + return configFilename; + } + + public LogicalImagerConfig getConfig() { + return config; + } + + @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")); + } 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); + } + } + +} 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..73ed437a04 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/ConfigureLogicalImager.java @@ -0,0 +1,85 @@ +/* + * 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, separatorAfter = 2050) +@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) { + // do something + if (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..c6585970b3 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.form @@ -0,0 +1,138 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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..58b1d0ffd6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditFullPathsRulePanel.java @@ -0,0 +1,265 @@ +/* + * 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.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 org.apache.commons.lang3.tuple.ImmutablePair; +import org.openide.util.NbBundle; + +/** + * Edit full paths rule panel + */ +public class EditFullPathsRulePanel extends javax.swing.JPanel { + + private JButton okButton; + private JButton cancelButton; + List newFullPaths = new ArrayList<>(); + private final JTextArea fullPathsTextArea; + + /** + * Creates new form EditFullPathsRulePanel + */ + @NbBundle.Messages({ + "EditFullPathsRulePanel.example=Example: " + }) + public EditFullPathsRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule) { + initComponents(); + 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 + + shouldAlertCheckBox.setSelected(true); + 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 + ruleNameTextField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + ruleNameTextFieldActionPerformed(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() + .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 + + private void ruleNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ruleNameTextFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_ruleNameTextFieldActionPerformed + + + // 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.shouldAlert(shouldAlertCheckBox.isSelected()) + .shouldSave(shouldSaveCheckBox.isSelected()) + .description(descriptionTextField.getText()) + .fullPaths(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..eb1c9be235 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.form @@ -0,0 +1,280 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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..708ba26671 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditNonFullPathsRulePanel.java @@ -0,0 +1,482 @@ +/* + * 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.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 + */ +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(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule) { + initComponents(); + + this.setRule(ruleName, rule); + this.setButtons(okButton, cancelButton); + + setExtensions(rule.getExtensions()); + + filenamesTextArea = new JTextArea(); + initTextArea(filenamesScrollPane, filenamesTextArea); + setTextArea(filenamesTextArea, rule.getFilenames()); + + 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"); // 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() { + + 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(); + + 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 + daysIncludedLabel.setEnabled(false); + + shouldSaveCheckBox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(shouldSaveCheckBox, org.openide.util.NbBundle.getMessage(EditNonFullPathsRulePanel.class, "EditNonFullPathsRulePanel.shouldSaveCheckBox.text")); // NOI18N + + shouldAlertCheckBox.setSelected(true); + 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 + ruleNameTextField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + ruleNameTextFieldActionPerformed(evt); + } + }); + + 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("####; ")))); + + 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() + .addGap(27, 27, 27) + .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(extensionsLabel) + .addComponent(extensionsTextField, 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.LEADING) + .addComponent(filenamesLabel) + .addComponent(filenamesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 70, 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) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .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 ruleNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ruleNameTextFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_ruleNameTextFieldActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel daysIncludedLabel; + private javax.swing.JLabel descriptionLabel; + private javax.swing.JTextField descriptionTextField; + private javax.swing.JLabel extensionsLabel; + private javax.swing.JTextField extensionsTextField; + private javax.swing.JLabel fileSizeLabel; + private javax.swing.JLabel filenamesLabel; + 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.description(descriptionTextField.getText()) + .shouldAlert(shouldAlertCheckBox.isSelected()) + .shouldSave(shouldSaveCheckBox.isSelected()) + .extensions(extensions) + .filenames(filenames) + .paths(folderNames); + + int minDays; + if (!isBlank(minDaysTextField.getText())) { + try { + minDaysTextField.commitEdit(); + minDays = ((Number)minDaysTextField.getValue()).intValue(); + if (minDays < 0) { + throw new IOException(Bundle.EditNonFullPathsRulePanel_modifiedDaysNotPositiveException()); + } + builder.minDays(minDays); + } catch (NumberFormatException | ParseException ex) { + throw new IOException(Bundle.EditNonFullPathsRulePanel_modifiedDaysMustBeNumberException(ex.getMessage())); + } + } + + 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())); + } + } + + 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())); + } + } + + if (maxFileSize != 0 && (maxFileSize < minFileSize)) { + throw new IOException(Bundle.EditNonFullPathsRulePanel_maxFileSizeSmallerThanMinException(maxFileSize, minFileSize)); + } + if (minFileSize != 0) { + builder.minFileSize(minFileSize); + } + if (maxFileSize != 0) { + builder.maxFileSize(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 { + List extensions = new ArrayList<>(); + if (isBlank(textField.getText())) { + return null; + } + 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..ae1704dcd9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EditRulePanel.java @@ -0,0 +1,127 @@ +/* + * 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); + } else { + editNonFullPathsRulePanel = new EditNonFullPathsRulePanel(okButton, cancelButton, ruleName, rule); + } + } + + void setRule(LogicalImagerRule rule) { + + } + + 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 { + List list = new ArrayList<>(); + if (isBlank(textArea.getText())) { + return null; + } + 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..61d18e4d37 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/EncryptionProgramsRule.java @@ -0,0 +1,54 @@ +/* + * 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<>(); + + // TODO: Add more files here + static { + FILENAMES.add("truecrypt.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..68fe81fe60 --- /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.HashMap; +import java.util.Map; + +/** + * Logical Imager Configuration file JSON + */ +public class LogicalImagerConfig { + + @SerializedName("finalize-image-writer") + @Expose(serialize = true) + private boolean finalizeImageWriter; + + @SerializedName("rule-set") + @Expose(serialize = true) + private Map ruleSet; + + public LogicalImagerConfig() { + this.finalizeImageWriter = false; + this.ruleSet = new HashMap<>(); + } + + public LogicalImagerConfig( + boolean finalizeImageWriter, + Map ruleSet + ) { + this.finalizeImageWriter = finalizeImageWriter; + this.ruleSet = ruleSet; + } + + public boolean isFinalizeImageWriter() { + return finalizeImageWriter; + } + + public void setFinalizeImageWriter(boolean finalizeImageWriter) { + this.finalizeImageWriter = finalizeImageWriter; + } + + public Map getRuleSet() { + return ruleSet; + } + + public void setRuleSet(Map ruleSet) { + this.ruleSet = ruleSet; + } +} 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..b206315dd9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerConfigDeserializer.java @@ -0,0 +1,187 @@ +/* + * 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.HashMap; +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; + Map ruleSet = new HashMap<>(); + + final JsonObject jsonObject = je.getAsJsonObject(); + final JsonElement jsonFinalizeImageWriter = jsonObject.get("finalize-image-writer"); // NON-NLS + if (jsonFinalizeImageWriter != null) { + finalizeImageWriter = jsonFinalizeImageWriter.getAsBoolean(); + } + + final JsonObject jsonRuleSet = jsonObject.get("rule-set").getAsJsonObject(); // NON-NLS + if (jsonRuleSet == null) { + throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_missingRuleSetException()); + } + for (Map.Entry entry : jsonRuleSet.entrySet()) { + String key = entry.getKey(); + JsonElement element = entry.getValue(); + Set> entrySet = element.getAsJsonObject().entrySet(); + String key1; + Boolean shouldSave = false; + Boolean shouldAlert = true; + 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; + + 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 "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() + .shouldAlert(shouldAlert) + .shouldSave(shouldSave) + .description(description) + .extensions(extensions) + .paths(paths) + .fullPaths(fullPaths) + .filenames(filenames) + .minFileSize(minFileSize) + .maxFileSize(maxFileSize) + .minDays(minDays) + .minDate(minDate) + .maxDate(maxDate) + .build(); + ruleSet.put(key, rule); + } + LogicalImagerConfig config = new LogicalImagerConfig(finalizeImageWriter, ruleSet); + return config; + } +} \ 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..781f00ae2a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/configurelogicalimager/LogicalImagerRule.java @@ -0,0 +1,239 @@ +/* + * 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 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) + private Map sizeRange = new HashMap<>(); + @SerializedName("date-range") + @Expose(serialize = true) + 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 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.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 = true; + this.shouldSave = false; + this.description = null; + } + + public Boolean isShouldAlert() { + return shouldAlert; + } + + public Boolean isShouldSave() { + return shouldSave; + } + + 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; + } + + public static class Builder { + private Boolean shouldAlert = null; + private Boolean shouldSave = 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() {} + + public Builder shouldAlert(boolean shouldAlert) { + this.shouldAlert = shouldAlert; + return this; + } + + public Builder shouldSave(boolean shouldSave) { + this.shouldSave = shouldSave; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder extensions(List extensions) { + this.extensions = extensions; + return this; + } + + public Builder filenames(List filenames) { + this.filenames = filenames; + return this; + } + + public Builder paths(List paths) { + this.paths = paths; + return this; + } + + public Builder fullPaths(List fullPaths) { + this.fullPaths = fullPaths; + return this; + } + + public Builder minFileSize(Integer minFileSize) { + this.minFileSize = minFileSize; + return this; + } + + public Builder maxFileSize(Integer maxFileSize) { + this.maxFileSize = maxFileSize; + return this; + } + + public Builder minDays(Integer minDays) { + this.minDays = minDays; + return this; + } + + public Builder minDate(Integer minDate) { + this.minDate = minDate; + return this; + } + + public Builder maxDate(Integer maxDate) { + this.maxDate = maxDate; + return this; + } + + public LogicalImagerRule build() { + return new LogicalImagerRule(shouldAlert, shouldSave, description, + extensions, filenames, paths, fullPaths, + minFileSize, maxFileSize, + minDays, minDate, maxDate + ); + } + } +} 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..e8c80c9737 --- /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..6e4532a5be --- /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 + */ +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()); + nonFullPathsJPanel.add(editNonFullPathsRulePanel, BorderLayout.NORTH); + + fullPathsPanel = createPanel(); + editFullPathsRulePanel = new EditFullPathsRulePanel(okButton, cancelButton, "", new LogicalImagerRule()); + fullPathsPanel.add(editFullPathsRulePanel, BorderLayout.NORTH); + + sharedLayeredPane.add(nonFullPathsJPanel, new Integer(0)); + sharedLayeredPane.add(fullPathsPanel, new Integer(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", "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(718, 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); + } + chooseComboBox.setEnabled(false); + }//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.isEnabled()) { + 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 0000000000000000000000000000000000000000..05f68c637658c53162dfe040a6e87b0f69475fa3 GIT binary patch literal 1398272 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

gQLpl_4Lis17(Sm>PJ0 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