diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java index 2ad7398b8a..e6e75bdd6c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java @@ -25,7 +25,6 @@ import java.util.Arrays; import java.util.HashMap; import javax.swing.AbstractAction; import javax.swing.JOptionPane; -import org.openide.util.Exceptions; /** * Do the context menu action for adding a new filename extension to the @@ -46,8 +45,8 @@ class AddFileExtensionAction extends AbstractAction { public void actionPerformed(ActionEvent event) { HashMap editableMap; try { - editableMap = FileExtMismatchXML.getDefault().load(); - } catch (FileExtMismatchXML.FileExtMismatchException ex) { + editableMap = FileExtMismatchSettings.readSettings().getSigTypeToExtMap(); + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.msg"), NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.title"), @@ -61,14 +60,14 @@ class AddFileExtensionAction extends AbstractAction { editableMap.put(mimeTypeStr, editedExtensions.toArray(new String[0])); try { - if (!FileExtMismatchXML.getDefault().save(editableMap)) { + if (!FileExtMismatchSettings.writeSettings(new FileExtMismatchSettings(editableMap))) { //error JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.msg"), NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.title"), JOptionPane.ERROR_MESSAGE); } // else //in the future we might want to update the statusbar to give feedback to the user - } catch (FileExtMismatchXML.FileExtMismatchException ex) { + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.msg"), NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.title"), diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java index 6684093e1a..afffbbcce2 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java @@ -98,13 +98,13 @@ public class FileExtMismatchContextMenuActionsProvider implements ContextMenuAct // Check if already added HashMap editableMap; try { - editableMap = FileExtMismatchXML.getDefault().load(); + editableMap = FileExtMismatchSettings.readSettings().getSigTypeToExtMap(); ArrayList editedExtensions = new ArrayList<>(Arrays.asList(editableMap.get(mimeTypeStr))); if (editedExtensions.contains(extStr)) { // Informs the user that they have already added this extension to this MIME type actions.get(0).setEnabled(false); } - } catch (FileExtMismatchXML.FileExtMismatchException ex) { + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.msg2"), NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.title"), diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleFactory.java index b303fd770f..0840f24296 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleFactory.java @@ -99,7 +99,7 @@ public class FileExtMismatchDetectorModuleFactory extends IngestModuleFactoryAda assert settings instanceof FileExtMismatchDetectorModuleSettings; if (!(settings instanceof FileExtMismatchDetectorModuleSettings)) { throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), - "FileExtMismatchDetectorModuleFactory.createFileIngestModule.exception.msg")); + "FileExtMismatchDetectorModuleFactory.getIngestJobSettingsPanel.exception.msg")); } return new FileExtMismatchIngestModule((FileExtMismatchDetectorModuleSettings) settings); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java index b2544455bc..664b92e078 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java @@ -92,10 +92,9 @@ public class FileExtMismatchIngestModule implements FileIngestModule { jobId = context.getJobId(); refCounter.incrementAndGet(jobId); - FileExtMismatchXML xmlLoader = FileExtMismatchXML.getDefault(); try { - SigTypeToExtMap = xmlLoader.load(); - } catch (FileExtMismatchXML.FileExtMismatchException ex) { + SigTypeToExtMap = FileExtMismatchSettings.readSettings().getSigTypeToExtMap(); + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { throw new IngestModuleException("Could not load file extension mismatch configurations.", ex); } try { diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettings.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettings.java index b798f860f0..6a0799b7bf 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettings.java @@ -18,13 +18,56 @@ */ package org.sleuthkit.autopsy.modules.fileextmismatch; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.logging.Level; +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; +/** + * Serialization settings for file extension mismatch. Contains static methods + * for reading and writing settings, and instances of this class are what is + * written to the serialized file. + */ class FileExtMismatchSettings implements Serializable { - private static final long serialVersionUID = 1L; - private final HashMap sigTypeToExtMap; + private static final long serialVersionUID = 1L; + private HashMap sigTypeToExtMap; + private static final Logger logger = Logger.getLogger(FileExtMismatchSettings.class.getName()); + private static final String SIG_EL = "signature"; //NON-NLS + private static final String EXT_EL = "ext"; //NON-NLS + private static final String SIG_MIMETYPE_ATTR = "mimetype"; //NON-NLS + + private static final String DEFAULT_CONFIG_FILE_NAME = "mismatch_config.xml"; //NON-NLS + private static final String FILTER_CONFIG_FILE = PlatformUtil.getUserConfigDirectory() + File.separator + DEFAULT_CONFIG_FILE_NAME; + private static final String DEFAULT_SERIALIZED_FILE_NAME = "mismatch_config.settings"; + private static final String DEFAULT_SERIALIZED_FILE_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + DEFAULT_SERIALIZED_FILE_NAME; + + static { + try { + boolean extracted = PlatformUtil.extractResourceToUserConfigDir(FileExtMismatchSettings.class, DEFAULT_CONFIG_FILE_NAME, false); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error copying default mismatch configuration to user dir ", ex); //NON-NLS + } + } + + /** + * Makes a settings object based on given sig type map + * + * @param sigTypeToExtMap + */ FileExtMismatchSettings(HashMap sigTypeToExtMap) { this.sigTypeToExtMap = sigTypeToExtMap; } @@ -35,6 +78,115 @@ class FileExtMismatchSettings implements Serializable { HashMap getSigTypeToExtMap() { return sigTypeToExtMap; } - - + + /** + * Sets the signature to extension map for this settings. + */ + public void setSigTypeToExtMap(HashMap sigTypeToExtMap) { + this.sigTypeToExtMap = sigTypeToExtMap; + } + + /** + * Load and parse the settings + * + * @return Loaded hash map or null on error or null if data does not exist + */ + public static synchronized FileExtMismatchSettings readSettings() throws FileExtMismatchSettingsException { + HashMap sigTypeToExtMap = new HashMap<>(); + File serializedFile = new File(DEFAULT_SERIALIZED_FILE_PATH); + //Tries reading the serialized file first, as this is the prioritized settings. + if (serializedFile.exists()) { + try { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedFile))) { + FileExtMismatchSettings fileExtMismatchSettings = (FileExtMismatchSettings) in.readObject(); + return fileExtMismatchSettings; + } + } catch (IOException | ClassNotFoundException ex) { + throw new FileExtMismatchSettingsException("Couldn't read serialized settings.", ex); + } + } + + //Next tries to read the xml file if the serialized file did not exist + File xmlFile = new File(FILTER_CONFIG_FILE); + if (xmlFile.exists()) { + try { + final Document doc = XMLUtil.loadDoc(FileExtMismatchSettings.class, FILTER_CONFIG_FILE); + if (doc == null) { + return new FileExtMismatchSettings(sigTypeToExtMap); + } + + Element root = doc.getDocumentElement(); + if (root == null) { + throw new FileExtMismatchSettingsException("Error loading config file: invalid file format (bad root)."); //NON-NLS + } + + NodeList sigNList = root.getElementsByTagName(SIG_EL); + final int numSigs = sigNList.getLength(); + + if (numSigs == 0) { + throw new FileExtMismatchSettingsException("Error loading config file: invalid file format (bad signature)."); //NON-NLS + } + + for (int sigIndex = 0; sigIndex < numSigs; ++sigIndex) { + Element sigEl = (Element) sigNList.item(sigIndex); + final String mimetype = sigEl.getAttribute(SIG_MIMETYPE_ATTR); + + NodeList extNList = sigEl.getElementsByTagName(EXT_EL); + final int numExts = extNList.getLength(); + + if (numExts != 0) { + List extStrings = new ArrayList<>(); + for (int extIndex = 0; extIndex < numExts; ++extIndex) { + Element extEl = (Element) extNList.item(extIndex); + extStrings.add(extEl.getTextContent()); + } + String[] sarray = extStrings.toArray(new String[0]); + sigTypeToExtMap.put(mimetype, sarray); + } else { + sigTypeToExtMap.put(mimetype, null); //ok to have an empty type (the ingest module will not use it) + } + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error loading config file.", e); //NON-NLS + return null; + } + } + return new FileExtMismatchSettings(sigTypeToExtMap); + } + + /** + * Save XML to filePath, overwriting it if it already exists + * + * @param sigTypeToExtMap String arrays of extensions mapped to each string + * mimetype. + * + * @return Loaded hash map or null on error or null if data does not exist + */ + public static synchronized boolean writeSettings(FileExtMismatchSettings settings) throws FileExtMismatchSettingsException { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(DEFAULT_SERIALIZED_FILE_PATH))) { + out.writeObject(settings); + return true; + } catch (IOException ex) { + throw new FileExtMismatchSettingsException(String.format("Failed to write settings to %s", DEFAULT_SERIALIZED_FILE_PATH), ex); + } + } + + /** + * Used to translate more implementation-details-specific exceptions (which + * are logged by this class) into more generic exceptions for propagation to + * clients of the user-defined file types manager. + */ + static class FileExtMismatchSettingsException extends Exception { + + private static final long serialVersionUID = 1L; + + FileExtMismatchSettingsException(String message) { + super(message); + } + + FileExtMismatchSettingsException(String message, Throwable throwable) { + super(message, throwable); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java index 2eea561575..405231a196 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java @@ -549,7 +549,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel @Override public void saveSettings() { try { - if (FileExtMismatchXML.getDefault().save(editableMap)) { + if (FileExtMismatchSettings.writeSettings(new FileExtMismatchSettings(editableMap))) { mimeErrLabel.setText(" "); mimeRemoveErrLabel.setText(" "); extRemoveErrLabel.setText(" "); @@ -566,7 +566,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel "FileExtMismatchConfigPanel.save.msgDlg.title"), JOptionPane.ERROR_MESSAGE); } - } catch (FileExtMismatchXML.FileExtMismatchException ex) { + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { //error JOptionPane.showMessageDialog(this, NbBundle.getMessage(this.getClass(), @@ -582,9 +582,9 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel try { // Load the configuration into a buffer that the user can modify. They can choose // to save it back to the file after making changes. - editableMap = FileExtMismatchXML.getDefault().load(); + editableMap = FileExtMismatchSettings.readSettings().getSigTypeToExtMap(); - } catch (FileExtMismatchXML.FileExtMismatchException ex) { + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { //error JOptionPane.showMessageDialog(this, NbBundle.getMessage(this.getClass(), diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchXML.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchXML.java deleted file mode 100644 index 630bc6add5..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchXML.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-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.fileextmismatch; - -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.logging.Level; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -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; - -/** - * Storage of file extension mismatch configuration, which maps mimetypes to - * allowable filename extensions. - */ -class FileExtMismatchXML { - - private static final Logger logger = Logger.getLogger(FileExtMismatchXML.class.getName()); - private static FileExtMismatchXML defaultInstance = null; - - private static final String ENCODING = "UTF-8"; //NON-NLS - private static final String XSDFILE = "MismatchConfigSchema.xsd"; //NON-NLS - - private static final String ROOT_EL = "mismatch_config"; //NON-NLS - private static final String SIG_EL = "signature"; //NON-NLS - private static final String EXT_EL = "ext"; //NON-NLS - private static final String SIG_MIMETYPE_ATTR = "mimetype"; //NON-NLS - - private static final String DEFAULT_CONFIG_FILE_NAME = "mismatch_config.xml"; //NON-NLS - private static final String DEFAULT_SERIALIZED_FILE_NAME = "mismatch_config.settings"; - private static final String DEFAULT_SERIALIZED_FILE_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + DEFAULT_SERIALIZED_FILE_NAME; - - protected String filePath; - - FileExtMismatchXML(String filePath) { - this.filePath = filePath; - - try { - boolean extracted = PlatformUtil.extractResourceToUserConfigDir(FileExtMismatchXML.class, DEFAULT_CONFIG_FILE_NAME, false); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Error copying default mismatch configuration to user dir ", ex); //NON-NLS - } - } - - /** - * Singleton provides default configuration from user's directory; user CAN - * modify this file. - */ - public static synchronized FileExtMismatchXML getDefault() { - if (defaultInstance == null) { - final String FILTER_CONFIG_FILE = PlatformUtil.getUserConfigDirectory() + File.separator + DEFAULT_CONFIG_FILE_NAME; - defaultInstance = new FileExtMismatchXML(FILTER_CONFIG_FILE); - } - return defaultInstance; - } - - /** - * Load and parse XML - * - * @return Loaded hash map or null on error or null if data does not exist - */ - public HashMap load() throws FileExtMismatchException {HashMap sigTypeToExtMap = new HashMap<>(); - File serializedFile = new File(DEFAULT_SERIALIZED_FILE_PATH); - if (serializedFile.exists()) { - try { - try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedFile))) { - FileExtMismatchSettings fileExtMismatchSettings = (FileExtMismatchSettings) in.readObject(); - return fileExtMismatchSettings.getSigTypeToExtMap(); - } - } catch (IOException | ClassNotFoundException ex) { - throw new FileExtMismatchException("Couldn't read serialized settings.", ex); - } - } - - try { - final Document doc = XMLUtil.loadDoc(FileExtMismatchXML.class, filePath); - if (doc == null) { - return null; - } - - Element root = doc.getDocumentElement(); - if (root == null) { - logger.log(Level.SEVERE, "Error loading config file: invalid file format (bad root)."); //NON-NLS - return null; - } - - NodeList sigNList = root.getElementsByTagName(SIG_EL); - final int numSigs = sigNList.getLength(); - - if (numSigs == 0) { - return null; - } - - for (int sigIndex = 0; sigIndex < numSigs; ++sigIndex) { - Element sigEl = (Element) sigNList.item(sigIndex); - final String mimetype = sigEl.getAttribute(SIG_MIMETYPE_ATTR); - - NodeList extNList = sigEl.getElementsByTagName(EXT_EL); - final int numExts = extNList.getLength(); - - if (numExts != 0) { - List extStrings = new ArrayList<>(); - for (int extIndex = 0; extIndex < numExts; ++extIndex) { - Element extEl = (Element) extNList.item(extIndex); - extStrings.add(extEl.getTextContent()); - } - String[] sarray = extStrings.toArray(new String[0]); - sigTypeToExtMap.put(mimetype, sarray); - } else { - sigTypeToExtMap.put(mimetype, null); //ok to have an empty type (the ingest module will not use it) - } - } - - } catch (Exception e) { - logger.log(Level.SEVERE, "Error loading config file.", e); //NON-NLS - return null; - } - return sigTypeToExtMap; - } - - /** - * Save XML to filePath, overwriting it if it already exists - * - * @param sigTypeToExtMap String arrays of extensions mapped to each string - * mimetype. - * - * @return Loaded hash map or null on error or null if data does not exist - */ - public boolean save(HashMap sigTypeToExtMap) throws FileExtMismatchException { - try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(DEFAULT_SERIALIZED_FILE_PATH))) { - FileExtMismatchSettings settings = new FileExtMismatchSettings(sigTypeToExtMap); - out.writeObject(settings); - return true; - } catch (IOException ex) { - throw new FileExtMismatchException(String.format("Failed to write settings to %s", DEFAULT_SERIALIZED_FILE_PATH), ex); - } - } - - /** - * Used to translate more implementation-details-specific exceptions (which - * are logged by this class) into more generic exceptions for propagation to - * clients of the user-defined file types manager. - */ - static class FileExtMismatchException extends Exception { - - private static final long serialVersionUID = 1L; - - FileExtMismatchException(String message) { - super(message); - } - - FileExtMismatchException(String message, Throwable throwable) { - super(message, throwable); - } - } - -}