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