diff --git a/Core/src/org/sleuthkit/autopsy/examples/SampleModuleIngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/examples/SampleModuleIngestJobSettings.java index 0a7e34d81f..83339dbc6f 100755 --- a/Core/src/org/sleuthkit/autopsy/examples/SampleModuleIngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/examples/SampleModuleIngestJobSettings.java @@ -46,6 +46,11 @@ public class SampleModuleIngestJobSettings implements IngestModuleIngestJobSetti this.skipKnownFiles = skipKnownFiles; } + @Override + public String getVersionNumber() { + return "1.0"; //NON-NLS + } + void setSkipKnownFiles(boolean enabled) { skipKnownFiles = enabled; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobLauncher.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobLauncher.java index 1fb2ccf989..23ab80d231 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobLauncher.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobLauncher.java @@ -18,11 +18,22 @@ */ package org.sleuthkit.autopsy.ingest; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.logging.Level; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import org.openide.util.io.NbObjectInputStream; +import org.openide.util.io.NbObjectOutputStream; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.datamodel.Content; /** @@ -35,9 +46,13 @@ public final class IngestJobLauncher { private static final String ENABLED_INGEST_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS private static final String DISABLED_INGEST_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS private static final String PARSE_UNALLOC_SPACE_KEY = "Process_Unallocated_Space"; //NON-NLS + private static final String MODULE_SETTINGS_FOLDER_PATH = new StringBuilder(PlatformUtil.getUserConfigDirectory()).append(File.separator).append("IngestModuleSettings").toString(); //NON-NLS + private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS + private static final Logger logger = Logger.getLogger(IngestJobLauncher.class.getName()); private final String launcherContext; + private String moduleSettingsFolderForContext = null; private final List warnings = new ArrayList<>(); - private IngestJobConfigurationPanel ingestConfigPanel; + private IngestJobConfigurationPanel ingestConfigPanel = null; /** * Constructs an ingest job launcher that creates and persists an ingest job @@ -49,6 +64,8 @@ public final class IngestJobLauncher { public IngestJobLauncher(String launcherContext) { this.launcherContext = launcherContext; + createModuleSettingsFolderForContext(); + // Get the ingest module factories discovered by the ingest module // loader. List moduleFactories = IngestModuleFactoryLoader.getInstance().getIngestModuleFactories(); @@ -84,10 +101,7 @@ public final class IngestJobLauncher { // Create ingest module templates. List moduleTemplates = new ArrayList<>(); for (IngestModuleFactory moduleFactory : moduleFactories) { - // NOTE: In the future, this code will be modified to get the - // module settings for the current context, if available, from - // storage; for now always use the defaults. - IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, moduleFactory.getDefaultIngestJobSettings()); + IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadJobSettings(moduleFactory)); String moduleName = moduleTemplate.getModuleName(); if (enabledModuleNames.contains(moduleName)) { moduleTemplate.setEnabled(true); @@ -119,6 +133,23 @@ public final class IngestJobLauncher { ingestConfigPanel = new IngestJobConfigurationPanel(moduleTemplates, processUnallocatedSpace); } + private void createModuleSettingsFolderForContext() { + try { + StringBuilder folderPath = new StringBuilder(MODULE_SETTINGS_FOLDER_PATH); + folderPath.append(File.separator); + folderPath.append(launcherContext); + folderPath.append(File.separator); + File folder = new File(folderPath.toString()); + if (!folder.exists()) { + Files.createDirectories(folder.toPath()); + } + moduleSettingsFolderForContext = folder.getAbsolutePath(); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Failed to create ingest module settings directory", ex); + JOptionPane.showMessageDialog(null, "Failed to create ingest module settings folder, cannot save settings.", "Ingest Job Initialization Failure", JOptionPane.ERROR_MESSAGE); + } + } + private HashSet getModulesNamesFromSetting(String key, String defaultSetting) { // Get the ingest modules setting from the user's config file. // If there is no such setting yet, create the default setting. @@ -150,7 +181,47 @@ public final class IngestJobLauncher { } return moduleNames; } - + + private IngestModuleIngestJobSettings loadJobSettings(IngestModuleFactory factory) { + IngestModuleIngestJobSettings settings = null; + File settingsFile = new File(getModuleSettingsFilePath(factory)); + if (settingsFile.exists()) { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) { + settings = (IngestModuleIngestJobSettings) in.readObject(); + } catch (IOException | ClassNotFoundException ex) { + String logMessage = String.format("Error loading ingest job settings for %s module for %s context, using defaults", factory.getModuleDisplayName(), launcherContext); + logger.log(Level.SEVERE, logMessage, ex); + String userMessage = String.format("Failed to load saved ingest job settings for %s module, using defaults.", factory.getModuleDisplayName()); + JOptionPane.showMessageDialog(null, userMessage, "Ingest Job Settings", JOptionPane.WARNING_MESSAGE); + } + } + if (settings == null) { + settings = factory.getDefaultIngestJobSettings(); + } + return settings; + } + + private void saveJobSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings) { + try { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(getModuleSettingsFilePath(factory)))) { + out.writeObject(settings); + } + } catch (IOException ex) { + String logMessage = String.format("Error saving ingest job settings for %s module for %s context", factory.getModuleDisplayName(), launcherContext); + logger.log(Level.SEVERE, logMessage, ex); + String userMessage = String.format("Failed to save ingest job settings for %s module.", factory.getModuleDisplayName()); + JOptionPane.showMessageDialog(null, userMessage, "Ingest Job Settings", JOptionPane.WARNING_MESSAGE); + } + } + + private String getModuleSettingsFilePath(IngestModuleFactory factory) { + StringBuilder filePath = new StringBuilder(this.moduleSettingsFolderForContext); + filePath.append(File.separator); + filePath.append(factory.getClass().getCanonicalName()); + filePath.append(MODULE_SETTINGS_FILE_EXT); + return filePath.toString(); + } + /** * Gets any warnings generated when the persisted ingest job configuration * for the specified context is retrieved and loaded. @@ -182,6 +253,7 @@ public final class IngestJobLauncher { HashSet enabledModuleNames = new HashSet<>(); HashSet disabledModuleNames = new HashSet<>(); for (IngestModuleTemplate moduleTemplate : moduleTemplates) { + saveJobSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings()); String moduleName = moduleTemplate.getModuleName(); if (moduleTemplate.isEnabled()) { enabledModuleNames.add(moduleName); @@ -195,9 +267,6 @@ public final class IngestJobLauncher { // Save the process unallocated space setting for the current context. String processUnalloc = Boolean.toString(ingestConfigPanel.getProcessUnallocSpace()); ModuleSettings.setConfigSetting(launcherContext, PARSE_UNALLOC_SPACE_KEY, processUnalloc); - - // NOTE: In the future, this code will be modified to persist the ingest - // options for each ingest module for the current launch context. } private static String makeCommaSeparatedList(HashSet input) { @@ -214,7 +283,7 @@ public final class IngestJobLauncher { csvList.append(list.get(list.size() - 1)); return csvList.toString(); } - + /** * Launches ingest jobs for one or more data sources using the ingest job * configuration for the selected context. diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleIngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleIngestJobSettings.java index 06e0f4b725..b68186b17f 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleIngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleIngestJobSettings.java @@ -26,4 +26,11 @@ import java.io.Serializable; * between invocations of the application. */ public interface IngestModuleIngestJobSettings extends Serializable { + + /** + * Returns the version number of the settings object. + * + * @return A version number string. + */ + String getVersionNumber(); } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleTemplate.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleTemplate.java index 58dbc0004f..6d802c4660 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleTemplate.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleTemplate.java @@ -33,6 +33,10 @@ final class IngestModuleTemplate { this.settings = settings; } + IngestModuleFactory getModuleFactory() { + return moduleFactory; + } + String getModuleName() { return moduleFactory.getModuleDisplayName(); } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/NoIngestModuleIngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/NoIngestModuleIngestJobSettings.java index da3ad8e5a9..4c92cfc3ee 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/NoIngestModuleIngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/NoIngestModuleIngestJobSettings.java @@ -26,6 +26,11 @@ public final class NoIngestModuleIngestJobSettings implements IngestModuleIngest private final String setting = "None"; //NON-NLS + @Override + public String getVersionNumber() { + return "1.0"; //NON-NLS + } + /** * Gets the string used as an ingest options placeholder for serialization * purposes. diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java index e01d1856f0..7a88433067 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java @@ -36,6 +36,11 @@ final class FileExtMismatchDetectorModuleSettings implements IngestModuleIngestJ this.skipFilesWithTextPlainMimeType = skipFilesWithTextPlainMimeType; } + @Override + public String getVersionNumber() { + return "1.0"; //NON-NLS + } + void setSkipFilesWithNoExtension(boolean enabled) { skipFilesWithNoExtension = enabled; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java index 26caff787d..f62cab64dc 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java @@ -33,7 +33,12 @@ public class FileTypeIdModuleSettings implements IngestModuleIngestJobSettings { FileTypeIdModuleSettings(boolean skipKnownFiles) { this.skipKnownFiles = skipKnownFiles; } - + + @Override + public String getVersionNumber() { + return "1.0"; //NON-NLS + } + void setSkipKnownFiles(boolean enabled) { skipKnownFiles = enabled; } diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java index 32304d47b7..19250cd4a3 100755 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbManager.java @@ -74,8 +74,6 @@ public class HashDbManager implements PropertyChangeListener { private static final String CONFIG_FILE_NAME = "hashsets.xml"; //NON-NLS private static final String XSD_FILE_NAME = "HashsetsSchema.xsd"; //NON-NLS private static final String ENCODING = "UTF-8"; //NON-NLS - private static final String ALWAYS_CALCULATE_HASHES_ELEMENT = "hash_calculate"; //NON-NLS - private static final String VALUE_ATTRIBUTE = "value"; //NON-NLS private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS private static HashDbManager instance = null; private final String configFilePath = PlatformUtil.getUserConfigDirectory() + File.separator + CONFIG_FILE_NAME; @@ -83,7 +81,6 @@ public class HashDbManager implements PropertyChangeListener { private List knownBadHashSets = new ArrayList<>(); private Set hashSetNames = new HashSet<>(); private Set hashSetPaths = new HashSet<>(); - private boolean alwaysCalculateHashes = true; PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class); private static final Logger logger = Logger.getLogger(HashDbManager.class.getName()); @@ -465,22 +462,6 @@ public class HashDbManager implements PropertyChangeListener { return updateableDbs; } - /** - * Sets the value for the flag that indicates whether hashes should be - * calculated for content even if no hash databases are configured. - */ - synchronized void setAlwaysCalculateHashes(boolean alwaysCalculateHashes) { - this.alwaysCalculateHashes = alwaysCalculateHashes; - } - - /** - * Gets the flag that indicates whether hashes should be calculated for - * content even if no hash databases are configured. - */ - synchronized boolean getAlwaysCalculateHashes() { - return alwaysCalculateHashes; - } - /** * Saves the hash sets configuration. Note that the configuration is only * saved on demand to support cancellation of configuration panels. @@ -529,11 +510,6 @@ public class HashDbManager implements PropertyChangeListener { writeHashDbsToDisk(doc, rootEl, knownHashSets); writeHashDbsToDisk(doc, rootEl, knownBadHashSets); - String calcValue = Boolean.toString(alwaysCalculateHashes); - Element setCalc = doc.createElement(ALWAYS_CALCULATE_HASHES_ELEMENT); - setCalc.setAttribute(VALUE_ATTRIBUTE, calcValue); - rootEl.appendChild(setCalc); - success = XMLUtil.saveDoc(HashDbManager.class, configFilePath, ENCODING, doc); } catch (ParserConfigurationException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error saving hash databases", ex); //NON-NLS @@ -691,17 +667,6 @@ public class HashDbManager implements PropertyChangeListener { } } - // Get the element that stores the always calculate hashes flag. - NodeList calcList = root.getElementsByTagName(ALWAYS_CALCULATE_HASHES_ELEMENT); - if (calcList.getLength() > 0) { - Element calcEl = (Element) calcList.item(0); // Shouldn't be more than one. - final String value = calcEl.getAttribute(VALUE_ATTRIBUTE); - alwaysCalculateHashes = Boolean.parseBoolean(value); - } else { - Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, " element "); //NON-NLS - alwaysCalculateHashes = true; - } - if (updatedSchema) { String backupFilePath = configFilePath + ".v1_backup"; //NON-NLS String messageBoxTitle = NbBundle.getMessage(this.getClass(), diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleFactory.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleFactory.java index 554c79ee33..d593c452e7 100755 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleFactory.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleFactory.java @@ -59,11 +59,11 @@ public class HashLookupModuleFactory extends IngestModuleFactoryAdapter { @Override public IngestModuleIngestJobSettings getDefaultIngestJobSettings() { - // All available hash sets are enabled by default. + // All available hash sets are enabled and always calculate hashes is true by default. HashDbManager hashDbManager = HashDbManager.getInstance(); List knownHashSetNames = getHashSetNames(hashDbManager.getKnownFileHashSets()); List knownBadHashSetNames = getHashSetNames(hashDbManager.getKnownBadFileHashSets()); - return new HashLookupModuleSettings(hashDbManager.getAlwaysCalculateHashes(), knownHashSetNames, knownBadHashSetNames); + return new HashLookupModuleSettings(true, knownHashSetNames, knownBadHashSetNames); } private List getHashSetNames(List hashDbs) { diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettings.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettings.java index 38ceaa846b..76edf6c184 100755 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettings.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettings.java @@ -38,6 +38,11 @@ final class HashLookupModuleSettings implements IngestModuleIngestJobSettings { this.namesOfEnabledKnownBadHashSets.addAll(namesOfEnabledKnownBadHashSets); } + @Override + public String getVersionNumber() { + return "1.0"; //NON-NLS + } + boolean shouldCalculateHashes() { return shouldCalculateHashes; } diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.form b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.form index dca060b4e9..54962006e2 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.form +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.form @@ -100,9 +100,6 @@ - - - diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.java index cc0bcb530e..414d7a1cb3 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashLookupModuleSettingsPanel.java @@ -49,7 +49,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe HashLookupModuleSettingsPanel(HashLookupModuleSettings settings) { initializeHashSetModels(settings); initComponents(); - customizeComponents(); + customizeComponents(settings); } private void initializeHashSetModels(HashLookupModuleSettings settings) { @@ -65,10 +65,10 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe } } - private void customizeComponents() { + private void customizeComponents(HashLookupModuleSettings settings) { customizeHashSetsTable(jScrollPane1, knownHashTable, knownHashSetsTableModel); customizeHashSetsTable(jScrollPane2, knownBadHashTable, knownBadHashSetsTableModel); - alwaysCalcHashesCheckbox.setSelected(hashDbManager.getAlwaysCalculateHashes()); + alwaysCalcHashesCheckbox.setSelected(settings.shouldCalculateHashes()); hashDbManager.addPropertyChangeListener(this); } @@ -280,11 +280,6 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe knownHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.knownHashDbsLabel.text")); // NOI18N alwaysCalcHashesCheckbox.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text")); // NOI18N - alwaysCalcHashesCheckbox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - alwaysCalcHashesCheckboxActionPerformed(evt); - } - }); jScrollPane2.setBorder(javax.swing.BorderFactory.createEtchedBorder()); @@ -336,9 +331,6 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe ); }// //GEN-END:initComponents - private void alwaysCalcHashesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_alwaysCalcHashesCheckboxActionPerformed - hashDbManager.setAlwaysCalculateHashes(alwaysCalcHashesCheckbox.isSelected()); - }//GEN-LAST:event_alwaysCalcHashesCheckboxActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JCheckBox alwaysCalcHashesCheckbox; private javax.swing.JScrollPane jScrollPane1; diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java index 495d171c77..729c922102 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java @@ -34,6 +34,11 @@ final class KeywordSearchJobSettings implements IngestModuleIngestJobSettings { this.namesOfEnabledKeywordLists.addAll(namesOfEnabledKeywordLists); } + @Override + public String getVersionNumber() { + return "1.0"; //NON-NLS + } + boolean isKeywordListEnabled(String keywordListName) { return namesOfEnabledKeywordLists.contains(keywordListName); }