diff --git a/Core/src/org/sleuthkit/autopsy/images/file_ingest_filter32x32.png b/Core/src/org/sleuthkit/autopsy/images/file_ingest_filter32x32.png new file mode 100644 index 0000000000..a31d8023e4 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/file_ingest_filter32x32.png differ diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index f8c1816e85..1a58c266b2 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -96,8 +96,6 @@ ModuleTableModel.colName.module=Module ModuleTableModel.colName.duration=Duration IngestJobSettingsPanel.jButtonSelectAll.text=Select All IngestJobSettingsPanel.jButtonDeselectAll.text=Deselect All -IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=Processes unallocated space, such as deleted files. Produces more complete results, but it may take longer to process on large images. -IngestJobSettingsPanel.processUnallocCheckbox.text=Process Unallocated Space IngestManager.cancellingIngest.msgDlg.text=Cancelling all currently running ingest jobs IngestManager.serviceIsDown.msgDlg.text={0} is down RunIngestSubMenu.menuItem.empty=-Empty- @@ -114,4 +112,5 @@ IngestJobSettingsPanel.globalSettingsButton.text=Global Settings gest IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced IngestJobSettingsPanel.globalSettingsButton.text=Global Settings -IngestJobSettingsPanel.pastJobsButton.text=View Ingest History +IngestJobSettingsPanel.pastJobsButton.text=History +IngestJobSettingsPanel.fileIngestFilterLabel.text=Run ingest modules on: diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index 130c0c3171..6ecb763bc2 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -89,9 +89,7 @@ IngestJobTableModel.colName.start=\u30b9\u30bf\u30fc\u30c8 IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=\u5225\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u540d\u524d\u3092\u91cd\u8907\u3059\u308b\u3001{0}\u306e\u540d\u524d\u3092\u6301\u3064\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u4f7f\u7528\u3057\u307e\u305b\u3093\u3002 IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30b8\u30e7\u30d6ID ModuleTableModel.colName.module=\u30e2\u30b8\u30e5\u30fc\u30eb -IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=\u524a\u9664\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u7b49\u306e\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u51e6\u7406\u3002\u3088\u308a\u5b8c\u5168\u306a\u7d50\u679c\u304c\u51fa\u307e\u3059\u304c\u3001\u5927\u304d\u3044\u30a4\u30e1\u30fc\u30b8\u3067\u306f\u51e6\u7406\u6642\u9593\u304c\u9577\u304f\u306a\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 -IngestJobSettingsPanel.processUnallocCheckbox.text=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u306e\u51e6\u7406 Menu/Tools/RunIngestModules=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c IngestJob.progress.fileIngest.cancelMessage={1}\u306e{0}\u3092\u5f85\u3063\u3066\u3044\u307e\u3059 IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306e\u30b1\u30fc\u30b9\u3067\u4f7f\u308f\u308c\u3066\u3044\u308b\u304b\u3082\u3057\u308c\u306a\u3044\u4ed6\u306e\u30ce\u30fc\u30c9\u306b\u89e3\u6790\u30d7\u30ed\u30bb\u30b9\u304c\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java index 1869be9169..f9caad7683 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2016 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. @@ -43,6 +43,7 @@ import org.sleuthkit.datamodel.IngestModuleInfo; import org.sleuthkit.datamodel.IngestModuleInfo.IngestModuleType; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSet; /** * Encapsulates a data source and the ingest module pipelines used to process @@ -159,7 +160,7 @@ final class DataSourceIngestJob { private ProgressHandle fileIngestProgress; private String currentFileIngestModule = ""; private String currentFileIngestTask = ""; - private List ingestModules = new ArrayList<>(); + private final List ingestModules = new ArrayList<>(); private IngestJobInfo ingestJob; /** @@ -331,6 +332,15 @@ final class DataSourceIngestJob { return this.settings.getProcessUnallocatedSpace(); } + /** + * Gets the selected file ingest filter from settings. + * + * @return True or false. + */ + FilesSet getFileIngestFilter() { + return this.settings.getFileIngestFilter(); + } + /** * Checks to see if this job has at least one ingest pipeline. * diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java index bea9d2a10b..fc2c8b38e9 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2016 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. @@ -29,6 +29,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.logging.Level; import org.openide.util.NbBundle; import org.openide.util.io.NbObjectInputStream; @@ -37,31 +39,56 @@ import org.python.util.PythonObjectInputStream; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSet; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager; /** * Encapsulates the ingest job settings for a particular execution context. * Examples of execution contexts include the add data source wizard and the run - * ingest modules dialog. Different execution conterxts may have different - * ingest job settings. + * ingest modules dialog. Different execution contexts may have different ingest + * job settings. */ public class IngestJobSettings { private static final String ENABLED_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS private static final String DISABLED_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS - private static final String PARSE_UNALLOC_SPACE_KEY = "Process_Unallocated_Space"; //NON-NLS - private static final String PROCESS_UNALLOC_SPACE_DEFAULT = "true"; //NON-NLS + private static final String LAST_FILE_INGEST_FILTER_KEY = "Last_File_Ingest_Filter"; private static final String MODULE_SETTINGS_FOLDER = "IngestModuleSettings"; //NON-NLS private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobSettings.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString(); private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS - private static final Logger logger = Logger.getLogger(IngestJobSettings.class.getName()); + private static final Logger LOGGER = Logger.getLogger(IngestJobSettings.class.getName()); + private FilesSet fileIngestFilter; private final String executionContext; private final IngestType ingestType; private String moduleSettingsFolderPath; private static final CharSequence pythonModuleSettingsPrefixCS = "org.python.proxies.".subSequence(0, "org.python.proxies.".length() - 1); //NON-NLS private final List moduleTemplates; - private boolean processUnallocatedSpace; private final List warnings; + /** + * Gets the last selected FileIngestFilter saved in settings which is represented + * by a FilesSet, if the last selected filter is null + * the default filter will be returned. + * + * @return FilesSet which represents the FileIngestFilter + */ + FilesSet getFileIngestFilter() { + if (fileIngestFilter==null){ + fileIngestFilter=FilesSetsManager.getDefaultFilter(); + } + return fileIngestFilter; + } + + /** + * Sets the FileIngestFilter which is currently being used by ingest. + * + * @param fileIngestFilter the FilesSet which represents the + * FileIngestFilter + */ + void setFileIngestFilter(FilesSet fileIngestFilter) { + this.fileIngestFilter = fileIngestFilter; + } + /** * The type of ingest modules to run. */ @@ -93,7 +120,6 @@ public class IngestJobSettings { this.executionContext = executionContext; this.ingestType = IngestType.ALL_MODULES; this.moduleTemplates = new ArrayList<>(); - this.processUnallocatedSpace = Boolean.parseBoolean(IngestJobSettings.PROCESS_UNALLOC_SPACE_DEFAULT); this.warnings = new ArrayList<>(); this.createSavedModuleSettingsFolder(); this.load(); @@ -118,7 +144,7 @@ public class IngestJobSettings { } this.moduleTemplates = new ArrayList<>(); - this.processUnallocatedSpace = Boolean.parseBoolean(IngestJobSettings.PROCESS_UNALLOC_SPACE_DEFAULT); + this.warnings = new ArrayList<>(); this.createSavedModuleSettingsFolder(); this.load(); @@ -195,18 +221,20 @@ public class IngestJobSettings { * settings. * * @return True or false. + * */ boolean getProcessUnallocatedSpace() { - return this.processUnallocatedSpace; - } - - /** - * Sets the process unallocated space flag for these ingest job settings. - * - * @param processUnallocatedSpace True or false. - */ - void setProcessUnallocatedSpace(boolean processUnallocatedSpace) { - this.processUnallocatedSpace = processUnallocatedSpace; + /* + * Used to be a simple flag but the processUnallocated checkbox was + * changed to a skip unallocated. This was due to the FileIngestFilters + * needing a default value which did not skip unallocated files. This + * method exists to maintain existing functionality. + */ + boolean processUnallocated = true; + if (!Objects.isNull(this.fileIngestFilter)) { + processUnallocated = (this.fileIngestFilter.ingoresUnallocatedSpace() == false); + } + return processUnallocated; } /** @@ -228,7 +256,7 @@ public class IngestJobSettings { Files.createDirectories(folder); this.moduleSettingsFolderPath = folder.toAbsolutePath().toString(); } catch (IOException | SecurityException ex) { - logger.log(Level.SEVERE, "Failed to create ingest module settings directory " + this.moduleSettingsFolderPath, ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Failed to create ingest module settings directory " + this.moduleSettingsFolderPath, ex); //NON-NLS this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.createModuleSettingsFolder.warning")); //NON-NLS } } @@ -285,7 +313,7 @@ public class IngestJobSettings { enabledModuleNames.remove(moduleName); disabledModuleNames.remove(moduleName); String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.missingModule.warning", moduleName); //NON-NLS - logger.log(Level.WARNING, warning); + LOGGER.log(Level.WARNING, warning); this.warnings.add(warning); } @@ -317,12 +345,24 @@ public class IngestJobSettings { ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames)); ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames)); - // Get the process unallocated space flag setting. If the setting does - // not exist yet, default it to true. - if (ModuleSettings.settingExists(this.executionContext, IngestJobSettings.PARSE_UNALLOC_SPACE_KEY) == false) { - ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.PARSE_UNALLOC_SPACE_KEY, IngestJobSettings.PROCESS_UNALLOC_SPACE_DEFAULT); + /** + * Restore the last used File Ingest Filter + */ + if (ModuleSettings.settingExists(this.executionContext, IngestJobSettings.LAST_FILE_INGEST_FILTER_KEY) == false) { + ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.LAST_FILE_INGEST_FILTER_KEY, FilesSetsManager.getDefaultFilter().getName()); + } + try { + Map fileIngestFilters = FilesSetsManager.getInstance() + .getCustomFileIngestFilters(); + for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()){ + fileIngestFilters.put(fSet.getName(), fSet); + } + this.fileIngestFilter = fileIngestFilters.get(ModuleSettings.getConfigSetting( + this.executionContext, IngestJobSettings.LAST_FILE_INGEST_FILTER_KEY)); + } catch (FilesSetsManager.FilesSetsManagerException ex) { + this.fileIngestFilter = FilesSetsManager.getDefaultFilter(); + LOGGER.log(Level.SEVERE, "Failed to get file ingest filter from .properties file, default filter being used", ex); //NON-NLS } - this.processUnallocatedSpace = Boolean.parseBoolean(ModuleSettings.getConfigSetting(this.executionContext, IngestJobSettings.PARSE_UNALLOC_SPACE_KEY)); } /** @@ -398,7 +438,7 @@ public class IngestJobSettings { settings = (IngestModuleIngestJobSettings) in.readObject(); } catch (IOException | ClassNotFoundException ex) { String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsLoad.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS - logger.log(Level.WARNING, warning, ex); + LOGGER.log(Level.WARNING, warning, ex); this.warnings.add(warning); } } else { @@ -406,7 +446,7 @@ public class IngestJobSettings { settings = (IngestModuleIngestJobSettings) in.readObject(); } catch (IOException | ClassNotFoundException exception) { String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsLoad.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS - logger.log(Level.WARNING, warning, exception); + LOGGER.log(Level.WARNING, warning, exception); this.warnings.add(warning); } } @@ -453,10 +493,9 @@ public class IngestJobSettings { ModuleSettings.setConfigSetting(this.executionContext, DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames)); /** - * Save the process unallocated space setting. + * Save the last used File Ingest Filter setting for this context. */ - String processUnalloc = Boolean.toString(this.processUnallocatedSpace); - ModuleSettings.setConfigSetting(this.executionContext, PARSE_UNALLOC_SPACE_KEY, processUnalloc); + ModuleSettings.setConfigSetting(this.executionContext, LAST_FILE_INGEST_FILTER_KEY, fileIngestFilter.getName()); } /** @@ -472,7 +511,7 @@ public class IngestJobSettings { out.writeObject(settings); } catch (IOException ex) { String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS - logger.log(Level.SEVERE, warning, ex); + LOGGER.log(Level.SEVERE, warning, ex); this.warnings.add(warning); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.form index 8c98480783..e66f0f4d3f 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.form @@ -32,52 +32,46 @@ - - - + + - - - - - - - - - - - - + + + + + + + + - - - + + + - - - + + + + + + + - + + - - - - - - - - + + @@ -135,16 +129,16 @@ - + - + - + @@ -218,6 +212,15 @@ + + + + + + + + + @@ -228,33 +231,52 @@ + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java index df7b9c1039..2f2480b694 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java @@ -26,8 +26,10 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.DefaultComboBoxModel; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JDialog; @@ -43,11 +45,15 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSet; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSetPanel; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.IngestModuleInfo; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager; /** * A panel to allow a user to make ingest job settings. @@ -77,6 +83,7 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { } initComponents(); customizeComponents(); + fileIngestFilterComboBox.setSelectedItem(settings.getFileIngestFilter().getName()); } /** @@ -101,6 +108,7 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { } initComponents(); customizeComponents(); + fileIngestFilterComboBox.setSelectedItem(settings.getFileIngestFilter().getName()); } /** @@ -165,7 +173,6 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { } }); modulesTable.setRowSelectionInterval(0, 0); - processUnallocCheckbox.setSelected(this.settings.getProcessUnallocatedSpace()); this.modulesTable.getColumnModel().getColumn(0).setMaxWidth(22); this.modulesTable.getColumnModel().getColumn(1).setMaxWidth(20); this.modulesTable.getColumnModel().getColumn(1).setMinWidth(20); @@ -198,8 +205,9 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { ingestSettingsPanel = new javax.swing.JPanel(); jButtonSelectAll = new javax.swing.JButton(); jButtonDeselectAll = new javax.swing.JButton(); - processUnallocCheckbox = new javax.swing.JCheckBox(); pastJobsButton = new javax.swing.JButton(); + fileIngestFilterLabel = new javax.swing.JLabel(); + fileIngestFilterComboBox = new javax.swing.JComboBox<>(); setMaximumSize(new java.awt.Dimension(5750, 3000)); setMinimumSize(new java.awt.Dimension(0, 0)); @@ -249,14 +257,14 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() + .addGap(8, 8, 8) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 321, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(globalSettingsButton))) - .addContainerGap()) + .addGap(8, 8, 8)) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -273,6 +281,9 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { ); jButtonSelectAll.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.jButtonSelectAll.text")); // NOI18N + jButtonSelectAll.setMaximumSize(new java.awt.Dimension(87, 23)); + jButtonSelectAll.setMinimumSize(new java.awt.Dimension(87, 23)); + jButtonSelectAll.setPreferredSize(new java.awt.Dimension(86, 23)); jButtonSelectAll.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonSelectAllActionPerformed(evt); @@ -280,67 +291,73 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { }); jButtonDeselectAll.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.jButtonDeselectAll.text")); // NOI18N + jButtonDeselectAll.setPreferredSize(new java.awt.Dimension(86, 23)); jButtonDeselectAll.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonDeselectAllActionPerformed(evt); } }); - processUnallocCheckbox.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.processUnallocCheckbox.text")); // NOI18N - processUnallocCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.processUnallocCheckbox.toolTipText")); // NOI18N - processUnallocCheckbox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - processUnallocCheckboxActionPerformed(evt); - } - }); - pastJobsButton.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.pastJobsButton.text")); // NOI18N + pastJobsButton.setMaximumSize(new java.awt.Dimension(87, 23)); + pastJobsButton.setMinimumSize(new java.awt.Dimension(87, 23)); + pastJobsButton.setPreferredSize(new java.awt.Dimension(87, 23)); pastJobsButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pastJobsButtonActionPerformed(evt); } }); + fileIngestFilterLabel.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.fileIngestFilterLabel.text")); // NOI18N + + fileIngestFilterComboBox.setModel(new DefaultComboBoxModel<>(getComboBoxContents())); + fileIngestFilterComboBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileIngestFilterComboBoxActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + .addGap(5, 5, 5) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(processUnallocCheckbox) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(jButtonSelectAll, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pastJobsButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(5, 5, 5) - .addComponent(jButtonDeselectAll))) - .addGap(0, 0, Short.MAX_VALUE))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE) - .addContainerGap()) + .addComponent(jButtonSelectAll, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButtonDeselectAll, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pastJobsButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(fileIngestFilterLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(fileIngestFilterComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(4, 4, 4) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(5, 5, 5)) ); + + layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jButtonDeselectAll, jButtonSelectAll, pastJobsButton}); + layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() + .addComponent(fileIngestFilterLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileIngestFilterComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(modulesScrollPane, 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.BASELINE) - .addComponent(jButtonSelectAll) - .addComponent(jButtonDeselectAll)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pastJobsButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(processUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 428, Short.MAX_VALUE) - .addContainerGap()))) + .addComponent(jButtonSelectAll, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jButtonDeselectAll, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(pastJobsButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 428, Short.MAX_VALUE)) + .addContainerGap()) ); }// //GEN-END:initComponents @@ -371,10 +388,6 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { private void jButtonDeselectAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonDeselectAllActionPerformed SelectAllModules(false); }//GEN-LAST:event_jButtonDeselectAllActionPerformed - - private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed - this.settings.setProcessUnallocatedSpace(processUnallocCheckbox.isSelected()); - }//GEN-LAST:event_processUnallocCheckboxActionPerformed @Messages({"IngestJobSettingsPanel.pastJobsButton.action.frame.title=Ingest History"}) private void pastJobsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pastJobsButtonActionPerformed JDialog topFrame = (JDialog) SwingUtilities.getWindowAncestor(this); @@ -390,6 +403,66 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { dialog.setVisible(true); }//GEN-LAST:event_pastJobsButtonActionPerformed + private void fileIngestFilterComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileIngestFilterComboBoxActionPerformed + if (fileIngestFilterComboBox.getSelectedItem().toString().equals(FilesSetPanel.getCreateNewFileIngestFilterString())) { + final AdvancedConfigurationDialog dialog = new AdvancedConfigurationDialog(true); + FilesSetDefsPanel fileIngestFilterPanel; + fileIngestFilterPanel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS); + fileIngestFilterPanel.load(); + dialog.addApplyButtonListener( + (ActionEvent e) -> { + fileIngestFilterPanel.store(); + fileIngestFilterComboBox.setModel(new DefaultComboBoxModel<>(getComboBoxContents())); + dialog.close(); + } + ); + dialog.display(fileIngestFilterPanel); + + fileIngestFilterComboBox.setSelectedItem(settings.getFileIngestFilter().getName()); + + } else if (evt.getActionCommand().equals("comboBoxChanged")) { + + try { + Map fileIngestFilters = FilesSetsManager.getInstance() + .getCustomFileIngestFilters(); + for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) { + fileIngestFilters.put(fSet.getName(), fSet); + } + settings.setFileIngestFilter(fileIngestFilters + .get(fileIngestFilterComboBox.getSelectedItem().toString())); + } catch (FilesSetsManager.FilesSetsManagerException ex) { + settings.setFileIngestFilter(FilesSetsManager.getDefaultFilter()); + logger.log(Level.SEVERE, "Failed to get file ingest filter from combobox selection, default filter being used", ex); //NON-NLS + } + } + }//GEN-LAST:event_fileIngestFilterComboBoxActionPerformed + + /** + * Returns an array which will contain the names of all options which should + * exist in the "Run Ingest Modules On:" JCombobox + * + * Keeping the default File Ingest Filters and the saved one separate allows + * the default to always be first elements. + * + * @return -filterNames an array of all established filter names as well as + * a Create New option + */ + private String[] getComboBoxContents() { + ArrayList nameList = new ArrayList<>(); + for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) { + nameList.add(fSet.getName()); + } + try { + for (FilesSet fSet : FilesSetsManager.getInstance().getCustomFileIngestFilters().values()) { + nameList.add(fSet.getName()); + } + } catch (FilesSetsManager.FilesSetsManagerException ex) { + logger.log(Level.SEVERE, "Failed to get user created file ingest filters for combo box, only default available for selection", ex); //NON-NLS + } + nameList.add(FilesSetPanel.getCreateNewFileIngestFilterString()); + return nameList.toArray(new String[nameList.size()]); + } + private void SelectAllModules(boolean set) { for (IngestModuleModel module : modules) { module.setEnabled(set); @@ -399,6 +472,8 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel descriptionLabel; + private javax.swing.JComboBox fileIngestFilterComboBox; + private javax.swing.JLabel fileIngestFilterLabel; private javax.swing.JButton globalSettingsButton; private javax.swing.JPanel ingestSettingsPanel; private javax.swing.JButton jButtonDeselectAll; @@ -409,7 +484,6 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { private javax.swing.JScrollPane modulesScrollPane; private javax.swing.JTable modulesTable; private javax.swing.JButton pastJobsButton; - private javax.swing.JCheckBox processUnallocCheckbox; private javax.swing.ButtonGroup timeGroup; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java index 2a56c71c85..834f475ffd 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2012-2015 Basis Technology Corp. + * + * Copyright 2012-2016 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. @@ -397,13 +397,6 @@ final class IngestTasksScheduler { private static boolean shouldEnqueueFileTask(final FileIngestTask task) { final AbstractFile file = task.getFile(); - // Skip the task if the file is an unallocated space file and the - // process unallocated space flag is not set for this job. - if (!task.getIngestJob().shouldProcessUnallocatedSpace() - && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) { - return false; - } - // Skip the task if the file is actually the pseudo-file for the parent // or current directory. String fileName = file.getName(); @@ -411,8 +404,17 @@ final class IngestTasksScheduler { return false; } - // Skip the task if the file is one of a select group of special, large - // NTFS or FAT file system files. + /** + * Check if the file is a member of the file ingest filter that is being + * applied to the current run of ingest, checks if unallocated space + * should be processed inside call to fileIsMemberOf + */ + if ((task.getIngestJob().getFileIngestFilter().fileIsMemberOf(file)) == null) { + return false; + } + +// Skip the task if the file is one of a select group of special, large +// NTFS or FAT file system files. if (file instanceof org.sleuthkit.datamodel.File) { final org.sleuthkit.datamodel.File f = (org.sleuthkit.datamodel.File) file; @@ -522,6 +524,7 @@ final class IngestTasksScheduler { */ synchronized IngestJobTasksSnapshot getTasksSnapshotForJob(long jobId) { return new IngestJobTasksSnapshot(jobId); + } /** @@ -555,12 +558,12 @@ final class IngestTasksScheduler { static final List MEDIUM_PRI_PATHS = new ArrayList<>(); static final List HIGH_PRI_PATHS = new ArrayList<>(); + /* * prioritize root directory folders based on the assumption that we * are looking for user content. Other types of investigations may * want different priorities. */ - static /* * prioritize root directory folders based on the assumption that we * are looking for user content. Other types of investigations may diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties index 3a1ced09a3..405269afb6 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties @@ -4,14 +4,20 @@ OpenIDE-Module-Short-Description=Interesting Files Identifier ingest module. OpenIDE-Module-Name=Interesting Files Identifier OptionsCategory_Name_InterestingItemDefinitions=Interesting Files OptionsCategory_Keywords_InterestingItemDefinitions=InterestingItemDefinitions +OptionsCategory_Name_FileIngestFilterDefinitions=File Ingest Filter +OptionsCategory_Keywords_FileIngestFilterDefinitions=FileIngestFilterDefinitions InterestingItemsIdentifierIngestModule.moduleName=Interesting Files Identifier InterestingItemsIdentifierIngestModule.moduleDescription=Identifies interesting items as defined by interesting item rule sets. -FilesSetPanel.title=Interesting Files Set +FilesSetPanel.interesting.title=Interesting Files Set FilesSetPanel.messages.filesSetsMustBeNamed=Interesting files sets must be named. +FilesSetPanel.messages.filesSetsReservedName=You have chosen a name reserved by the software, please choose a different name. FilesSetPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files FilesSetPanel.descriptionPanel.border.title=Description -FilesSetPanel.nameLabel.text=Set Name: +FilesSetPanel.interesting.nameLabel.text=Set Name: +FilesSetPanel.ingest.nameLabel.text=Filter Name: FilesSetPanel.descPanel.border.title=Description +FilesSetPanel.ignoreUnallocCheckbox.toolTipText=Ignores unallocated space, such as deleted files. May run faster but produce less complete results. +FilesSetPanel.ignoreUnallocCheckbox.text=Ignore Unallocated Space FilesSetRulePanel.title=Interesting Files Set Rule FilesSetRulePanel.extensionRadioButton.text=Extension Only FilesSetRulePanel.pathRegexCheckBox.text=Regex @@ -26,42 +32,51 @@ FilesSetRulePanel.messages.invalidNameRegex=The name regular expression is not v FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, \", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0} -InterestingItemDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists. +FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists. FilesSetRulePanel.pathSeparatorInfoLabel.text=Use / as path separator FilesIdentifierIngestJobSettingsPanel.border.title=Select interesting files sets to enable during ingest: FilesSetRulePanel.jLabel1.text=Type: -FilesSetRulePanel.jLabel5.text=Enter information about files that you want to find. -InterestingItemDefsPanel.jLabel6.text=Set Details -InterestingItemDefsPanel.jLabel8.text=File Size: -InterestingItemDefsPanel.jLabel7.text=MIME Type: -InterestingItemDefsPanel.jTextArea1.text=This module allows you to find files that match specified criteria. Each set has a list of rules, which will match on file name and parent path patterns. -InterestingItemDefsPanel.jLabel4.text=Path Pattern: -InterestingItemDefsPanel.jLabel1.text=Rule Details -InterestingItemDefsPanel.dirsRadioButton.text=Directories -InterestingItemDefsPanel.jLabel2.text=File Type: -InterestingItemDefsPanel.newSetButton.text=New Set -InterestingItemDefsPanel.deleteRuleButton.text=Delete Rule -InterestingItemDefsPanel.deleteSetButton.text=Delete Set -InterestingItemDefsPanel.bothRadioButton.text=Files and Directories -InterestingItemDefsPanel.setsListLabel.text=Rule Sets -InterestingItemDefsPanel.fileNameRegexCheckbox.text=Regex -InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files -InterestingItemDefsPanel.fileNameRadioButton.text=File Name -InterestingItemDefsPanel.jLabel5.text=Description: -InterestingItemDefsPanel.fileNameTextField.text= -InterestingItemDefsPanel.jLabel3.text=Name Pattern: -InterestingItemDefsPanel.fileNameExtensionRadioButton.text=Extension Only -InterestingItemDefsPanel.editSetButton.text=Edit Set -InterestingItemDefsPanel.rulesListLabel.text=Rules: -InterestingItemDefsPanel.editRuleButton.text=Edit Rule -InterestingItemDefsPanel.filesRadioButton.text=Files -InterestingItemDefsPanel.newRuleButton.text=New Rule -InterestingItemDefsPanel.rulePathConditionTextField.text= -InterestingItemDefsPanel.rulePathConditionRegexCheckBox.text=Regex +FilesSetRulePanel.interesting.jLabel5.text=Enter information about files that you want to find. +FilesSetRulePanel.ingest.jLabel5.text=Enter information about files that you want to run ingest on. FilesSetRulePanel.nameCheck.text=Name Pattern: FilesSetRulePanel.pathCheck.text=Path Pattern: FilesSetRulePanel.mimeCheck.text=MIME Type: FilesSetRulePanel.fileSizeCheck.text=File Size: FilesSetRulePanel.filesRadioButton.text=Files FilesSetRulePanel.dirsRadioButton.text=Directories -FilesSetRulePanel.filesAndDirsRadioButton.text=Files and Directories +FilesSetDefsPanel.interesting.setsListLabel.text=Rule Sets +FilesSetDefsPanel.ingest.setsListLabel.text=File Ingest Filters +FilesSetDefsPanel.interesting.jTextArea1.text=This module allows you to find files that match specified criteria. Each set has a list of rules, which will match on file name and parent path patterns. +FilesSetDefsPanel.ingest.jTextArea1.text=Add rules so that only a subset of the files in a data source are analyzed. Rules are organized into sets and one set can be used at at time. +FilesSetDefsPanel.interesting.editSetButton.text=Edit Set +FilesSetDefsPanel.ingest.editSetButton.text=Edit Filter +FilesSetDefsPanel.interesting.newSetButton.text=New Set +FilesSetDefsPanel.ingest.newSetButton.text=New Filter +FilesSetDefsPanel.interesting.deleteSetButton.text=Delete Set +FilesSetDefsPanel.ingest.deleteSetButton.text=Delete Filter +FilesSetDefsPanel.interesting.jLabel6.text=Set Details +FilesSetDefsPanel.ingest.jLabel6.text=Filter Details +FilesSetDefsPanel.newRuleButton.text=New Rule +FilesSetDefsPanel.jLabel8.text=File Size: +FilesSetDefsPanel.jLabel7.text=MIME Type: +FilesSetDefsPanel.rulePathConditionRegexCheckBox.text=Regex +FilesSetDefsPanel.jLabel4.text=Path Pattern: +FilesSetDefsPanel.jLabel1.text=Rule Details +FilesSetDefsPanel.dirsRadioButton.text=Directories +FilesSetDefsPanel.jLabel2.text=File Type: +FilesSetDefsPanel.deleteRuleButton.text=Delete Rule +FilesSetDefsPanel.bothRadioButton.text=Files and Directories +FilesSetDefsPanel.fileNameRegexCheckbox.text=Regex +FilesSetDefsPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files +FilesSetDefsPanel.rulePathConditionTextField.text= +FilesSetDefsPanel.fileNameRadioButton.text=File Name +FilesSetDefsPanel.jLabel5.text=Description: +FilesSetDefsPanel.fileNameTextField.text= +FilesSetDefsPanel.jLabel3.text=Name Pattern: +FilesSetDefsPanel.fileNameExtensionRadioButton.text=Extension Only +FilesSetDefsPanel.rulesListLabel.text=Rules: +FilesSetDefsPanel.editRuleButton.text=Edit Rule +FilesSetDefsPanel.filesRadioButton.text=Files +FilesSetRulePanel.allRadioButton.text=All +FilesSetDefsPanel.ingoreUnallocCheckbox.text=Ignore Unallocated Space +FilesSetDefsPanel.ingoreUnallocCheckbox.toolTipText=Ignores unallocated space, such as deleted files. May run faster but produce less complete results. diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties index 487925a7b4..078be65eb0 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties @@ -3,7 +3,7 @@ FilesSetPanel.descPanel.border.title=\u6982\u8981 FilesSetPanel.descriptionPanel.border.title=\u6982\u8981 FilesSetPanel.ignoreKnownFilesCheckbox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\u3092\u7121\u8996 FilesSetPanel.messages.filesSetsMustBeNamed=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u306f\u540d\u524d\u304c\u5fc5\u8981\u3067\u3059\u3002 -FilesSetPanel.nameLabel.text=\u30bb\u30c3\u30c8\u540d\uff1a +FilesSetPanel.interesting.nameLabel.text=\u30bb\u30c3\u30c8\u540d\uff1a FilesSetPanel.title=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8 FilesSetRulePanel.extensionRadioButton.text=\u62e1\u5f35\u5b50\u306e\u307f FilesSetRulePanel.fullNameRadioButton.text=\u30d5\u30eb\u30cd\u30fc\u30e0 @@ -26,49 +26,26 @@ OpenIDE-Module-Name=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u691c\u77e5 OpenIDE-Module-Short-Description=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u691c\u77e5\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb OptionsCategory_Name_InterestingItemDefinitions=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb OptionsCategory_Keywords_InterestingItemDefinitions=\u7591\u308f\u3057\u3044\u30a2\u30a4\u30c6\u30e0\u5b9a\u7fa9 -InterestingItemDefsPanel.doFileSetsDialog.duplicateRuleSet.text=\u540d\u524d\u304c{0}\u306e\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8\u306f\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 -FilesSetRulePanel.jLabel5.text=\u898b\u3064\u3051\u305f\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -InterestingItemDefsPanel.jTextArea1.text=\u6307\u5b9a\u3055\u308c\u305f\u6761\u4ef6\u3068\u4e00\u81f4\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\u3059\u308b\u306e\u304c\u53ef\u80fd\u306a\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u3059\u3002\u5404\u30bb\u30c3\u30c8\u306b\u306f\u30d5\u30a1\u30a4\u30eb\u540d\u304a\u3088\u3073\u30da\u30a2\u30ec\u30f3\u30c8\u30d1\u30b9\u30d1\u30bf\u30fc\u30f3\u3092\u3082\u3068\u306b\u4e00\u81f4\u3059\u308b\u3001\u30eb\u30fc\u30eb\u30ea\u30b9\u30c8\u304c\u3042\u308a\u307e\u3059\u3002 - -InterestingItemDefsPanel.jLabel4.text=\u30d1\u30b9\u30d1\u30bf\u30fc\u30f3\uff1a - -InterestingItemDefsPanel.jLabel1.text=\u30eb\u30fc\u30eb\u8a73\u7d30 - -InterestingItemDefsPanel.dirsRadioButton.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea - -InterestingItemDefsPanel.jLabel2.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\uff1a - -InterestingItemDefsPanel.newSetButton.text=\u65b0\u898f\u30bb\u30c3\u30c8 - -InterestingItemDefsPanel.deleteRuleButton.text=\u30eb\u30fc\u30eb\u3092\u524a\u9664 - -InterestingItemDefsPanel.deleteSetButton.text=\u30bb\u30c3\u30c8\u3092\u524a\u9664 - -InterestingItemDefsPanel.bothRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u304a\u3088\u3073\u30c7\u30a3\u30ec\u30af\u30c8\u30ea - -InterestingItemDefsPanel.setsListLabel.text=\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8 - -InterestingItemDefsPanel.fileNameRegexCheckbox.text=\u6b63\u898f\u8868\u73fe - -InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\u3092\u7121\u8996 - -InterestingItemDefsPanel.fileNameRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u540d - -InterestingItemDefsPanel.jLabel5.text=\u6982\u8981\uff1a - -InterestingItemDefsPanel.jLabel3.text=\u30cd\u30fc\u30e0\u30d1\u30bf\u30fc\u30f3 - -InterestingItemDefsPanel.fileNameExtensionRadioButton.text=\u62e1\u5f35\u5b50\u306e\u307f - -InterestingItemDefsPanel.editSetButton.text=\u30bb\u30c3\u30c8\u3092\u7de8\u96c6 - -InterestingItemDefsPanel.rulesListLabel.text=\u30eb\u30fc\u30eb\uff1a - -InterestingItemDefsPanel.editRuleButton.text=\u30eb\u30fc\u30eb\u3092\u7de8\u96c6 - -InterestingItemDefsPanel.filesRadioButton.text=\u30d5\u30a1\u30a4\u30eb - -InterestingItemDefsPanel.newRuleButton.text=\u65b0\u898f\u30eb\u30fc\u30eb - -InterestingItemDefsPanel.jLabel6.text=\u30bb\u30c3\u30c8\u8a73\u7d30 -InterestingItemDefsPanel.rulePathConditionRegexCheckBox.text=\u6b63\u898f\u8868\u73fe +FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=\u540d\u524d\u304c{0}\u306e\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8\u306f\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 +FilesSetRulePanel.interesting.jLabel5.text=\u898b\u3064\u3051\u305f\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +FilesSetDefsPanel.interesting.setsListLabel.text=\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8 +FilesSetDefsPanel.interesting.editSetButton.text=\u30bb\u30c3\u30c8\u3092\u7de8\u96c6 +FilesSetDefsPanel.interesting.newSetButton.text=\u65b0\u898f\u30bb\u30c3\u30c8 +FilesSetDefsPanel.interesting.deleteSetButton.text=\u30bb\u30c3\u30c8\u3092\u524a\u9664 +FilesSetDefsPanel.newRuleButton.text=\u65b0\u898f\u30eb\u30fc\u30eb +FilesSetDefsPanel.rulePathConditionRegexCheckBox.text=\u6b63\u898f\u8868\u73fe +FilesSetDefsPanel.jLabel4.text=\u30d1\u30b9\u30d1\u30bf\u30fc\u30f3\uff1a +FilesSetDefsPanel.jLabel1.text=\u30eb\u30fc\u30eb\u8a73\u7d30 +FilesSetDefsPanel.dirsRadioButton.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea +FilesSetDefsPanel.jLabel2.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\uff1a +FilesSetDefsPanel.deleteRuleButton.text=\u30eb\u30fc\u30eb\u3092\u524a\u9664 +FilesSetDefsPanel.bothRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u304a\u3088\u3073\u30c7\u30a3\u30ec\u30af\u30c8\u30ea +FilesSetDefsPanel.fileNameRegexCheckbox.text=\u6b63\u898f\u8868\u73fe +FilesSetDefsPanel.ignoreKnownFilesCheckbox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\u3092\u7121\u8996 +FilesSetDefsPanel.fileNameRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u540d +FilesSetDefsPanel.jLabel5.text=\u6982\u8981\uff1a +FilesSetDefsPanel.jLabel3.text=\u30cd\u30fc\u30e0\u30d1\u30bf\u30fc\u30f3 +FilesSetDefsPanel.fileNameExtensionRadioButton.text=\u62e1\u5f35\u5b50\u306e\u307f +FilesSetDefsPanel.rulesListLabel.text=\u30eb\u30fc\u30eb\uff1a +FilesSetDefsPanel.editRuleButton.text=\u30eb\u30fc\u30eb\u3092\u7de8\u96c6 +FilesSetDefsPanel.filesRadioButton.text=\u30d5\u30a1\u30a4\u30eb diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FileIngestFilterDefsOptionsPanelController.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FileIngestFilterDefsOptionsPanelController.java new file mode 100644 index 0000000000..af394bf2c3 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FileIngestFilterDefsOptionsPanelController.java @@ -0,0 +1,154 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2016 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.modules.interestingitems; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.sleuthkit.autopsy.coreutils.Logger; + +@OptionsPanelController.TopLevelRegistration( + categoryName = "#OptionsCategory_Name_FileIngestFilterDefinitions", + iconBase = "org/sleuthkit/autopsy/images/file_ingest_filter32x32.png", + keywords = "#OptionsCategory_Keywords_FileIngestFilterDefinitions", + keywordsCategory = "FileIngestFilterDefinitions", + position = 7 +) + +/** + * Class for creating an FilesSetDefsPanel which will be used for configuring + * the FileIngestFilter. + */ +public final class FileIngestFilterDefsOptionsPanelController extends OptionsPanelController { + + private FilesSetDefsPanel panel; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private boolean changed; + private static final Logger LOGGER = Logger.getLogger(FileIngestFilterDefsOptionsPanelController.class.getName()); + + /** + * Component should load its data here. + */ + @Override + public void update() { + getPanel().load(); + changed = false; + } + + + /** + * This method is called when both the Ok and Apply buttons are pressed. It + * applies to any of the panels that have been opened in the process of + * using the options pane. + */ + @Override + public void applyChanges() { + if (changed) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + getPanel().store(); + changed = false; + } + }); + } + } + + /** + * This method is called when the Cancel button is pressed. It applies to + * any of the panels that have been opened in the process of using the + * options pane. + */ + @Override + public void cancel() { + // need not do anything special, if no changes have been persisted yet + } + + @Override + public boolean isValid() { + return true; + } + + /** + * Used to determine whether any changes have been made to this controller's + * panel. + * + * @return Whether or not a change has been made. + */ + @Override + public boolean isChanged() { + return changed; + } + + @Override + public HelpCtx getHelpCtx() { + return null; + } + + @Override + public JComponent getComponent(Lookup masterLookup) { + return getPanel(); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener l) { + pcs.addPropertyChangeListener(l); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener l) { + pcs.removePropertyChangeListener(l); + } + + /** + * Creates an interestingItemsDefPanel that will be labeled to indicate it + * is for File Ingest Filter settings + * + * @return an FilesSetDefsPanel which has text and fields modified to + * indicate it is for File Ingest Filtering. + */ + private FilesSetDefsPanel getPanel() { + if (panel == null) { + panel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS); + panel.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) { + changed(); + } + } + }); + } + return panel; + } + + void changed() { + if (!changed) { + changed = true; + pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true); + } + pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FileSetsDefinitions.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FileSetsDefinitions.java new file mode 100644 index 0000000000..8272f2e3ab --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FileSetsDefinitions.java @@ -0,0 +1,97 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 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.modules.interestingitems; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import org.openide.util.io.NbObjectInputStream; +import org.openide.util.io.NbObjectOutputStream; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; + +/** + * Class for wrapping a map which stores FilesSets as values with a String key. + */ +class FileSetsDefinitions implements Serializable { + + + private static final long serialVersionUID = 1L; + //By wrapping the map in this class we avoid warnings for unchecked casting when serializing + private final Map filesSets; + + FileSetsDefinitions(Map filesSets) { + this.filesSets = filesSets; + } + + /** + * @return the filesSets + */ + Map getFilesSets() { + return filesSets; + } + + /** + * Writes FilesSet definitions to disk as an XML file, logging any errors. + * + * @param fileName Name of the set definitions file as a string. + * + * @returns True if the definitions are written to disk, false otherwise. + */ + static boolean writeDefinitionsFile(String fileName, Map interestingFilesSets) throws FilesSetsManager.FilesSetsManagerException { + try (final NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(Paths.get(PlatformUtil.getUserConfigDirectory(), fileName).toString()))) { + out.writeObject(new FileSetsDefinitions(interestingFilesSets)); + } catch (IOException ex) { + throw new FilesSetsManager.FilesSetsManagerException(String.format("Failed to write settings to %s", fileName), ex); + } + return true; + } + + /** + * Reads the definitions from the serialization file + * + * @return the map representing settings saved to serialization file, empty + * set if the file does not exist. + * + * @throws FilesSetsManagerException if file could not be read + */ + static Map readSerializedDefinitions(String serialFileName) throws FilesSetsManager.FilesSetsManagerException { + Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), serialFileName); + File fileSetFile = filePath.toFile(); + String filePathStr = filePath.toString(); + if (fileSetFile.exists()) { + try { + try (final NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePathStr))) { + FileSetsDefinitions filesSetsSettings = (FileSetsDefinitions) in.readObject(); + return filesSetsSettings.getFilesSets(); + } + } catch (IOException | ClassNotFoundException ex) { + throw new FilesSetsManager.FilesSetsManagerException(String.format("Failed to read settings from %s", filePathStr), ex); + } + } else { + return new HashMap<>(); + } + } + +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java index bab3117d3a..934fde0fef 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java @@ -26,7 +26,6 @@ import java.util.TreeMap; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; -import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; @@ -36,6 +35,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; * Ingest job settings panel for interesting files identifier ingest modules. */ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel implements Observer { + @Messages({ "FilesIdentifierIngestJobSettingsPanel.updateError=Error updating interesting files sets settings file.", "FilesIdentifierIngestJobSettingsPanel.getError=Error getting interesting files sets from settings file." @@ -62,7 +62,7 @@ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobS // interesting file set definitions. This is used to keep this panel in // synch with changes made using the global settings/option panel for // this module. - InterestingItemDefsManager.getInstance().addObserver(panel); + FilesSetsManager.getInstance().addObserver(panel); return panel; } @@ -83,8 +83,8 @@ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobS */ List filesSetRows = new ArrayList<>(); try { - this.filesSetSnapshot = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); - } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + this.filesSetSnapshot = new TreeMap<>(FilesSetsManager.getInstance().getInterestingFilesSets()); + } catch (FilesSetsManager.FilesSetsManagerException ex) { MessageNotifyUtil.Message.error(Bundle.FilesIdentifierIngestJobSettingsPanel_getError()); this.filesSetSnapshot = new TreeMap<>(); } @@ -138,8 +138,8 @@ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobS List rowModels = new ArrayList<>(); TreeMap newFilesSetSnapshot; try { - newFilesSetSnapshot = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); - } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + newFilesSetSnapshot = new TreeMap<>(FilesSetsManager.getInstance().getInterestingFilesSets()); + } catch (FilesSetsManager.FilesSetsManagerException ex) { MessageNotifyUtil.Message.error(Bundle.FilesIdentifierIngestJobSettingsPanel_updateError()); return; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java index 173029e3fe..8a9a2b8469 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java @@ -83,12 +83,12 @@ final class FilesIdentifierIngestModule implements FileIngestModule { // to disable the interesting files set definition UI during ingest. List filesSets = new ArrayList<>(); try { - for (FilesSet set : InterestingItemDefsManager.getInstance().getInterestingFilesSets().values()) { + for (FilesSet set : FilesSetsManager.getInstance().getInterestingFilesSets().values()) { if (settings.interestingFilesSetIsEnabled(set.getName())) { filesSets.add(set); } } - } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + } catch (FilesSetsManager.FilesSetsManagerException ex) { throw new IngestModuleException(Bundle.FilesIdentifierIngestModule_getFilesError(), ex); } FilesIdentifierIngestModule.interestingFileSetsByJob.put(context.getJobId(), filesSets); @@ -103,7 +103,7 @@ final class FilesIdentifierIngestModule implements FileIngestModule { @Messages({"FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search."}) public ProcessResult process(AbstractFile file) { blackboard = Case.getCurrentCase().getServices().getBlackboard(); - + // Skip slack space files. if (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) { return ProcessResult.OK; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java index 7b196d17b2..403ab31be7 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java @@ -36,31 +36,35 @@ import org.sleuthkit.datamodel.TskData; * Interesting files set definition objects are immutable, so they may be safely * published to multiple threads. */ -final class FilesSet implements Serializable { +public final class FilesSet implements Serializable { private static final long serialVersionUID = 1L; private final String name; private final String description; private final boolean ignoreKnownFiles; + private final boolean ignoreUnallocatedSpace; private final Map rules = new HashMap<>(); /** * Constructs an interesting files set. * - * @param name The name of the set. - * @param description A description of the set, may be null. - * @param ignoreKnownFiles Whether or not to exclude known files from the - * set. - * @param rules The rules that define the set. May be null, but a - * set with no rules is the empty set. + * @param name The name of the set. + * @param description A description of the set, may be null. + * @param ignoreKnownFiles Whether or not to exclude known files from + * the set. + * @param ignoreUnallocatedSpace Whether or not to exclude unallocated space + * from the set. + * @param rules The rules that define the set. May be null, + * but a set with no rules is the empty set. */ - FilesSet(String name, String description, boolean ignoreKnownFiles, Map rules) { + public FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map rules) { if ((name == null) || (name.isEmpty())) { throw new IllegalArgumentException("Interesting files set name cannot be null or empty"); } this.name = name; this.description = (description != null ? description : ""); this.ignoreKnownFiles = ignoreKnownFiles; + this.ignoreUnallocatedSpace = ignoreUnallocatedSpace; if (rules != null) { this.rules.putAll(rules); } @@ -71,7 +75,7 @@ final class FilesSet implements Serializable { * * @return A name string. */ - String getName() { + public String getName() { return this.name; } @@ -97,6 +101,16 @@ final class FilesSet implements Serializable { return this.ignoreKnownFiles; } + /** + * Returns whether or not this set of rules will process unallocated space. + * + * @return True if unallocated space should be processed, false if it should + * not be. + */ + public boolean ingoresUnallocatedSpace() { + return this.ignoreUnallocatedSpace; + } + /** * Gets a copy of the set membership rules of this interesting files set. * @@ -114,10 +128,18 @@ final class FilesSet implements Serializable { * @return The name of the first set membership rule satisfied by the file, * will be null if the file does not belong to the set. */ - String fileIsMemberOf(AbstractFile file) { + public String fileIsMemberOf(AbstractFile file) { if ((this.ignoreKnownFiles) && (file.getKnown() == TskData.FileKnown.KNOWN)) { return null; } + + if ((this.ignoreUnallocatedSpace) + && (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) + || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) + || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))) { + return null; + } + for (Rule rule : rules.values()) { if (rule.isSatisfied(file)) { return rule.getName(); @@ -165,9 +187,6 @@ final class FilesSet implements Serializable { if (metaTypeCondition == null) { throw new IllegalArgumentException("Interesting files set rule meta-type condition cannot be null"); } - if (pathCondition == null && fileNameCondition == null && mimeTypeCondition == null && fileSizeCondition == null) { - throw new IllegalArgumentException("Must have at least one condition on rule."); - } this.ruleName = ruleName; @@ -497,7 +516,8 @@ final class FilesSet implements Serializable { FILES, DIRECTORIES, - FILES_AND_DIRECTORIES + FILES_AND_DIRECTORIES, + ALL } private final Type type; @@ -518,9 +538,13 @@ final class FilesSet implements Serializable { return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG; case DIRECTORIES: return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR; - default: + case FILES_AND_DIRECTORIES: return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR; + case ALL: + return true; //Effectively ignores the metatype condition when All is selected. + default: + return true; } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form similarity index 75% rename from Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.form rename to Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form index b4c3076206..4565237aa8 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form @@ -29,7 +29,10 @@ - + + + + @@ -62,127 +65,111 @@ - + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + - + + - - - - - - - + + + + + - - - - - + + + + + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + @@ -196,11 +183,11 @@ - + - - + + @@ -211,15 +198,18 @@ - - - - + + + + + + + - - + + @@ -227,7 +217,7 @@ - + @@ -245,26 +235,26 @@ - + - + - + - + @@ -283,7 +273,7 @@ - + @@ -298,7 +288,7 @@ - + @@ -317,7 +307,7 @@ - + @@ -333,7 +323,7 @@ - + @@ -349,7 +339,7 @@ - + @@ -389,6 +379,12 @@ + + + + + + @@ -431,7 +427,7 @@ - + @@ -479,7 +475,7 @@ - + @@ -492,7 +488,7 @@ - + @@ -505,12 +501,9 @@ - + - - - @@ -520,7 +513,7 @@ - + @@ -535,7 +528,7 @@ - + @@ -549,7 +542,7 @@ - + @@ -561,13 +554,10 @@ - + - - - @@ -577,7 +567,7 @@ - + @@ -595,7 +585,7 @@ - + @@ -610,7 +600,7 @@ - + @@ -626,7 +616,7 @@ - + @@ -645,7 +635,7 @@ - + @@ -664,7 +654,7 @@ - + @@ -679,7 +669,7 @@ - + @@ -694,13 +684,10 @@ - + - - - @@ -710,7 +697,7 @@ - + @@ -722,7 +709,7 @@ - + @@ -734,7 +721,7 @@ - + @@ -768,7 +755,7 @@ - + @@ -778,13 +765,15 @@ - + - + + + @@ -803,7 +792,7 @@ - + @@ -830,7 +819,7 @@ - + @@ -839,6 +828,17 @@ + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java similarity index 69% rename from Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java rename to Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java index 94af650828..2afc136613 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java @@ -43,22 +43,28 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; /** * A panel that allows a user to make interesting item definitions. */ -final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel { +public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel { @NbBundle.Messages({ - "InterestingItemDefsPanel.bytes=Bytes", - "InterestingItemDefsPanel.kiloBytes=Kilobytes", - "InterestingItemDefsPanel.megaBytes=Megabytes", - "InterestingItemDefsPanel.gigaBytes=Gigabytes", - "InterestingItemsDefsPanel.loadError=Error loading interesting files sets from file.", - "InterestingItemsDefsPanel.saveError=Error saving interesting files sets to file." + "FilesSetDefsPanel.bytes=Bytes", + "FilesSetDefsPanel.kiloBytes=Kilobytes", + "FilesSetDefsPanel.megaBytes=Megabytes", + "FilesSetDefsPanel.gigaBytes=Gigabytes", + "FilesSetDefsPanel.loadError=Error loading interesting files sets from file.", + "FilesSetDefsPanel.saveError=Error saving interesting files sets to file." }) + public static enum PANEL_TYPE { + FILE_INGEST_FILTERS, + INTERESTING_FILE_SETS + } private final DefaultListModel setsListModel = new DefaultListModel<>(); private final DefaultListModel rulesListModel = new DefaultListModel<>(); - private final Logger logger = Logger.getLogger(InterestingItemDefsPanel.class.getName()); + private final Logger logger = Logger.getLogger(FilesSetDefsPanel.class.getName()); private final JButton okButton = new JButton("OK"); private final JButton cancelButton = new JButton("Cancel"); + private final PANEL_TYPE panelType; + private final String ruleDialogTitle; // The following is a map of interesting files set names to interesting // files set definitions. It is a snapshot of the files set definitions @@ -72,18 +78,46 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp /** * Constructs an interesting item definitions panel. */ - InterestingItemDefsPanel() { + public FilesSetDefsPanel(PANEL_TYPE panelType) { + this.panelType = panelType; this.initComponents(); this.customInit(); this.setsList.setModel(setsListModel); - this.setsList.addListSelectionListener(new InterestingItemDefsPanel.SetsListSelectionListener()); + this.setsList.addListSelectionListener(new FilesSetDefsPanel.SetsListSelectionListener()); this.rulesList.setModel(rulesListModel); - this.rulesList.addListSelectionListener(new InterestingItemDefsPanel.RulesListSelectionListener()); + this.rulesList.addListSelectionListener(new FilesSetDefsPanel.RulesListSelectionListener()); + + if (panelType == PANEL_TYPE.FILE_INGEST_FILTERS) { //Hide the mimetype settings when this is displaying FileSet rules instead of interesting item rules + this.mimeTypeComboBox.setVisible(false); + this.jLabel7.setVisible(false); + this.fileSizeUnitComboBox.setVisible(false); + this.fileSizeSpinner.setVisible(false); + this.ruleDialogTitle = "FilesSetPanel.ingest.title"; + + this.jLabel8.setVisible(false); + this.equalitySignComboBox.setVisible(false); + this.ignoreKnownFilesCheckbox.setVisible(false); + this.jTextArea1.setText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingest.jTextArea1.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(setsListLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingest.setsListLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(editSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingest.editSetButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(newSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingest.newSetButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(deleteSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingest.deleteSetButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingest.jLabel6.text")); // NOI18N + } else { + this.ruleDialogTitle = "FilesSetPanel.interesting.title"; + this.ingoreUnallocCheckbox.setVisible(false); + + } } - @NbBundle.Messages({"InterestingItemDefsPanel.Title=Global Interesting Items Settings"}) + @NbBundle.Messages({"FilesSetDefsPanel.Interesting.Title=Global Interesting Items Settings", + "FilesSetDefsPanel.Ingest.Title=File Ingest Filter Settings"}) private void customInit() { - setName(Bundle.InterestingItemDefsPanel_Title()); + if (panelType == PANEL_TYPE.FILE_INGEST_FILTERS) { + setName(Bundle.FilesSetDefsPanel_Ingest_Title()); + } else { + setName(Bundle.FilesSetDefsPanel_Interesting_Title()); + } Set fileTypesCollated = new HashSet<>(); for (String mediaType : FileTypeDetector.getStandardDetectedTypes()) { @@ -122,9 +156,14 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp @Override public void saveSettings() { try { - InterestingItemDefsManager.getInstance().setInterestingFilesSets(this.filesSets); - } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { - MessageNotifyUtil.Message.error(Bundle.InterestingItemsDefsPanel_saveError()); + if (panelType == PANEL_TYPE.FILE_INGEST_FILTERS) { + FilesSetsManager.getInstance().setCustomFileIngestFilters(this.filesSets); + } else { + FilesSetsManager.getInstance().setInterestingFilesSets(this.filesSets); + } + + } catch (FilesSetsManager.FilesSetsManagerException ex) { + MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_saveError()); } } @@ -146,9 +185,14 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp try { // Get a working copy of the interesting files set definitions and sort // by set name. - this.filesSets = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); - } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { - MessageNotifyUtil.Message.error(Bundle.InterestingItemsDefsPanel_loadError()); + if (panelType == PANEL_TYPE.FILE_INGEST_FILTERS) { + this.filesSets = new TreeMap<>(FilesSetsManager.getInstance().getCustomFileIngestFilters()); + } else { + this.filesSets = new TreeMap<>(FilesSetsManager.getInstance().getInterestingFilesSets()); + } + + } catch (FilesSetsManager.FilesSetsManagerException ex) { + MessageNotifyUtil.Message.error(Bundle.FilesSetDefsPanel_loadError()); this.filesSets = new TreeMap<>(); } @@ -162,7 +206,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // Select the first files set by default. The list selections // listeners will then populate the other components. EventQueue.invokeLater(() -> { - InterestingItemDefsPanel.this.setsList.setSelectedIndex(0); + FilesSetDefsPanel.this.setsList.setSelectedIndex(0); }); } } @@ -175,6 +219,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp this.setsListModel.clear(); this.setDescriptionTextArea.setText(""); this.ignoreKnownFilesCheckbox.setSelected(true); + this.ingoreUnallocCheckbox.setSelected(true); this.newSetButton.setEnabled(true); this.editSetButton.setEnabled(false); this.deleteSetButton.setEnabled(false); @@ -211,32 +256,32 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp return; } - InterestingItemDefsPanel.this.rulesListModel.clear(); - InterestingItemDefsPanel.this.resetRuleComponents(); + FilesSetDefsPanel.this.rulesListModel.clear(); + FilesSetDefsPanel.this.resetRuleComponents(); // Get the selected interesting files set and populate the set // components. - FilesSet selectedSet = InterestingItemDefsPanel.this.setsList.getSelectedValue(); + FilesSet selectedSet = FilesSetDefsPanel.this.setsList.getSelectedValue(); if (selectedSet != null) { // Populate the components that display the properties of the // selected files set. - InterestingItemDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription()); - InterestingItemDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles()); - + FilesSetDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription()); + FilesSetDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles()); + FilesSetDefsPanel.this.ingoreUnallocCheckbox.setSelected(selectedSet.ingoresUnallocatedSpace()); // Enable the new, edit and delete set buttons. - InterestingItemDefsPanel.this.newSetButton.setEnabled(true); - InterestingItemDefsPanel.this.editSetButton.setEnabled(true); - InterestingItemDefsPanel.this.deleteSetButton.setEnabled(true); + FilesSetDefsPanel.this.newSetButton.setEnabled(true); + FilesSetDefsPanel.this.editSetButton.setEnabled(true); + FilesSetDefsPanel.this.deleteSetButton.setEnabled(true); // Populate the rule definitions list, sorted by name. TreeMap rules = new TreeMap<>(selectedSet.getRules()); for (FilesSet.Rule rule : rules.values()) { - InterestingItemDefsPanel.this.rulesListModel.addElement(rule); + FilesSetDefsPanel.this.rulesListModel.addElement(rule); } // Select the first rule by default. - if (!InterestingItemDefsPanel.this.rulesListModel.isEmpty()) { - InterestingItemDefsPanel.this.rulesList.setSelectedIndex(0); + if (!FilesSetDefsPanel.this.rulesListModel.isEmpty()) { + FilesSetDefsPanel.this.rulesList.setSelectedIndex(0); } } } @@ -256,7 +301,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp } // Get the selected rule and populate the rule components. - FilesSet.Rule rule = InterestingItemDefsPanel.this.rulesList.getSelectedValue(); + FilesSet.Rule rule = FilesSetDefsPanel.this.rulesList.getSelectedValue(); if (rule != null) { // Get the conditions that make up the rule. FilesSet.Rule.FileNameCondition nameCondition = rule.getFileNameCondition(); @@ -268,55 +313,55 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // Populate the components that display the properties of the // selected rule. if (nameCondition != null) { - InterestingItemDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch()); - InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.FullNameCondition); - InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.ExtensionCondition); - InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(nameCondition.isRegex()); + FilesSetDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch()); + FilesSetDefsPanel.this.fileNameRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.FullNameCondition); + FilesSetDefsPanel.this.fileNameExtensionRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.ExtensionCondition); + FilesSetDefsPanel.this.fileNameRegexCheckbox.setSelected(nameCondition.isRegex()); } else { - InterestingItemDefsPanel.this.fileNameTextField.setText(""); - InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(true); - InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(false); - InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(false); + FilesSetDefsPanel.this.fileNameTextField.setText(""); + FilesSetDefsPanel.this.fileNameRadioButton.setSelected(true); + FilesSetDefsPanel.this.fileNameExtensionRadioButton.setSelected(false); + FilesSetDefsPanel.this.fileNameRegexCheckbox.setSelected(false); } switch (typeCondition.getMetaType()) { case FILES: - InterestingItemDefsPanel.this.filesRadioButton.setSelected(true); + FilesSetDefsPanel.this.filesRadioButton.setSelected(true); break; case DIRECTORIES: - InterestingItemDefsPanel.this.dirsRadioButton.setSelected(true); + FilesSetDefsPanel.this.dirsRadioButton.setSelected(true); break; case FILES_AND_DIRECTORIES: - InterestingItemDefsPanel.this.bothRadioButton.setSelected(true); + FilesSetDefsPanel.this.bothRadioButton.setSelected(true); break; } if (pathCondition != null) { - InterestingItemDefsPanel.this.rulePathConditionTextField.setText(pathCondition.getTextToMatch()); - InterestingItemDefsPanel.this.rulePathConditionRegexCheckBox.setSelected(pathCondition.isRegex()); + FilesSetDefsPanel.this.rulePathConditionTextField.setText(pathCondition.getTextToMatch()); + FilesSetDefsPanel.this.rulePathConditionRegexCheckBox.setSelected(pathCondition.isRegex()); } else { - InterestingItemDefsPanel.this.rulePathConditionTextField.setText(""); - InterestingItemDefsPanel.this.rulePathConditionRegexCheckBox.setSelected(false); + FilesSetDefsPanel.this.rulePathConditionTextField.setText(""); + FilesSetDefsPanel.this.rulePathConditionRegexCheckBox.setSelected(false); } if (mimeTypeCondition != null) { - InterestingItemDefsPanel.this.mimeTypeComboBox.setSelectedItem(mimeTypeCondition.getMimeType()); + FilesSetDefsPanel.this.mimeTypeComboBox.setSelectedItem(mimeTypeCondition.getMimeType()); } else { - InterestingItemDefsPanel.this.mimeTypeComboBox.setSelectedIndex(0); + FilesSetDefsPanel.this.mimeTypeComboBox.setSelectedIndex(0); } if (fileSizeCondition != null) { - InterestingItemDefsPanel.this.fileSizeUnitComboBox.setSelectedItem(fileSizeCondition.getUnit().getName()); - InterestingItemDefsPanel.this.equalitySignComboBox.setSelectedItem(fileSizeCondition.getComparator().getSymbol()); - InterestingItemDefsPanel.this.fileSizeSpinner.setValue(fileSizeCondition.getSizeValue()); + FilesSetDefsPanel.this.fileSizeUnitComboBox.setSelectedItem(fileSizeCondition.getUnit().getName()); + FilesSetDefsPanel.this.equalitySignComboBox.setSelectedItem(fileSizeCondition.getComparator().getSymbol()); + FilesSetDefsPanel.this.fileSizeSpinner.setValue(fileSizeCondition.getSizeValue()); } else { - InterestingItemDefsPanel.this.fileSizeUnitComboBox.setSelectedIndex(1); - InterestingItemDefsPanel.this.equalitySignComboBox.setSelectedIndex(2); - InterestingItemDefsPanel.this.fileSizeSpinner.setValue(0); + FilesSetDefsPanel.this.fileSizeUnitComboBox.setSelectedIndex(1); + FilesSetDefsPanel.this.equalitySignComboBox.setSelectedIndex(2); + FilesSetDefsPanel.this.fileSizeSpinner.setValue(0); } // Enable the new, edit and delete rule buttons. - InterestingItemDefsPanel.this.newRuleButton.setEnabled(true); - InterestingItemDefsPanel.this.editRuleButton.setEnabled(true); - InterestingItemDefsPanel.this.deleteRuleButton.setEnabled(true); + FilesSetDefsPanel.this.newRuleButton.setEnabled(true); + FilesSetDefsPanel.this.editRuleButton.setEnabled(true); + FilesSetDefsPanel.this.deleteRuleButton.setEnabled(true); } else { - InterestingItemDefsPanel.this.resetRuleComponents(); + FilesSetDefsPanel.this.resetRuleComponents(); } } @@ -335,10 +380,10 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSetPanel panel; if (selectedSet != null) { // Editing an existing set definition. - panel = new FilesSetPanel(selectedSet); + panel = new FilesSetPanel(selectedSet, panelType); } else { // Creating a new set definition. - panel = new FilesSetPanel(); + panel = new FilesSetPanel(panelType); } // Do a dialog box with the files set panel until the user either enters @@ -346,14 +391,14 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // feedback when isValidDefinition() is called. int option = JOptionPane.OK_OPTION; do { - option = JOptionPane.showConfirmDialog(null, panel, NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); + option = JOptionPane.showConfirmDialog(null, panel, NbBundle.getMessage(FilesSetPanel.class, ruleDialogTitle), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); } while (option == JOptionPane.OK_OPTION && !panel.isValidDefinition()); // While adding new ruleset(selectedSet == null), if rule set with same name already exists, do not add to the filesSets hashMap. // In case of editing an existing ruleset(selectedSet != null), following check is not performed. if (this.filesSets.containsKey(panel.getFilesSetName()) && selectedSet == null) { MessageNotifyUtil.Message.error(NbBundle.getMessage(this.getClass(), - "InterestingItemDefsPanel.doFileSetsDialog.duplicateRuleSet.text", + "FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text", panel.getFilesSetName())); return; } @@ -366,7 +411,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // Preserve the existing rules from the set being edited. rules.putAll(selectedSet.getRules()); } - this.replaceFilesSet(selectedSet, panel.getFilesSetName(), panel.getFilesSetDescription(), panel.getFileSetIgnoresKnownFiles(), rules); + this.replaceFilesSet(selectedSet, panel.getFilesSetName(), panel.getFilesSetDescription(), panel.getFileSetIgnoresKnownFiles(), panel.getFileSetIgnoresUnallocatedSpace(), rules); } } @@ -382,17 +427,18 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSetRulePanel panel; if (selectedRule != null) { // Editing an existing rule definition. - panel = new FilesSetRulePanel(selectedRule, okButton, cancelButton); + panel = new FilesSetRulePanel(selectedRule, okButton, cancelButton, panelType); } else { // Creating a new rule definition. - panel = new FilesSetRulePanel(okButton, cancelButton); + panel = new FilesSetRulePanel(okButton, cancelButton, panelType); } // Do a dialog box with the files set panel until the user either enters // a valid definition or cancels. Note that the panel gives the user // feedback when isValidDefinition() is called. int option = JOptionPane.OK_OPTION; do { - option = JOptionPane.showOptionDialog(null, panel, NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[]{okButton, cancelButton}, okButton); + option = JOptionPane.showOptionDialog(null, panel, NbBundle.getMessage(FilesSetPanel.class, ruleDialogTitle), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[]{okButton, cancelButton}, okButton); + } while (option == JOptionPane.OK_OPTION && !panel.isValidRuleDefinition()); if (option == JOptionPane.OK_OPTION) { @@ -412,7 +458,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // Add the new/edited files set definition, replacing any previous // definition with the same name and refreshing the display. - this.replaceFilesSet(selectedSet, selectedSet.getName(), selectedSet.getDescription(), selectedSet.ignoresKnownFiles(), rules); + this.replaceFilesSet(selectedSet, selectedSet.getName(), selectedSet.getDescription(), selectedSet.ignoresKnownFiles(), selectedSet.ingoresUnallocatedSpace(), rules); // Select the new/edited rule. Queue it up so it happens after the // selection listeners react to the selection of the "new" files @@ -428,15 +474,17 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp * owned by this panel. If there is a definition with the same name, it will * be replaced, so this is an add/edit operation. * - * @param oldSet A set to replace, null if the new set is not a - * replacement. - * @param name The name of the files set. - * @param description The description of the files set. - * @param ignoresKnownFiles Whether or not the files set ignores known - * files. - * @param rules The set membership rules for the set. + * @param oldSet A set to replace, null if the new set is + * not a replacement. + * @param name The name of the files set. + * @param description The description of the files set. + * @param ignoresKnownFiles Whether or not the files set ignores + * known files. + * @param rules The set membership rules for the set. + * @param processesUnallocatedSpace Whether or not this set of rules + * processes unallocated space */ - void replaceFilesSet(FilesSet oldSet, String name, String description, boolean ignoresKnownFiles, Map rules) { + void replaceFilesSet(FilesSet oldSet, String name, String description, boolean ignoresKnownFiles, boolean ignoresUnallocatedSpace, Map rules) { if (oldSet != null) { // Remove the set to be replaced from the working copy if the files // set definitions. @@ -445,12 +493,12 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // Make the new/edited set definition and add it to the working copy of // the files set definitions. - FilesSet newSet = new FilesSet(name, description, ignoresKnownFiles, rules); + FilesSet newSet = new FilesSet(name, description, ignoresKnownFiles, ignoresUnallocatedSpace, rules); this.filesSets.put(newSet.getName(), newSet); // Redo the list model for the files set list component, which will make // everything stays sorted as in the working copy tree set. - InterestingItemDefsPanel.this.setsListModel.clear(); + FilesSetDefsPanel.this.setsListModel.clear(); for (FilesSet set : this.filesSets.values()) { this.setsListModel.addElement(set); } @@ -513,6 +561,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp equalitySignComboBox = new javax.swing.JComboBox(); fileSizeSpinner = new javax.swing.JSpinner(); fileSizeUnitComboBox = new javax.swing.JComboBox(); + ingoreUnallocCheckbox = new javax.swing.JCheckBox(); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -521,11 +570,11 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp jPanel1.setFont(jPanel1.getFont().deriveFont(jPanel1.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); jLabel6.setFont(jLabel6.getFont().deriveFont(jLabel6.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel6.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.jLabel6.text")); // NOI18N newRuleButton.setFont(newRuleButton.getFont().deriveFont(newRuleButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); 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(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.newRuleButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.newRuleButton.text")); // NOI18N newRuleButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { newRuleButtonActionPerformed(evt); @@ -535,12 +584,12 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp typeButtonGroup.add(filesRadioButton); filesRadioButton.setFont(filesRadioButton.getFont().deriveFont(filesRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); filesRadioButton.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(filesRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.filesRadioButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(filesRadioButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.filesRadioButton.text")); // NOI18N filesRadioButton.setEnabled(false); editRuleButton.setFont(editRuleButton.getFont().deriveFont(editRuleButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); 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(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.editRuleButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(editRuleButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.editRuleButton.text")); // NOI18N editRuleButton.setEnabled(false); editRuleButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -549,7 +598,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp }); rulesListLabel.setFont(rulesListLabel.getFont().deriveFont(rulesListLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(rulesListLabel, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.rulesListLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(rulesListLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.rulesListLabel.text")); // NOI18N rulesListScrollPane.setFont(rulesListScrollPane.getFont().deriveFont(rulesListScrollPane.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -558,6 +607,8 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp rulesListScrollPane.setViewportView(rulesList); setDescScrollPanel.setFont(setDescScrollPanel.getFont().deriveFont(setDescScrollPanel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); + setDescScrollPanel.setMinimumSize(new java.awt.Dimension(10, 22)); + setDescScrollPanel.setPreferredSize(new java.awt.Dimension(14, 40)); setDescriptionTextArea.setEditable(false); setDescriptionTextArea.setBackground(new java.awt.Color(240, 240, 240)); @@ -571,7 +622,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp editSetButton.setFont(editSetButton.getFont().deriveFont(editSetButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); editSetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(editSetButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.editSetButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(editSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.editSetButton.text")); // NOI18N editSetButton.setEnabled(false); editSetButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -587,59 +638,49 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp fileNameButtonGroup.add(fileNameExtensionRadioButton); fileNameExtensionRadioButton.setFont(fileNameExtensionRadioButton.getFont().deriveFont(fileNameExtensionRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(fileNameExtensionRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.fileNameExtensionRadioButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(fileNameExtensionRadioButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.fileNameExtensionRadioButton.text")); // NOI18N fileNameExtensionRadioButton.setEnabled(false); jLabel3.setFont(jLabel3.getFont().deriveFont(jLabel3.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel3.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel3.text")); // NOI18N fileNameTextField.setEditable(false); fileNameTextField.setFont(fileNameTextField.getFont().deriveFont(fileNameTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - fileNameTextField.setText(org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.fileNameTextField.text")); // NOI18N - fileNameTextField.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - fileNameTextFieldActionPerformed(evt); - } - }); + fileNameTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.fileNameTextField.text")); // NOI18N jLabel5.setFont(jLabel5.getFont().deriveFont(jLabel5.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel5.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel5.text")); // NOI18N fileNameButtonGroup.add(fileNameRadioButton); fileNameRadioButton.setFont(fileNameRadioButton.getFont().deriveFont(fileNameRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(fileNameRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.fileNameRadioButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(fileNameRadioButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.fileNameRadioButton.text")); // NOI18N fileNameRadioButton.setEnabled(false); rulePathConditionTextField.setEditable(false); rulePathConditionTextField.setFont(rulePathConditionTextField.getFont().deriveFont(rulePathConditionTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - rulePathConditionTextField.setText(org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.rulePathConditionTextField.text")); // NOI18N + rulePathConditionTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.rulePathConditionTextField.text")); // NOI18N ignoreKnownFilesCheckbox.setFont(ignoreKnownFilesCheckbox.getFont().deriveFont(ignoreKnownFilesCheckbox.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(ignoreKnownFilesCheckbox, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(ignoreKnownFilesCheckbox, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ignoreKnownFilesCheckbox.text")); // NOI18N ignoreKnownFilesCheckbox.setEnabled(false); - ignoreKnownFilesCheckbox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - ignoreKnownFilesCheckboxActionPerformed(evt); - } - }); fileNameRegexCheckbox.setFont(fileNameRegexCheckbox.getFont().deriveFont(fileNameRegexCheckbox.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(fileNameRegexCheckbox, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.fileNameRegexCheckbox.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(fileNameRegexCheckbox, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.fileNameRegexCheckbox.text")); // NOI18N fileNameRegexCheckbox.setEnabled(false); separator.setOrientation(javax.swing.SwingConstants.VERTICAL); setsListLabel.setFont(setsListLabel.getFont().deriveFont(setsListLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(setsListLabel, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.setsListLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(setsListLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.setsListLabel.text")); // NOI18N typeButtonGroup.add(bothRadioButton); bothRadioButton.setFont(bothRadioButton.getFont().deriveFont(bothRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(bothRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.bothRadioButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(bothRadioButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.bothRadioButton.text")); // NOI18N bothRadioButton.setEnabled(false); deleteSetButton.setFont(deleteSetButton.getFont().deriveFont(deleteSetButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); deleteSetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(deleteSetButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.deleteSetButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(deleteSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.deleteSetButton.text")); // NOI18N deleteSetButton.setEnabled(false); deleteSetButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -649,7 +690,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp deleteRuleButton.setFont(deleteRuleButton.getFont().deriveFont(deleteRuleButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); 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(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.deleteRuleButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.deleteRuleButton.text")); // NOI18N deleteRuleButton.setEnabled(false); deleteRuleButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -659,7 +700,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp newSetButton.setFont(newSetButton.getFont().deriveFont(newSetButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); newSetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(newSetButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.newSetButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(newSetButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.newSetButton.text")); // NOI18N newSetButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { newSetButtonActionPerformed(evt); @@ -667,26 +708,21 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp }); jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel2.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel2.text")); // NOI18N typeButtonGroup.add(dirsRadioButton); dirsRadioButton.setFont(dirsRadioButton.getFont().deriveFont(dirsRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(dirsRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.dirsRadioButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(dirsRadioButton, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.dirsRadioButton.text")); // NOI18N dirsRadioButton.setEnabled(false); - dirsRadioButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - dirsRadioButtonActionPerformed(evt); - } - }); jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel1.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel1.text")); // NOI18N jLabel4.setFont(jLabel4.getFont().deriveFont(jLabel4.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel4.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel4.text")); // NOI18N rulePathConditionRegexCheckBox.setFont(rulePathConditionRegexCheckBox.getFont().deriveFont(rulePathConditionRegexCheckBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(rulePathConditionRegexCheckBox, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.rulePathConditionRegexCheckBox.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(rulePathConditionRegexCheckBox, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.rulePathConditionRegexCheckBox.text")); // NOI18N rulePathConditionRegexCheckBox.setEnabled(false); jScrollPane2.setFont(jScrollPane2.getFont().deriveFont(jScrollPane2.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -697,19 +733,19 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp jTextArea1.setFont(jTextArea1.getFont().deriveFont(jTextArea1.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); jTextArea1.setLineWrap(true); jTextArea1.setRows(3); - jTextArea1.setText(org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jTextArea1.text")); // NOI18N + jTextArea1.setText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.interesting.jTextArea1.text")); // NOI18N jTextArea1.setWrapStyleWord(true); jScrollPane2.setViewportView(jTextArea1); - org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel7.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel7.text")); // NOI18N - mimeTypeComboBox.setEditable(true); + mimeTypeComboBox.setBackground(new java.awt.Color(240, 240, 240)); mimeTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] {""})); mimeTypeComboBox.setEnabled(false); mimeTypeComboBox.setMinimumSize(new java.awt.Dimension(0, 20)); mimeTypeComboBox.setPreferredSize(new java.awt.Dimension(12, 20)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel8.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel8.text")); // NOI18N equalitySignComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "=", ">", "≥", "<", "≤" })); equalitySignComboBox.setEnabled(false); @@ -717,105 +753,103 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp fileSizeSpinner.setEnabled(false); fileSizeSpinner.setMinimumSize(new java.awt.Dimension(2, 20)); - fileSizeUnitComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.InterestingItemDefsPanel_bytes(), Bundle.InterestingItemDefsPanel_kiloBytes(), Bundle.InterestingItemDefsPanel_megaBytes(), Bundle.InterestingItemDefsPanel_gigaBytes() })); + fileSizeUnitComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.FilesSetDefsPanel_bytes(), Bundle.FilesSetDefsPanel_kiloBytes(), Bundle.FilesSetDefsPanel_megaBytes(), Bundle.FilesSetDefsPanel_gigaBytes() })); fileSizeUnitComboBox.setEnabled(false); + org.openide.awt.Mnemonics.setLocalizedText(ingoreUnallocCheckbox, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingoreUnallocCheckbox.text")); // NOI18N + ingoreUnallocCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.ingoreUnallocCheckbox.toolTipText")); // NOI18N + ingoreUnallocCheckbox.setEnabled(false); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(setsListLabel) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 314, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(newSetButton) + .addGap(9, 9, 9) + .addComponent(editSetButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(deleteSetButton)) + .addComponent(setsListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 344, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(360, 360, 360) + .addGap(101, 101, 101) + .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(dirsRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(bothRadioButton)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(105, 105, 105) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(fileNameRadioButton) + .addGap(4, 4, 4) + .addComponent(fileNameExtensionRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(fileNameRegexCheckbox)) + .addComponent(rulePathConditionRegexCheckBox))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(rulesListLabel) - .addComponent(jLabel5) - .addComponent(ignoreKnownFilesCheckbox) - .addComponent(jLabel6)) - .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(setsListLabel) - .addComponent(setsListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 314, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 314, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(newRuleButton) .addGap(18, 18, 18) - .addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(editRuleButton) + .addGap(18, 18, 18) + .addComponent(deleteRuleButton)) .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(newSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(editSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(deleteSetButton))) - .addGap(12, 12, 12) + .addComponent(ignoreKnownFilesCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jLabel5) + .addComponent(jLabel6))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(29, 29, 29) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(20, 20, 20) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel3) - .addComponent(jLabel2)) - .addGap(6, 6, 6)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addComponent(jLabel4) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED))) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(rulePathConditionTextField, javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(fileNameTextField))) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel7) - .addComponent(jLabel8)) - .addGap(6, 6, 6) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() - .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fileSizeSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(8, 8, 8)) - .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))) + .addComponent(jLabel7) + .addComponent(jLabel8)) + .addGap(18, 18, 18)) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel3) + .addComponent(jLabel2)) + .addGap(6, 6, 6)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)))) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mimeTypeComboBox, 0, 313, Short.MAX_VALUE) + .addComponent(rulePathConditionTextField) .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(setDescScrollPanel) - .addComponent(rulesListScrollPane)) - .addGap(7, 7, 7)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel1) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(92, 92, 92) - .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(dirsRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(bothRadioButton)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(newRuleButton) - .addGap(18, 18, 18) - .addComponent(editRuleButton) - .addGap(18, 18, 18) - .addComponent(deleteRuleButton)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(96, 96, 96) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(fileNameRadioButton) - .addGap(4, 4, 4) - .addComponent(fileNameExtensionRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(fileNameRegexCheckbox)) - .addComponent(rulePathConditionRegexCheckBox)))) - .addGap(4, 4, 4))))) - .addGap(23, 23, 23)) + .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileSizeSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(fileNameTextField))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(setDescScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)))) + .addGap(18, 18, 18)) ); + + jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteSetButton, editSetButton, newSetButton}); + jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() @@ -826,10 +860,10 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(setsListLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(setsListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 354, Short.MAX_VALUE) + .addComponent(setsListScrollPane) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newSetButton) @@ -839,22 +873,24 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(jLabel6) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel5) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(ignoreKnownFilesCheckbox) + .addGap(1, 1, 1) + .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(6, 6, 6) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ignoreKnownFilesCheckbox) + .addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(rulesListLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 67, Short.MAX_VALUE) - .addGap(10, 10, 10) + .addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newRuleButton) .addComponent(editRuleButton) .addComponent(deleteRuleButton)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel1) - .addGap(2, 2, 2) + .addGap(8, 8, 8) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(filesRadioButton) @@ -869,23 +905,23 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(fileNameRadioButton) .addComponent(fileNameExtensionRadioButton) .addComponent(fileNameRegexCheckbox)) - .addGap(14, 14, 14) + .addGap(16, 16, 16) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(rulePathConditionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGap(7, 7, 7) .addComponent(rulePathConditionRegexCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel7) .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(16, 16, 16) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel8) .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(13, 13, 13))) + .addGap(5, 5, 5))) .addGap(5, 5, 5)))) ); @@ -897,7 +933,9 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1) + .addGroup(layout.createSequentialGroup() + .addComponent(jScrollPane1) + .addGap(0, 0, 0)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -905,10 +943,6 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp ); }// //GEN-END:initComponents - private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_dirsRadioButtonActionPerformed - private void newSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newSetButtonActionPerformed this.doFileSetsDialog(null); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); @@ -923,7 +957,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp Map rules = new HashMap<>(oldSet.getRules()); FilesSet.Rule selectedRule = this.rulesList.getSelectedValue(); rules.remove(selectedRule.getUuid()); - this.replaceFilesSet(oldSet, oldSet.getName(), oldSet.getDescription(), oldSet.ignoresKnownFiles(), rules); + this.replaceFilesSet(oldSet, oldSet.getName(), oldSet.getDescription(), oldSet.ignoresKnownFiles(), oldSet.ingoresUnallocatedSpace(), rules); if (!this.rulesListModel.isEmpty()) { this.rulesList.setSelectedIndex(0); } else { @@ -947,10 +981,6 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_deleteSetButtonActionPerformed - private void ignoreKnownFilesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ignoreKnownFilesCheckboxActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_ignoreKnownFilesCheckboxActionPerformed - private void editSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editSetButtonActionPerformed this.doFileSetsDialog(this.setsList.getSelectedValue()); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); @@ -966,10 +996,6 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_newRuleButtonActionPerformed - private void fileNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileNameTextFieldActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_fileNameTextFieldActionPerformed - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton bothRadioButton; private javax.swing.JButton deleteRuleButton; @@ -987,6 +1013,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp private javax.swing.JComboBox fileSizeUnitComboBox; private javax.swing.JRadioButton filesRadioButton; private javax.swing.JCheckBox ignoreKnownFilesCheckbox; + private javax.swing.JCheckBox ingoreUnallocCheckbox; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.form index fa5e501cf3..0b5872a5a5 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.form @@ -19,13 +19,18 @@ + + - - + + + + + @@ -42,7 +47,10 @@ - + + + + @@ -52,7 +60,7 @@ - + @@ -114,5 +122,15 @@ + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.java index 83f83be276..733902b1ec 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2014-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,18 +21,36 @@ package org.sleuthkit.autopsy.modules.interestingitems; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel.PANEL_TYPE; /** * A panel that allows a user to create and edit interesting files set * definitions. */ public class FilesSetPanel extends javax.swing.JPanel { + @NbBundle.Messages({"FilesSetPanel.ingest.title=File Ingest Filter", "FilesSetPanel.ingest.createNewFilter=Create new file ingest filter..."}) + + private static final String CREATE_NEW_FILE_INGEST_FILTER = Bundle.FilesSetPanel_ingest_createNewFilter(); + /** + * @return the CREATE_NEW_FILE_INGEST_FILTER + */ + public static String getCreateNewFileIngestFilterString() { + return CREATE_NEW_FILE_INGEST_FILTER; + } + + /** * Construct a files set panel in create mode. */ - FilesSetPanel() { + FilesSetPanel(PANEL_TYPE panelType) { initComponents(); + if (panelType == PANEL_TYPE.FILE_INGEST_FILTERS) { + ignoreKnownFilesCheckbox.setVisible(false); + org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.ingest.nameLabel.text")); // NOI18N + } else { + ignoreUnallocCheckbox.setVisible(false); + } } /** @@ -40,11 +58,17 @@ public class FilesSetPanel extends javax.swing.JPanel { * * @param filesSet The files set to be edited. */ - FilesSetPanel(FilesSet filesSet) { + FilesSetPanel(FilesSet filesSet, PANEL_TYPE panelType) { initComponents(); + if (panelType == PANEL_TYPE.FILE_INGEST_FILTERS) { + ignoreKnownFilesCheckbox.setVisible(false); + } else { + ignoreUnallocCheckbox.setVisible(false); + } this.nameTextField.setText(filesSet.getName()); this.descTextArea.setText(filesSet.getDescription()); this.ignoreKnownFilesCheckbox.setSelected(filesSet.ignoresKnownFiles()); + this.ignoreUnallocCheckbox.setSelected(filesSet.ingoresUnallocatedSpace()); } /** @@ -61,6 +85,25 @@ public class FilesSetPanel extends javax.swing.JPanel { NotifyDescriptor.WARNING_MESSAGE); DialogDisplayer.getDefault().notify(notifyDesc); return false; + } else { + // The FileIngestFilters have reserved names for default filter, and creating a new filter from the jComboBox + // These names if used would have undefined results, so prohibiting the user from using them is necessary + for (FilesSet filesSet : FilesSetsManager.getStandardFileIngestFilters()) { + if (this.nameTextField.getText().equals(filesSet.getName())) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.messages.filesSetsReservedName"), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } + if (this.nameTextField.getText().equals(getCreateNewFileIngestFilterString())) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.messages.filesSetsReservedName"), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } } return true; } @@ -71,7 +114,8 @@ public class FilesSetPanel extends javax.swing.JPanel { * @return A name string. */ String getFilesSetName() { - return this.nameTextField.getText(); + String returnValue = this.nameTextField.getText(); + return returnValue; } /** @@ -94,6 +138,13 @@ public class FilesSetPanel extends javax.swing.JPanel { return this.ignoreKnownFilesCheckbox.isSelected(); } + /** + * + */ + boolean getFileSetIgnoresUnallocatedSpace() { + return ignoreUnallocCheckbox.isSelected(); + } + /** * 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 @@ -109,8 +160,9 @@ public class FilesSetPanel extends javax.swing.JPanel { descScrollPanel = new javax.swing.JScrollPane(); descTextArea = new javax.swing.JTextArea(); ignoreKnownFilesCheckbox = new javax.swing.JCheckBox(); + ignoreUnallocCheckbox = new javax.swing.JCheckBox(); - org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.nameLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.interesting.nameLabel.text")); // NOI18N descPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.descPanel.border.title"))); // NOI18N @@ -137,6 +189,9 @@ public class FilesSetPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(ignoreKnownFilesCheckbox, org.openide.util.NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.ignoreKnownFilesCheckbox.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(ignoreUnallocCheckbox, org.openide.util.NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.ignoreUnallocCheckbox.text")); // NOI18N + ignoreUnallocCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.ignoreUnallocCheckbox.toolTipText")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -144,12 +199,16 @@ public class FilesSetPanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(descPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) .addComponent(nameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 299, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(descPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(ignoreKnownFilesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(ignoreKnownFilesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(ignoreUnallocCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( @@ -162,16 +221,20 @@ public class FilesSetPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(descPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(ignoreKnownFilesCheckbox) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ignoreKnownFilesCheckbox) + .addComponent(ignoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap()) ); }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel descPanel; private javax.swing.JScrollPane descScrollPanel; private javax.swing.JTextArea descTextArea; private javax.swing.JCheckBox ignoreKnownFilesCheckbox; + private javax.swing.JCheckBox ignoreUnallocCheckbox; private javax.swing.JLabel nameLabel; private javax.swing.JTextField nameTextField; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form index 72b506199a..4777c108b4 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form @@ -42,7 +42,7 @@ - + @@ -111,7 +111,7 @@ - + @@ -199,9 +199,6 @@ - - - @@ -252,7 +249,7 @@ - + @@ -370,17 +367,17 @@ - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index 29d56e6f8a..f53700c34e 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -36,9 +36,10 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel.PANEL_TYPE; /** - * A panel that allows a user to create and edit interesting files set + * A panel that allows a user to create and edit files set * membership rules. */ final class FilesSetRulePanel extends javax.swing.JPanel { @@ -57,17 +58,28 @@ final class FilesSetRulePanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(FilesSetRulePanel.class.getName()); private static final String SLEUTHKIT_PATH_SEPARATOR = "/"; // NON-NLS - private static final List ILLEGAL_FILE_NAME_CHARS = InterestingItemDefsManager.getIllegalFileNameChars(); - private static final List ILLEGAL_FILE_PATH_CHARS = InterestingItemDefsManager.getIllegalFilePathChars(); + private static final List ILLEGAL_FILE_NAME_CHARS = FilesSetsManager.getIllegalFileNameChars(); + private static final List ILLEGAL_FILE_PATH_CHARS = FilesSetsManager.getIllegalFilePathChars(); private JButton okButton; private JButton cancelButton; /** * Constructs a files set rule panel in create rule mode. */ - FilesSetRulePanel(JButton okButton, JButton cancelButton) { + FilesSetRulePanel(JButton okButton, JButton cancelButton, PANEL_TYPE panelType) { initComponents(); - populateMimeTypesComboBox(); + if (panelType == FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS) { //Hide the mimetype settings when this is displaying a FileSet rule instead of a interesting item rule + mimeTypeComboBox.setVisible(false); + mimeCheck.setVisible(false); + fileSizeComboBox.setVisible(false); + fileSizeCheck.setVisible(false); + equalitySymbolComboBox.setVisible(false); + fileSizeSpinner.setVisible(false); + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ingest.jLabel5.text")); // NOI18N + + } else { + populateMimeTypesComboBox(); + } populateComponentsWithDefaultValues(); this.setButtons(okButton, cancelButton); } @@ -77,15 +89,25 @@ final class FilesSetRulePanel extends javax.swing.JPanel { * * @param rule The files set rule to be edited. */ - FilesSetRulePanel(FilesSet.Rule rule, JButton okButton, JButton cancelButton) { + FilesSetRulePanel(FilesSet.Rule rule, JButton okButton, JButton cancelButton, PANEL_TYPE panelType) { initComponents(); + if (panelType == FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS) { //Hide the mimetype settings when this is displaying a FileSet rule instead of a interesting item rule + mimeTypeComboBox.setVisible(false); + mimeCheck.setVisible(false); + fileSizeComboBox.setVisible(false); + fileSizeCheck.setVisible(false); + equalitySymbolComboBox.setVisible(false); + fileSizeSpinner.setVisible(false); + } else { + populateMimeTypesComboBox(); + populateMimeConditionComponents(rule); + populateSizeConditionComponents(rule); + } populateMimeTypesComboBox(); populateRuleNameComponent(rule); populateTypeConditionComponents(rule); populateNameConditionComponents(rule); populatePathConditionComponents(rule); - populateMimeConditionComponents(rule); - populateSizeConditionComponents(rule); this.setButtons(okButton, cancelButton); } @@ -229,8 +251,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { case DIRECTORIES: this.dirsRadioButton.setSelected(true); break; - case FILES_AND_DIRECTORIES: - this.filesAndDirsRadioButton.setSelected(true); + case ALL: + this.allRadioButton.setSelected(true); break; } } @@ -273,7 +295,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { /** * Returns whether or not the data entered in the panel constitutes a valid - * interesting files set membership rule definition, displaying a dialog + * files set membership rule definition, displaying a dialog * explaining the deficiency if the definition is invalid. * * @return True if the definition is valid, false otherwise. @@ -457,7 +479,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } else if (this.dirsRadioButton.isSelected()) { return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES); } else { - return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES_AND_DIRECTORIES); + return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.ALL); } } @@ -579,7 +601,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { fileSizeCheck = new javax.swing.JCheckBox(); filesRadioButton = new javax.swing.JRadioButton(); dirsRadioButton = new javax.swing.JRadioButton(); - filesAndDirsRadioButton = new javax.swing.JRadioButton(); + allRadioButton = new javax.swing.JRadioButton(); org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameLabel.text")); // NOI18N @@ -598,11 +620,6 @@ final class FilesSetRulePanel extends javax.swing.JPanel { nameButtonGroup.add(fullNameRadioButton); org.openide.awt.Mnemonics.setLocalizedText(fullNameRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fullNameRadioButton.text")); // NOI18N fullNameRadioButton.setEnabled(false); - fullNameRadioButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - fullNameRadioButtonActionPerformed(evt); - } - }); nameButtonGroup.add(extensionRadioButton); org.openide.awt.Mnemonics.setLocalizedText(extensionRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.extensionRadioButton.text")); // NOI18N @@ -621,7 +638,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(pathSeparatorInfoLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathSeparatorInfoLabel.text")); // NOI18N pathSeparatorInfoLabel.setEnabled(false); - org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel5.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.interesting.jLabel5.text")); // NOI18N mimeTypeComboBox.setEditable(true); mimeTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] {""})); @@ -633,7 +650,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { fileSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.FilesSetRulePanel_bytes(), Bundle.FilesSetRulePanel_kiloBytes(), Bundle.FilesSetRulePanel_megaBytes(), Bundle.FilesSetRulePanel_gigaBytes() })); fileSizeComboBox.setEnabled(false); - fileSizeSpinner.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(0), Integer.valueOf(0), null, Integer.valueOf(1))); + fileSizeSpinner.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1)); fileSizeSpinner.setEnabled(false); org.openide.awt.Mnemonics.setLocalizedText(nameCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameCheck.text")); // NOI18N @@ -680,11 +697,11 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } }); - typeButtonGroup.add(filesAndDirsRadioButton); - org.openide.awt.Mnemonics.setLocalizedText(filesAndDirsRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.filesAndDirsRadioButton.text")); // NOI18N - filesAndDirsRadioButton.addActionListener(new java.awt.event.ActionListener() { + typeButtonGroup.add(allRadioButton); + org.openide.awt.Mnemonics.setLocalizedText(allRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.allRadioButton.text")); // NOI18N + allRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - filesAndDirsRadioButtonActionPerformed(evt); + allRadioButtonActionPerformed(evt); } }); @@ -711,7 +728,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(dirsRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(filesAndDirsRadioButton))) + .addComponent(allRadioButton))) .addGap(0, 0, Short.MAX_VALUE)))) .addGroup(layout.createSequentialGroup() .addContainerGap() @@ -762,7 +779,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { .addComponent(jLabel1) .addComponent(filesRadioButton) .addComponent(dirsRadioButton) - .addComponent(filesAndDirsRadioButton)) + .addComponent(allRadioButton)) .addGap(5, 5, 5) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -867,22 +884,18 @@ final class FilesSetRulePanel extends javax.swing.JPanel { this.setComponentsForSearchType(); }//GEN-LAST:event_dirsRadioButtonActionPerformed - private void filesAndDirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesAndDirsRadioButtonActionPerformed + private void allRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allRadioButtonActionPerformed this.setComponentsForSearchType(); - }//GEN-LAST:event_filesAndDirsRadioButtonActionPerformed - - private void fullNameRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fullNameRadioButtonActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_fullNameRadioButtonActionPerformed + }//GEN-LAST:event_allRadioButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JRadioButton allRadioButton; private javax.swing.JRadioButton dirsRadioButton; private javax.swing.JComboBox equalitySymbolComboBox; private javax.swing.JRadioButton extensionRadioButton; private javax.swing.JCheckBox fileSizeCheck; private javax.swing.JComboBox fileSizeComboBox; private javax.swing.JSpinner fileSizeSpinner; - private javax.swing.JRadioButton filesAndDirsRadioButton; private javax.swing.JRadioButton filesRadioButton; private javax.swing.JRadioButton fullNameRadioButton; private javax.swing.JLabel jLabel1; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetsManager.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetsManager.java new file mode 100755 index 0000000000..6350805ee6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetsManager.java @@ -0,0 +1,188 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 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.modules.interestingitems; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Observable; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MetaTypeCondition; + +/** + * Provides access to collections of FilesSet definitions persisted to disk. + * Clients receive copies of the most recent FilesSet definitions for + * Interesting Items or File Ingest Filters via synchronized methods, allowing + * the definitions to be safely published to multiple threads. + */ +public final class FilesSetsManager extends Observable { + + @NbBundle.Messages({"FilesSetsManager.allFilesAndDirectories=All Files and Directories", + "FilesSetsManager.allFilesDirectoriesAndUnallocated=All Files, Directories, and Unallocated Space"}) + private static final List ILLEGAL_FILE_NAME_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", "/", ":", "*", "?", "\"", "<", ">"))); + private static final List ILLEGAL_FILE_PATH_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", ":", "*", "?", "\"", "<", ">"))); + private static final String LEGACY_FILES_SET_DEFS_FILE_NAME = "InterestingFilesSetDefs.xml"; //NON-NLS + private static final String INTERESTING_FILES_SET_DEFS_NAME = "InterestingFileSets.settings"; + private static final String FILE_INGEST_FILTER_DEFS_NAME = "FileIngestFilterDefs.settings"; + private static final Object FILE_INGEST_FILTER_LOCK = new Object(); + private static final Object INTERESTING_FILES_SET_LOCK = new Object(); + private static FilesSetsManager instance; + private static final FilesSet FILES_DIRS_INGEST_FILTER = new FilesSet( + Bundle.FilesSetsManager_allFilesAndDirectories(), Bundle.FilesSetsManager_allFilesAndDirectories(), false, true, new HashMap() { + { + put(Bundle.FilesSetsManager_allFilesAndDirectories(), + new Rule(Bundle.FilesSetsManager_allFilesAndDirectories(), null, + new MetaTypeCondition(MetaTypeCondition.Type.ALL), null, null, null)); + } + }); + private static final FilesSet FILES_DIRS_UNALLOC_INGEST_FILTER = new FilesSet( + Bundle.FilesSetsManager_allFilesDirectoriesAndUnallocated(), Bundle.FilesSetsManager_allFilesDirectoriesAndUnallocated(), + false, false, new HashMap() { + { + put(Bundle.FilesSetsManager_allFilesDirectoriesAndUnallocated(), + new Rule(Bundle.FilesSetsManager_allFilesDirectoriesAndUnallocated(), null, + new MetaTypeCondition(MetaTypeCondition.Type.ALL), null, null, null)); + } + }); + + /** + * Gets the FilesSet definitions manager singleton. + */ + public synchronized static FilesSetsManager getInstance() { + if (instance == null) { + instance = new FilesSetsManager(); + } + return instance; + } + + /** + * Gets the set of chars deemed to be illegal in file names (Windows). + * + * @return A list of characters. + */ + static List getIllegalFileNameChars() { + return FilesSetsManager.ILLEGAL_FILE_NAME_CHARS; + } + + /** + * Gets the set of chars deemed to be illegal in file path + * (SleuthKit/Windows). + * + * @return A list of characters. + */ + static List getIllegalFilePathChars() { + return FilesSetsManager.ILLEGAL_FILE_PATH_CHARS; + } + + /** + * Get a list of default FileIngestFilters. + * + * @return a list of FilesSets which cover default options. + */ + public static List getStandardFileIngestFilters() { + return Arrays.asList(FILES_DIRS_UNALLOC_INGEST_FILTER, FILES_DIRS_INGEST_FILTER); + } + + /** + * Get the filter that should be used as the default value, if no filter is + * specified. + * + * @return FILES_DIRS_UNALLOC_INGEST_FILTER + */ + public static FilesSet getDefaultFilter() { + return FILES_DIRS_UNALLOC_INGEST_FILTER; + } + + /** + * Gets a copy of the current interesting files set definitions. + * + * @return A map of interesting files set names to interesting file sets, + * possibly empty. + */ + Map getInterestingFilesSets() throws FilesSetsManagerException { + synchronized (INTERESTING_FILES_SET_LOCK) { + return InterestingItemsFilesSetSettings.readDefinitionsFile(INTERESTING_FILES_SET_DEFS_NAME, LEGACY_FILES_SET_DEFS_FILE_NAME); + } + } + + /** + * Gets a copy of the current ingest file set definitions. + * + * The defaults are not included so that they will not show up in the + * editor. + * + * @return A map of FilesSet names to file ingest sets, possibly empty. + */ + public Map getCustomFileIngestFilters() throws FilesSetsManagerException { + synchronized (FILE_INGEST_FILTER_LOCK) { + return FileSetsDefinitions.readSerializedDefinitions(FILE_INGEST_FILTER_DEFS_NAME); + } + } + + /** + * Sets the current interesting file sets definitions, replacing any + * previous definitions. + * + * @param filesSets A mapping of interesting files set names to files sets, + * used to enforce unique files set names. + */ + void setInterestingFilesSets(Map filesSets) throws FilesSetsManagerException { + synchronized (INTERESTING_FILES_SET_LOCK) { + InterestingItemsFilesSetSettings.writeDefinitionsFile(INTERESTING_FILES_SET_DEFS_NAME, filesSets); + this.setChanged(); + this.notifyObservers(); + } + } + + /** + * Sets the current interesting file sets definitions, replacing any + * previous definitions. + * + * @param filesSets A mapping of file ingest filters names to files sets, + * used to enforce unique files set names. + */ + void setCustomFileIngestFilters(Map filesSets) throws FilesSetsManagerException { + synchronized (FILE_INGEST_FILTER_LOCK) { + FileSetsDefinitions.writeDefinitionsFile(FILE_INGEST_FILTER_DEFS_NAME, filesSets); + } + } + + public static class FilesSetsManagerException extends Exception { + + FilesSetsManagerException() { + + } + + FilesSetsManagerException(String message) { + super(message); + } + + FilesSetsManagerException(String message, Throwable cause) { + super(message, cause); + } + + FilesSetsManagerException(Throwable cause) { + super(cause); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java deleted file mode 100755 index 95ab09eff1..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.interestingitems; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Observable; -import java.util.logging.Level; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import org.openide.util.io.NbObjectInputStream; -import org.openide.util.io.NbObjectOutputStream; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.PlatformUtil; -import org.sleuthkit.autopsy.coreutils.XMLUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -/** - * Provides access to interesting item definitions persisted to disk. Clients - * receive copies of the most recent interesting item definitions via - * synchronized methods, allowing the definitions to be safely published to - * multiple threads. - */ -final class InterestingItemDefsManager extends Observable { - - private static final List ILLEGAL_FILE_NAME_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", "/", ":", "*", "?", "\"", "<", ">"))); - private static final List ILLEGAL_FILE_PATH_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", ":", "*", "?", "\"", "<", ">"))); - private static final String LEGACY_FILES_SET_DEFS_FILE_NAME = "InterestingFilesSetDefs.xml"; //NON-NLS - private static final String INTERESTING_FILES_SET_DEFS_SERIALIZATION_NAME = "InterestingFileSets.settings"; - private static final String INTERESTING_FILES_SET_DEFS_SERIALIZATION_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + INTERESTING_FILES_SET_DEFS_SERIALIZATION_NAME; - private static final String LEGACY_FILE_SET_DEFS_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + LEGACY_FILES_SET_DEFS_FILE_NAME; - private static InterestingItemDefsManager instance; - - /** - * Gets the interesting item definitions manager singleton. - */ - synchronized static InterestingItemDefsManager getInstance() { - if (instance == null) { - instance = new InterestingItemDefsManager(); - } - return instance; - } - - /** - * Gets the set of chars deemed to be illegal in file names (Windows). - * - * @return A list of characters. - */ - static List getIllegalFileNameChars() { - return InterestingItemDefsManager.ILLEGAL_FILE_NAME_CHARS; - } - - /** - * Gets the set of chars deemed to be illegal in file path - * (SleuthKit/Windows). - * - * @return A list of characters. - */ - static List getIllegalFilePathChars() { - return InterestingItemDefsManager.ILLEGAL_FILE_PATH_CHARS; - } - - /** - * Gets a copy of the current interesting files set definitions. - * - * @return A map of interesting files set names to interesting file sets, - * possibly empty. - */ - synchronized Map getInterestingFilesSets() throws InterestingItemDefsManagerException { - return FilesSetXML.readDefinitionsFile(LEGACY_FILE_SET_DEFS_PATH); - } - - /** - * Sets the current interesting file sets definitions, replacing any - * previous definitions. - * - * @param filesSets A mapping of interesting files set names to files sets, - * used to enforce unique files set names. - */ - synchronized void setInterestingFilesSets(Map filesSets) throws InterestingItemDefsManagerException { - FilesSetXML.writeDefinitionsFile(INTERESTING_FILES_SET_DEFS_SERIALIZATION_PATH, filesSets); - this.setChanged(); - this.notifyObservers(); - } - - /** - * Reads and writes interesting files set definitions to and from disk in - * XML format. - */ - private final static class FilesSetXML { - - private static final Logger logger = Logger.getLogger(FilesSetXML.class.getName()); - private static final String XML_ENCODING = "UTF-8"; //NON-NLS - private static final List illegalFileNameChars = InterestingItemDefsManager.getIllegalFileNameChars(); - - // The following tags and attributes are identical to those used in the - // TSK Framework interesting files set definitions file schema. - private static final String FILE_SETS_ROOT_TAG = "INTERESTING_FILE_SETS"; //NON-NLS - private static final String FILE_SET_TAG = "INTERESTING_FILE_SET"; //NON-NLS - private static final String NAME_RULE_TAG = "NAME"; //NON-NLS - private static final String EXTENSION_RULE_TAG = "EXTENSION"; //NON-NLS - private static final String NAME_ATTR = "name"; //NON-NLS - private static final String RULE_UUID_ATTR = "ruleUUID"; //NON-NLS - private static final String DESC_ATTR = "description"; //NON-NLS - private static final String IGNORE_KNOWN_FILES_ATTR = "ignoreKnown"; //NON-NLS - private static final String TYPE_FILTER_ATTR = "typeFilter"; //NON-NLS - private static final String PATH_FILTER_ATTR = "pathFilter"; //NON-NLS - private static final String TYPE_FILTER_VALUE_FILES = "file"; //NON-NLS - private static final String TYPE_FILTER_VALUE_DIRS = "dir"; //NON-NLS - - private static final String REGEX_ATTR = "regex"; //NON-NLS - private static final String PATH_REGEX_ATTR = "pathRegex"; //NON-NLS - private static final String TYPE_FILTER_VALUE_FILES_AND_DIRS = "files_and_dirs"; //NON-NLS - private static final String UNNAMED_LEGACY_RULE_PREFIX = "Unnamed Rule "; // NON-NLS - private static int unnamedLegacyRuleCounter; - - /** - * Reads interesting file set definitions from an XML file. - * - * @param filePath Path of the set definitions file as a string. - * - * @return The set definitions in a map of set names to sets. - */ - // Note: This method takes a file path to support the possibility of - // multiple intersting files set definition files, e.g., one for - // definitions that ship with Autopsy and one for user definitions. - static Map readDefinitionsFile(String filePath) throws InterestingItemDefsManagerException { - Map filesSets = readSerializedDefinitions(); - - if (!filesSets.isEmpty()) { - return filesSets; - } - // Check if the legacy xml file exists. - File defsFile = new File(filePath); - if (!defsFile.exists()) { - return filesSets; - } - - // Check if the file can be read. - if (!defsFile.canRead()) { - logger.log(Level.SEVERE, "Interesting file sets definition file at {0} exists, but cannot be read", filePath); // NON-NLS - return filesSets; - } - - // Parse the XML in the file. - Document doc = XMLUtil.loadDoc(FilesSetXML.class, filePath); - if (doc == null) { - logger.log(Level.SEVERE, "Failed to parse interesting file sets definition file at {0}", filePath); // NON-NLS - return filesSets; - } - - // Get the root element. - Element root = doc.getDocumentElement(); - if (root == null) { - logger.log(Level.SEVERE, "Failed to get root {0} element tag of interesting file sets definition file at {1}", new Object[]{FilesSetXML.FILE_SETS_ROOT_TAG, filePath}); // NON-NLS - return filesSets; - } - - // Read in the files set definitions. - NodeList setElems = root.getElementsByTagName(FILE_SET_TAG); - for (int i = 0; i < setElems.getLength(); ++i) { - readFilesSet((Element) setElems.item(i), filesSets, filePath); - } - return filesSets; - } - - /** - * Reads the definitions from the serialization file - * - * @return the map representing settings saved to serialization file, - * empty set if the file does not exist. - * - * @throws InterestingItemDefsManagerException if file could not be read - */ - private static Map readSerializedDefinitions() throws InterestingItemDefsManagerException { - String filePath = INTERESTING_FILES_SET_DEFS_SERIALIZATION_PATH; - File fileSetFile = new File(filePath); - if (fileSetFile.exists()) { - try { - try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePath))) { - InterestingItemsFilesSetSettings filesSetsSettings = (InterestingItemsFilesSetSettings) in.readObject(); - return filesSetsSettings.getFilesSets(); - } - } catch (IOException | ClassNotFoundException ex) { - throw new InterestingItemDefsManagerException(String.format("Failed to read settings from %s", filePath), ex); - } - } else { - return new HashMap(); - } - } - - /** - * Reads in an interesting files set. - * - * @param setElem An interesting files set XML element - * @param filesSets A collection to which the set is to be added. - * @param filePath The source file, used for error reporting. - */ - private static void readFilesSet(Element setElem, Map filesSets, String filePath) { - // The file set must have a unique name. - String setName = setElem.getAttribute(FilesSetXML.NAME_ATTR); - if (setName.isEmpty()) { - logger.log(Level.SEVERE, "Found {0} element without required {1} attribute, ignoring malformed file set definition in interesting file sets definition file at {2}", new Object[]{FilesSetXML.FILE_SET_TAG, FilesSetXML.NAME_ATTR, filePath}); // NON-NLS - return; - } - if (filesSets.containsKey(setName)) { - logger.log(Level.SEVERE, "Found duplicate definition of set named {0} in interesting file sets definition file at {1}, discarding duplicate set", new Object[]{setName, filePath}); // NON-NLS - return; - } - - // The file set may have a description. The empty string is o.k. - String description = setElem.getAttribute(FilesSetXML.DESC_ATTR); - - // The file set may or may not ignore known files. The default behavior - // is to not ignore them. - String ignoreKnown = setElem.getAttribute(FilesSetXML.IGNORE_KNOWN_FILES_ATTR); - boolean ignoreKnownFiles = false; - if (!ignoreKnown.isEmpty()) { - ignoreKnownFiles = Boolean.parseBoolean(ignoreKnown); - } - - // Read file name set membership rules, if any. - FilesSetXML.unnamedLegacyRuleCounter = 1; - Map rules = new HashMap<>(); - NodeList nameRuleElems = setElem.getElementsByTagName(FilesSetXML.NAME_RULE_TAG); - for (int j = 0; j < nameRuleElems.getLength(); ++j) { - Element elem = (Element) nameRuleElems.item(j); - FilesSet.Rule rule = FilesSetXML.readFileNameRule(elem); - if (rule != null) { - if (!rules.containsKey(rule.getUuid())) { - rules.put(rule.getUuid(), rule); - } else { - logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in interesting file sets definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); // NON-NLS - return; - } - } else { - logger.log(Level.SEVERE, "Found malformed rule for set named {0} in interesting file sets definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); // NON-NLS - return; - } - } - - // Read file extension set membership rules, if any. - NodeList extRuleElems = setElem.getElementsByTagName(FilesSetXML.EXTENSION_RULE_TAG); - for (int j = 0; j < extRuleElems.getLength(); ++j) { - Element elem = (Element) extRuleElems.item(j); - FilesSet.Rule rule = FilesSetXML.readFileExtensionRule(elem); - if (rule != null) { - if (!rules.containsKey(rule.getUuid())) { - rules.put(rule.getUuid(), rule); - } else { - logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in interesting file sets definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); //NOI18N NON-NLS - return; - } - } else { - logger.log(Level.SEVERE, "Found malformed rule for set named {0} in interesting file sets definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); //NOI18N NON-NLS - return; - } - } - - // Make the files set. Note that degenerate sets with no rules are - // allowed to facilitate the separation of set definition and rule - // definitions. A set without rules is simply the empty set. - FilesSet set = new FilesSet(setName, description, ignoreKnownFiles, rules); - filesSets.put(set.getName(), set); - } - - /** - * Construct an interesting files set file name rule from the data in an - * XML element. - * - * @param elem The file name rule XML element. - * - * @return A file name rule, or null if there is an error (the error is - * logged). - */ - private static FilesSet.Rule readFileNameRule(Element elem) { - String ruleName = FilesSetXML.readRuleName(elem); - - // The content of the rule tag is a file name condition. It may be a - // regex, or it may be from a TSK Framework rule definition with a - // "*" globbing char, or it may be simple text. - String content = elem.getTextContent(); - FilesSet.Rule.FullNameCondition nameCondition; - String regex = elem.getAttribute(FilesSetXML.REGEX_ATTR); - if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS - Pattern pattern = compileRegex(content); - if (pattern != null) { - nameCondition = new FilesSet.Rule.FullNameCondition(pattern); - } else { - logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.NAME_RULE_TAG + " regex, ignoring malformed '{0}' rule definition", ruleName); // NON-NLS - return null; - } - } else { - for (String illegalChar : illegalFileNameChars) { - if (content.contains(illegalChar)) { - logger.log(Level.SEVERE, FilesSetXML.NAME_RULE_TAG + " content has illegal chars, ignoring malformed '{0}' rule definition", new Object[]{FilesSetXML.NAME_RULE_TAG, ruleName}); // NON-NLS - return null; - } - } - nameCondition = new FilesSet.Rule.FullNameCondition(content); - } - - // Read in the type condition. - FilesSet.Rule.MetaTypeCondition metaTypeCondition = FilesSetXML.readMetaTypeCondition(elem); - if (metaTypeCondition == null) { - // Malformed attribute. - return null; - } - - // Read in the optional path condition. Null is o.k., but if the attribute - // is there, be sure it is not malformed. - FilesSet.Rule.ParentPathCondition pathCondition = null; - if (!elem.getAttribute(FilesSetXML.PATH_FILTER_ATTR).isEmpty() - || !elem.getAttribute(FilesSetXML.PATH_REGEX_ATTR).isEmpty()) { - pathCondition = FilesSetXML.readPathCondition(elem); - if (pathCondition == null) { - // Malformed attribute. - return null; - } - } - - return new FilesSet.Rule(ruleName, nameCondition, metaTypeCondition, pathCondition, null, null); - } - - /** - * Construct an interesting files set file name extension rule from the - * data in an XML element. - * - * @param elem The file name extension rule XML element. - * - * @return A file name extension rule, or null if there is an error (the - * error is logged). - */ - private static FilesSet.Rule readFileExtensionRule(Element elem) { - String ruleName = FilesSetXML.readRuleName(elem); - - // The content of the rule tag is a file name extension condition. It may - // be a regex, or it may be from a TSK Framework rule definition - // with a "*" globbing char. - String content = elem.getTextContent(); - FilesSet.Rule.ExtensionCondition extCondition; - String regex = elem.getAttribute(FilesSetXML.REGEX_ATTR); - if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS - Pattern pattern = compileRegex(content); - if (pattern != null) { - extCondition = new FilesSet.Rule.ExtensionCondition(pattern); - } else { - logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.EXTENSION_RULE_TAG + " regex, ignoring malformed {0} rule definition", ruleName); // NON-NLS - return null; - } - } else { - for (String illegalChar : illegalFileNameChars) { - if (content.contains(illegalChar)) { - logger.log(Level.SEVERE, "{0} content has illegal chars, ignoring malformed {1} rule definition", ruleName); // NON-NLS - return null; - } - } - extCondition = new FilesSet.Rule.ExtensionCondition(content); - } - - // The rule must have a meta-type condition, unless a TSK Framework - // definitions file is being read. - FilesSet.Rule.MetaTypeCondition metaTypeCondition = null; - if (!elem.getAttribute(FilesSetXML.TYPE_FILTER_ATTR).isEmpty()) { - metaTypeCondition = FilesSetXML.readMetaTypeCondition(elem); - if (metaTypeCondition == null) { - // Malformed attribute. - return null; - } - } else { - metaTypeCondition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); - } - - // The rule may have a path condition. Null is o.k., but if the attribute - // is there, it must not be malformed. - FilesSet.Rule.ParentPathCondition pathCondition = null; - if (!elem.getAttribute(FilesSetXML.PATH_FILTER_ATTR).isEmpty() - || !elem.getAttribute(FilesSetXML.PATH_REGEX_ATTR).isEmpty()) { - pathCondition = FilesSetXML.readPathCondition(elem); - if (pathCondition == null) { - // Malformed attribute. - return null; - } - } - - return new FilesSet.Rule(ruleName, extCondition, metaTypeCondition, pathCondition, null, null); - } - - /** - * Read a rule name attribute from a rule element. - * - * @param elem A rule element. - * - * @return A rule name. - */ - private static String readRuleName(Element elem) { - // The rule must have a name. - String ruleName = elem.getAttribute(FilesSetXML.NAME_ATTR); - return ruleName; - } - - /** - * Attempts to compile a regular expression. - * - * @param regex The regular expression. - * - * @return A pattern object, or null if the compilation fails. - */ - private static Pattern compileRegex(String regex) { - try { - return Pattern.compile(regex); - } catch (PatternSyntaxException ex) { - logger.log(Level.SEVERE, "Error compiling rule regex: " + ex.getMessage(), ex); // NON-NLS - return null; - } - } - - /** - * Construct a meta-type condition for an interesting files set - * membership rule from data in an XML element. - * - * @param ruleElement The XML element. - * - * @return The meta-type condition, or null if there is an error - * (logged). - */ - private static FilesSet.Rule.MetaTypeCondition readMetaTypeCondition(Element ruleElement) { - FilesSet.Rule.MetaTypeCondition condition = null; - String conditionAttribute = ruleElement.getAttribute(FilesSetXML.TYPE_FILTER_ATTR); - if (!conditionAttribute.isEmpty()) { - switch (conditionAttribute) { - case FilesSetXML.TYPE_FILTER_VALUE_FILES: - condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); - break; - case FilesSetXML.TYPE_FILTER_VALUE_DIRS: - condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES); - break; - case FilesSetXML.TYPE_FILTER_VALUE_FILES_AND_DIRS: - condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES_AND_DIRECTORIES); - break; - default: - logger.log(Level.SEVERE, "Found {0} " + FilesSetXML.TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", conditionAttribute); // NON-NLS - break; - } - } else { - // Accept TSK Framework interesting files set definitions, - // default to files. - condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); - } - return condition; - } - - /** - * Construct a path condition for an interesting files set membership - * rule from data in an XML element. - * - * @param ruleElement The XML element. - * - * @return The path condition, or null if there is an error (logged). - */ - private static FilesSet.Rule.ParentPathCondition readPathCondition(Element ruleElement) { - FilesSet.Rule.ParentPathCondition condition = null; - String path = ruleElement.getAttribute(FilesSetXML.PATH_FILTER_ATTR); - String pathRegex = ruleElement.getAttribute(FilesSetXML.PATH_REGEX_ATTR); - if (!pathRegex.isEmpty() && path.isEmpty()) { - try { - Pattern pattern = Pattern.compile(pathRegex); - condition = new FilesSet.Rule.ParentPathCondition(pattern); - } catch (PatternSyntaxException ex) { - logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.PATH_REGEX_ATTR + " regex, ignoring malformed path condition definition", ex); // NON-NLS - } - } else if (!path.isEmpty() && pathRegex.isEmpty()) { - condition = new FilesSet.Rule.ParentPathCondition(path); - } - return condition; - } - - /** - * Writes interesting files set definitions to disk as an XML file, - * logging any errors. - * - * @param filePath Path of the set definitions file as a string. - * - * @returns True if the definitions are written to disk, false - * otherwise. - */ - // Note: This method takes a file path to support the possibility of - // multiple intersting files set definition files, e.g., one for - // definitions that ship with Autopsy and one for user definitions. - static boolean writeDefinitionsFile(String filePath, Map interestingFilesSets) throws InterestingItemDefsManagerException { - try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { - out.writeObject(new InterestingItemsFilesSetSettings(interestingFilesSets)); - } catch (IOException ex) { - throw new InterestingItemDefsManagerException(String.format("Failed to write settings to %s", filePath), ex); - } - return true; - } - } - - static class InterestingItemDefsManagerException extends Exception { - - InterestingItemDefsManagerException() { - - } - - InterestingItemDefsManagerException(String message) { - super(message); - } - - InterestingItemDefsManagerException(String message, Throwable cause) { - super(message, cause); - } - - InterestingItemDefsManagerException(Throwable cause) { - super(cause); - } - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsOptionsPanelController.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsOptionsPanelController.java index 61f4e8f9fc..609fc937ac 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsOptionsPanelController.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsOptionsPanelController.java @@ -36,7 +36,7 @@ import org.openide.util.Lookup; ) public final class InterestingItemDefsOptionsPanelController extends OptionsPanelController { - private InterestingItemDefsPanel panel; + private FilesSetDefsPanel panel; private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); private boolean changed; @@ -113,9 +113,9 @@ public final class InterestingItemDefsOptionsPanelController extends OptionsPane pcs.removePropertyChangeListener(l); } - private InterestingItemDefsPanel getPanel() { + private FilesSetDefsPanel getPanel() { if (panel == null) { - panel = new InterestingItemDefsPanel(); + panel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.INTERESTING_FILE_SETS); panel.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java index 14771992eb..bdd9f53a49 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java @@ -18,16 +18,61 @@ */ package org.sleuthkit.autopsy.modules.interestingitems; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.Serializable; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import org.openide.util.io.NbObjectInputStream; +import org.openide.util.io.NbObjectOutputStream; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.coreutils.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; /** * * @author oliver */ class InterestingItemsFilesSetSettings implements Serializable { + private static final long serialVersionUID = 1L; + // The following tags and attributes are identical to those used in the + // TSK Framework FilesSet definitions file schema. + private static final String FILE_SETS_ROOT_TAG = "INTERESTING_FILE_SETS"; //NON-NLS + private static final String DESC_ATTR = "description"; //NON-NLS + private static final String RULE_UUID_ATTR = "ruleUUID"; //NON-NLS + private static final String IGNORE_KNOWN_FILES_ATTR = "ignoreKnown"; //NON-NLS + private static final String PATH_REGEX_ATTR = "pathRegex"; //NON-NLS + private static final String TYPE_FILTER_VALUE_FILES_AND_DIRS = "files_and_dirs"; //NON-NLS + private static final String IGNORE_UNALLOCATED_SPACE = "ingoreUnallocated"; //NON-NLS + private static final String PATH_FILTER_ATTR = "pathFilter"; //NON-NLS + private static final String TYPE_FILTER_VALUE_DIRS = "dir"; //NON-NLS + private static final String REGEX_ATTR = "regex"; //NON-NLS + private static final List illegalFileNameChars = FilesSetsManager.getIllegalFileNameChars(); + private static final String FILE_SET_TAG = "INTERESTING_FILE_SET"; //NON-NLS + private static final String NAME_RULE_TAG = "NAME"; //NON-NLS + private static final String UNNAMED_LEGACY_RULE_PREFIX = "Unnamed Rule "; // NON-NLS + private static final String NAME_ATTR = "name"; //NON-NLS + private static final String TYPE_FILTER_VALUE_FILES = "file"; //NON-NLS + private static final String XML_ENCODING = "UTF-8"; //NON-NLS + private static final Logger logger = Logger.getLogger(InterestingItemsFilesSetSettings.class.getName()); + private static int unnamedLegacyRuleCounter; + private static final String TYPE_FILTER_ATTR = "typeFilter"; //NON-NLS + private static final String EXTENSION_RULE_TAG = "EXTENSION"; //NON-NLS + private Map filesSets; + InterestingItemsFilesSetSettings(Map filesSets) { this.filesSets = filesSets; } @@ -38,7 +83,376 @@ class InterestingItemsFilesSetSettings implements Serializable { Map getFilesSets() { return filesSets; } - - - + + /** + * Read a rule name attribute from a rule element. + * + * @param elem A rule element. + * + * @return A rule name. + */ + private static String readRuleName(Element elem) { + // The rule must have a name. + String ruleName = elem.getAttribute(InterestingItemsFilesSetSettings.NAME_ATTR); + return ruleName; + } + + /** + * Reads the definitions from the serialization file + * + * @return the map representing settings saved to serialization file, empty + * set if the file does not exist. + * + * @throws FilesSetsManagerException if file could not be read + */ + private static Map readSerializedDefinitions(String serialFileName) throws FilesSetsManager.FilesSetsManagerException { + Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), serialFileName); + File fileSetFile = filePath.toFile(); + String filePathStr = filePath.toString(); + if (fileSetFile.exists()) { + try { + try (final NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePathStr))) { + InterestingItemsFilesSetSettings filesSetsSettings = (InterestingItemsFilesSetSettings) in.readObject(); + return filesSetsSettings.getFilesSets(); + } + } catch (IOException | ClassNotFoundException ex) { + throw new FilesSetsManager.FilesSetsManagerException(String.format("Failed to read settings from %s", filePathStr), ex); + } + } else { + return new HashMap<>(); + } + } + + /** + * Construct a path condition for a FilesSet membership rule from data in an + * XML element. + * + * @param ruleElement The XML element. + * + * @return The path condition, or null if there is an error (logged). + */ + private static FilesSet.Rule.ParentPathCondition readPathCondition(Element ruleElement) { + FilesSet.Rule.ParentPathCondition condition = null; + String path = ruleElement.getAttribute(InterestingItemsFilesSetSettings.PATH_FILTER_ATTR); + String pathRegex = ruleElement.getAttribute(InterestingItemsFilesSetSettings.PATH_REGEX_ATTR); + if (!pathRegex.isEmpty() && path.isEmpty()) { + try { + Pattern pattern = Pattern.compile(pathRegex); + condition = new FilesSet.Rule.ParentPathCondition(pattern); + } catch (PatternSyntaxException ex) { + logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.PATH_REGEX_ATTR + " regex, ignoring malformed path condition definition", ex); // NON-NLS + } + } else if (!path.isEmpty() && pathRegex.isEmpty()) { + condition = new FilesSet.Rule.ParentPathCondition(path); + } + return condition; + } + + /** + * Attempts to compile a regular expression. + * + * @param regex The regular expression. + * + * @return A pattern object, or null if the compilation fails. + */ + private static Pattern compileRegex(String regex) { + try { + return Pattern.compile(regex); + } catch (PatternSyntaxException ex) { + logger.log(Level.SEVERE, "Error compiling rule regex: " + ex.getMessage(), ex); // NON-NLS + return null; + } + } + + /** + * Construct a FilesSet file name extension rule from the data in an XML + * element. + * + * @param elem The file name extension rule XML element. + * + * @return A file name extension rule, or null if there is an error (the + * error is logged). + */ + private static FilesSet.Rule readFileExtensionRule(Element elem) { + String ruleName = InterestingItemsFilesSetSettings.readRuleName(elem); + // The content of the rule tag is a file name extension condition. It may + // be a regex, or it may be from a TSK Framework rule definition + // with a "*" globbing char. + String content = elem.getTextContent(); + FilesSet.Rule.ExtensionCondition extCondition; + String regex = elem.getAttribute(InterestingItemsFilesSetSettings.REGEX_ATTR); + if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { + // NON-NLS + Pattern pattern = compileRegex(content); + if (pattern != null) { + extCondition = new FilesSet.Rule.ExtensionCondition(pattern); + } else { + logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.EXTENSION_RULE_TAG + " regex, ignoring malformed {0} rule definition", ruleName); // NON-NLS + return null; + } + } else { + for (String illegalChar : illegalFileNameChars) { + if (content.contains(illegalChar)) { + logger.log(Level.SEVERE, "{0} content has illegal chars, ignoring malformed {1} rule definition", ruleName); // NON-NLS + return null; + } + } + extCondition = new FilesSet.Rule.ExtensionCondition(content); + } + // The rule must have a meta-type condition, unless a TSK Framework + // definitions file is being read. + FilesSet.Rule.MetaTypeCondition metaTypeCondition = null; + if (!elem.getAttribute(InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR).isEmpty()) { + metaTypeCondition = InterestingItemsFilesSetSettings.readMetaTypeCondition(elem); + if (metaTypeCondition == null) { + // Malformed attribute. + return null; + } + } else { + metaTypeCondition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); + } + // The rule may have a path condition. Null is o.k., but if the attribute + // is there, it must not be malformed. + FilesSet.Rule.ParentPathCondition pathCondition = null; + if (!elem.getAttribute(InterestingItemsFilesSetSettings.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(InterestingItemsFilesSetSettings.PATH_REGEX_ATTR).isEmpty()) { + pathCondition = InterestingItemsFilesSetSettings.readPathCondition(elem); + if (pathCondition == null) { + // Malformed attribute. + return null; + } + } + return new FilesSet.Rule(ruleName, extCondition, metaTypeCondition, pathCondition, null, null); + } + + /** + * Construct a FilesSet file name rule from the data in an XML element. + * + * @param elem The file name rule XML element. + * + * @return A file name rule, or null if there is an error (the error is + * logged). + */ + private static FilesSet.Rule readFileNameRule(Element elem) { + String ruleName = InterestingItemsFilesSetSettings.readRuleName(elem); + // The content of the rule tag is a file name condition. It may be a + // regex, or it may be from a TSK Framework rule definition with a + // "*" globbing char, or it may be simple text. + String content = elem.getTextContent(); + FilesSet.Rule.FullNameCondition nameCondition; + String regex = elem.getAttribute(InterestingItemsFilesSetSettings.REGEX_ATTR); + if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { + // NON-NLS + Pattern pattern = compileRegex(content); + if (pattern != null) { + nameCondition = new FilesSet.Rule.FullNameCondition(pattern); + } else { + logger.log(Level.SEVERE, "Error compiling " + InterestingItemsFilesSetSettings.NAME_RULE_TAG + " regex, ignoring malformed '{0}' rule definition", ruleName); // NON-NLS + return null; + } + } else { + for (String illegalChar : illegalFileNameChars) { + if (content.contains(illegalChar)) { + logger.log(Level.SEVERE, InterestingItemsFilesSetSettings.NAME_RULE_TAG + " content has illegal chars, ignoring malformed '{0}' rule definition", new Object[]{InterestingItemsFilesSetSettings.NAME_RULE_TAG, ruleName}); // NON-NLS + return null; + } + } + nameCondition = new FilesSet.Rule.FullNameCondition(content); + } + // Read in the type condition. + FilesSet.Rule.MetaTypeCondition metaTypeCondition = InterestingItemsFilesSetSettings.readMetaTypeCondition(elem); + if (metaTypeCondition == null) { + // Malformed attribute. + return null; + } + // Read in the optional path condition. Null is o.k., but if the attribute + // is there, be sure it is not malformed. + FilesSet.Rule.ParentPathCondition pathCondition = null; + if (!elem.getAttribute(InterestingItemsFilesSetSettings.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(InterestingItemsFilesSetSettings.PATH_REGEX_ATTR).isEmpty()) { + pathCondition = InterestingItemsFilesSetSettings.readPathCondition(elem); + if (pathCondition == null) { + // Malformed attribute. + return null; + } + } + return new FilesSet.Rule(ruleName, nameCondition, metaTypeCondition, pathCondition, null, null); + } + + /** + * Reads in a FilesSet. + * + * @param setElem A FilesSet XML element + * @param filesSets A collection to which the set is to be added. + * @param filePath The source file, used for error reporting. + */ + private static void readFilesSet(Element setElem, Map filesSets, String filePath) { + // The file set must have a unique name. + String setName = setElem.getAttribute(InterestingItemsFilesSetSettings.NAME_ATTR); + if (setName.isEmpty()) { + logger.log(Level.SEVERE, "Found {0} element without required {1} attribute, ignoring malformed file set definition in FilesSet definition file at {2}", new Object[]{InterestingItemsFilesSetSettings.FILE_SET_TAG, InterestingItemsFilesSetSettings.NAME_ATTR, filePath}); // NON-NLS + return; + } + if (filesSets.containsKey(setName)) { + logger.log(Level.SEVERE, "Found duplicate definition of set named {0} in FilesSet definition file at {1}, discarding duplicate set", new Object[]{setName, filePath}); // NON-NLS + return; + } + // The file set may have a description. The empty string is o.k. + String description = setElem.getAttribute(InterestingItemsFilesSetSettings.DESC_ATTR); + // The file set may or may not ignore known files. The default behavior + // is to not ignore them. + String ignoreKnown = setElem.getAttribute(InterestingItemsFilesSetSettings.IGNORE_KNOWN_FILES_ATTR); + boolean ignoreKnownFiles = false; + if (!ignoreKnown.isEmpty()) { + ignoreKnownFiles = Boolean.parseBoolean(ignoreKnown); + } + // The file set may or may not skip unallocated space. The default behavior + // is not to skip it. + String ignoreUnallocated = setElem.getAttribute(InterestingItemsFilesSetSettings.IGNORE_UNALLOCATED_SPACE); + boolean ignoreUnallocatedSpace = false; + if (!ignoreUnallocated.isEmpty()) { + ignoreUnallocatedSpace = Boolean.parseBoolean(ignoreUnallocated); + } + // Read file name set membership rules, if any. + InterestingItemsFilesSetSettings.unnamedLegacyRuleCounter = 1; + Map rules = new HashMap<>(); + NodeList nameRuleElems = setElem.getElementsByTagName(InterestingItemsFilesSetSettings.NAME_RULE_TAG); + for (int j = 0; j < nameRuleElems.getLength(); ++j) { + Element elem = (Element) nameRuleElems.item(j); + FilesSet.Rule rule = InterestingItemsFilesSetSettings.readFileNameRule(elem); + if (rule != null) { + if (!rules.containsKey(rule.getUuid())) { + rules.put(rule.getUuid(), rule); + } else { + logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in FilesSet definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); // NON-NLS + return; + } + } else { + logger.log(Level.SEVERE, "Found malformed rule for set named {0} in FilesSet definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); // NON-NLS + return; + } + } + // Read file extension set membership rules, if any. + NodeList extRuleElems = setElem.getElementsByTagName(InterestingItemsFilesSetSettings.EXTENSION_RULE_TAG); + for (int j = 0; j < extRuleElems.getLength(); ++j) { + Element elem = (Element) extRuleElems.item(j); + FilesSet.Rule rule = InterestingItemsFilesSetSettings.readFileExtensionRule(elem); + if (rule != null) { + if (!rules.containsKey(rule.getUuid())) { + rules.put(rule.getUuid(), rule); + } else { + logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in FilesSet definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); //NOI18N NON-NLS + return; + } + } else { + logger.log(Level.SEVERE, "Found malformed rule for set named {0} in FilesSet definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); //NOI18N NON-NLS + return; + } + } + // Make the files set. Note that degenerate sets with no rules are + // allowed to facilitate the separation of set definition and rule + // definitions. A set without rules is simply the empty set. + FilesSet set = new FilesSet(setName, description, ignoreKnownFiles, ignoreUnallocatedSpace, rules); + filesSets.put(set.getName(), set); + } + + // Note: This method takes a file path to support the possibility of + // multiple intersting files set definition files, e.g., one for + // definitions that ship with Autopsy and one for user definitions. + /** + * Reads FilesSet definitions from an XML file. + * + * @param fileName The name of the file which is expected to store the + * serialized definitions + * @param legacyFilePath Path of the set definitions file as a string. + * + * @return The set definitions in a map of set names to sets. + */ + static Map readDefinitionsFile(String fileName, String legacyFileName) throws FilesSetsManager.FilesSetsManagerException { + Map filesSets = readSerializedDefinitions(fileName); + if (!filesSets.isEmpty()) { + return filesSets; + } + // Check if the legacy xml file exists. + if (!legacyFileName.isEmpty()) { + File defsFile = Paths.get(PlatformUtil.getUserConfigDirectory(), legacyFileName).toFile(); + if (!defsFile.exists()) { + return filesSets; + } + // Check if the file can be read. + if (!defsFile.canRead()) { + logger.log(Level.SEVERE, "FilesSet definition file at {0} exists, but cannot be read", defsFile.getPath()); // NON-NLS + return filesSets; + } + // Parse the XML in the file. + Document doc = XMLUtil.loadDoc(InterestingItemsFilesSetSettings.class, defsFile.getPath()); + if (doc == null) { + logger.log(Level.SEVERE, "FilesSet definition file at {0}", defsFile.getPath()); // NON-NLS + return filesSets; + } + // Get the root element. + Element root = doc.getDocumentElement(); + if (root == null) { + logger.log(Level.SEVERE, "Failed to get root {0} element tag of FilesSet definition file at {1}", new Object[]{InterestingItemsFilesSetSettings.FILE_SETS_ROOT_TAG, defsFile.getPath()}); // NON-NLS + return filesSets; + } + // Read in the files set definitions. + NodeList setElems = root.getElementsByTagName(FILE_SET_TAG); + for (int i = 0; i < setElems.getLength(); ++i) { + readFilesSet((Element) setElems.item(i), filesSets, defsFile.getPath()); + } + } + return filesSets; + } + + // Note: This method takes a file path to support the possibility of + // multiple intersting files set definition files, e.g., one for + // definitions that ship with Autopsy and one for user definitions. + /** + * Writes FilesSet definitions to disk as an XML file, logging any errors. + * + * @param fileName Name of the set definitions file as a string. + * + * @returns True if the definitions are written to disk, false otherwise. + */ + static boolean writeDefinitionsFile(String fileName, Map interestingFilesSets) throws FilesSetsManager.FilesSetsManagerException { + try (final NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(Paths.get(PlatformUtil.getUserConfigDirectory(), fileName).toString()))) { + out.writeObject(new InterestingItemsFilesSetSettings(interestingFilesSets)); + } catch (IOException ex) { + throw new FilesSetsManager.FilesSetsManagerException(String.format("Failed to write settings to %s", fileName), ex); + } + return true; + } + + /** + * Construct a meta-type condition for a FilesSet membership rule from data + * in an XML element. + * + * @param ruleElement The XML element. + * + * @return The meta-type condition, or null if there is an error (logged). + */ + private static FilesSet.Rule.MetaTypeCondition readMetaTypeCondition(Element ruleElement) { + FilesSet.Rule.MetaTypeCondition condition = null; + String conditionAttribute = ruleElement.getAttribute(InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR); + if (!conditionAttribute.isEmpty()) { + switch (conditionAttribute) { + case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_FILES: + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); + break; + case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_DIRS: + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES); + break; + case InterestingItemsFilesSetSettings.TYPE_FILTER_VALUE_FILES_AND_DIRS: + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES_AND_DIRECTORIES); + break; + default: + logger.log(Level.SEVERE, "Found {0} " + InterestingItemsFilesSetSettings.TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", conditionAttribute); // NON-NLS + break; + } + } else { + // Accept TSK Framework FilesSet definitions, + // default to files. + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); + } + return condition; + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java index 1779c8b3c2..04034e5016 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.modules.interestingitems; import java.util.ArrayList; import java.util.List; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; @@ -70,7 +69,7 @@ final public class InterestingItemsIngestModuleFactory extends IngestModuleFacto @Override public IngestModuleGlobalSettingsPanel getGlobalSettingsPanel() { - InterestingItemDefsPanel panel = new InterestingItemDefsPanel(); + FilesSetDefsPanel panel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.INTERESTING_FILE_SETS); panel.load(); return panel; } @@ -84,10 +83,10 @@ final public class InterestingItemsIngestModuleFactory extends IngestModuleFacto // Doing so also keeps the serialization simple. List enabledFilesSetNames = new ArrayList<>(); try { - for (String name : InterestingItemDefsManager.getInstance().getInterestingFilesSets().keySet()) { + for (String name : FilesSetsManager.getInstance().getInterestingFilesSets().keySet()) { enabledFilesSetNames.add(name); } - } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + } catch (FilesSetsManager.FilesSetsManagerException ex) { MessageNotifyUtil.Message.error(Bundle.InterestingItemsIngestModuleFactory_defaultSettingsError()); } return new FilesIdentifierIngestJobSettings(enabledFilesSetNames); diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java index d1a8e7e5a3..30aa69ba75 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java @@ -68,7 +68,7 @@ import org.sleuthkit.datamodel.TskData; "PhotoRecIngestModule.PermissionsNotSufficient=Insufficient permissions accessing", "PhotoRecIngestModule.PermissionsNotSufficientSeeReference=See 'Shared Drive Authentication' in Autopsy help.", "# {0} - output directory name", "cannotCreateOutputDir.message=Unable to create output directory: {0}.", - "unallocatedSpaceProcessingSettingsError.message='Process Unallocated Space' is not checked. The PhotoRec module is designed to carve unallocated space. Either enable processing of unallocated space or disable this module.", + "unallocatedSpaceProcessingSettingsError.message=The selected file ingest filter ignores unallocated space. This module carves unallocated space. Please choose a filter which does not ignore unallocated space or disable this module.", "unsupportedOS.message=PhotoRec module is supported on Windows platforms only.", "missingExecutable.message=Unable to locate PhotoRec executable.", "cannotRunExecutable.message=Unable to execute PhotoRec.", diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 8db9e3167d..43ba62c3c6 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -199,7 +199,7 @@ KeywordSearchOptionsPanelController.moduleErr.msg1=A module caused an error list KeywordSearchOptionsPanelController.moduleErr.msg2=A module caused an error listening to KeywordSearchOptionsPanelController updates. See log to determine which module. Some data could be incomplete. KeywordSearchQueryManager.pathText.text=Keyword search KeywordSearchResultFactory.progress.saving=Saving results\: {0} -KeywordSearchSettings.moduleName.text=Keyword Search +KeywordSearchSettings.moduleName.text=KeywordSearch KeywordSearchSettings.properties_options.text={0}_Options KeywordSearchSettings.propertiesNSRL.text={0}_NSRL KeywordSearchSettings.propertiesScripts.text={0}_Scripts diff --git a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java index 33d73c2044..f8cd7a5b59 100755 --- a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java +++ b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java @@ -299,10 +299,6 @@ public class RegressionTest extends TestCase { JButtonOperator jbo2 = new JButtonOperator(jdo, "OK", 0); jbo2.pushNoBlock(); WizardOperator wo = new WizardOperator("Add Data"); - JCheckBoxOperator jbco0 = new JCheckBoxOperator(wo, "Process Unallocated Space"); - if (Boolean.parseBoolean(System.getProperty("ignore_unalloc"))) { - jbco0.doClick(); - } new Timeout("pausing", 10000).sleep(); // let things catch up wo.btNext().clickMouse(); }