diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java index 7be2e30983..7c43f14182 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/AddFileExtensionAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,44 +18,52 @@ */ package org.sleuthkit.autopsy.modules.fileextmismatch; -import org.openide.util.NbBundle; import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; +import java.util.Set; +import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JOptionPane; +import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.Logger; /** * Do the context menu action for adding a new filename extension to the - * mismatch list for the MIME type of the selected node. + * extension list for the MIME type. */ class AddFileExtensionAction extends AbstractAction { - private String extStr; - private String mimeTypeStr; + private static final long serialVersionUID = 1L; + private static final Logger logger = Logger.getLogger(AddFileExtensionAction.class.getName()); + private final String extStr; + private final String mimeTypeStr; + private final FileExtMismatchSettings settings; - public AddFileExtensionAction(String menuItemStr, String extStr, String mimeTypeStr) { + AddFileExtensionAction(String menuItemStr, String extStr, String mimeTypeStr, FileExtMismatchSettings settings) { super(menuItemStr); this.mimeTypeStr = mimeTypeStr; this.extStr = extStr; + this.settings = settings; } @Override + @Messages({"AddFileExtensionAction.writeError.message=Could not write file extension settings."}) public void actionPerformed(ActionEvent event) { - HashMap editableMap = FileExtMismatchXML.getDefault().load(); - ArrayList editedExtensions = new ArrayList<>(Arrays.asList(editableMap.get(mimeTypeStr))); + HashMap> editableMap; + editableMap = settings.getMimeTypeToExtsMap(); + Set editedExtensions = editableMap.get(mimeTypeStr); editedExtensions.add(extStr); - // Old array will be replaced by new array for this key - editableMap.put(mimeTypeStr, editedExtensions.toArray(new String[0])); - - if (!FileExtMismatchXML.getDefault().save(editableMap)) { + try { + FileExtMismatchSettings.writeSettings(new FileExtMismatchSettings(editableMap)); + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { //error JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.msg"), + Bundle.AddFileExtensionAction_writeError_message(), 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 + logger.log(Level.SEVERE, "Could not write file extension settings.", ex); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties index 1b8dd3acc7..6ac747bd6c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties @@ -1,7 +1,7 @@ OpenIDE-Module-Name=FileExtMismatch OptionsCategory_Name_FileExtMismatchOptions=File Extension Mismatch OptionsCategory_FileExtMismatch=File Extension Mismatch -AddFileExtensionAction.msgDlg.msg=Writing XML configuration file failed. +AddFileExtensionAction.msgDlg.msg2=File extension mismatch settings could not be read, extensions update not available. AddFileExtensionAction.msgDlg.title=Add Mismatch Extension Error AddFileExtensionAction.extHeaderLbl.text=Allowed Extensions for FileExtMismatchConfigPanel.addExtButton.errLabel.empty=Extension text is empty\! @@ -19,7 +19,7 @@ FileExtMismatchConfigPanel.removeExtButton.noneSelected=No extension selected\! FileExtMismatchConfigPanel.removeExtButton.noMimeTypeSelected=No MIME type selected\! FileExtMismatchConfigPanel.removeExtButton.deleted=Extension {0} deleted. FileExtMismatchConfigPanel.store.msg=Saved. -FileExtMismatchConfigPanel.store.msgDlg.msg=Writing XML configuration file failed. +FileExtMismatchConfigPanel.store.msgDlg.msg=File extension mismatch settings could not be saved. FileExtMismatchConfigPanel.save.msgDlg.title=Save Error FileExtMismatchConfigPanel.ok.confDlg.msg=Would you like to save configuration changes? FileExtMismatchConfigPanel.confDlg.title=Unsaved Changes diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java index 005e7fba50..877a92e6e6 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchContextMenuActionsProvider.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,13 +19,13 @@ package org.sleuthkit.autopsy.modules.fileextmismatch; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Set; import java.util.logging.Level; import javax.swing.Action; -import org.openide.util.Lookup; +import javax.swing.JOptionPane; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.openide.util.lookup.ServiceProvider; @@ -34,15 +34,14 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.TskCoreException; /** * This creates a single context menu item for adding a new filename extension - * to the mismatch list for the MIME type of the selected node. + * to the extension list for the MIME type of the selected node. */ @ServiceProvider(service = ContextMenuActionsProvider.class) public class FileExtMismatchContextMenuActionsProvider implements ContextMenuActionsProvider { + private static final Logger logger = Logger.getLogger(FileExtMismatchContextMenuActionsProvider.class.getName()); @Override public List getActions() { @@ -63,22 +62,17 @@ public class FileExtMismatchContextMenuActionsProvider implements ContextMenuAct String mimeTypeStr = ""; String extStr = ""; - AbstractFile af = null; - try { - af = nodeArt.getSleuthkitCase().getAbstractFileById(nodeArt.getObjectID()); - } catch (TskCoreException ex) { - Logger.getLogger(FileExtMismatchContextMenuActionsProvider.class.getName()).log(Level.SEVERE, "Error getting file by id", ex); //NON-NLS - } - + AbstractFile af = Utilities.actionsGlobalContext().lookup(AbstractFile.class); + if (af != null) { - int i = af.getName().lastIndexOf("."); - if ((i > -1) && ((i + 1) < af.getName().length())) { - extStr = af.getName().substring(i + 1).toLowerCase(); - } - mimeTypeStr = af.getMIMEType(); - if(mimeTypeStr == null) { - mimeTypeStr = ""; - } + int i = af.getName().lastIndexOf("."); + if ((i > -1) && ((i + 1) < af.getName().length())) { + extStr = af.getName().substring(i + 1).toLowerCase(); + } + mimeTypeStr = af.getMIMEType(); + if (mimeTypeStr == null) { + mimeTypeStr = ""; + } if (!extStr.isEmpty() && !mimeTypeStr.isEmpty()) { // Limit max size so the context window doesn't get ridiculously wide @@ -91,16 +85,25 @@ public class FileExtMismatchContextMenuActionsProvider implements ContextMenuAct String menuItemStr = NbBundle.getMessage(this.getClass(), "FileExtMismatchContextMenuActionsProvider.menuItemStr", extStr, mimeTypeStr); - actions.add(new AddFileExtensionAction(menuItemStr, extStr, mimeTypeStr)); // Check if already added - HashMap editableMap = FileExtMismatchXML.getDefault().load(); - 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); + HashMap> editableMap; + try { + FileExtMismatchSettings settings = FileExtMismatchSettings.readSettings(); + editableMap = settings.getMimeTypeToExtsMap(); + actions.add(new AddFileExtensionAction(menuItemStr, extStr, mimeTypeStr, settings)); + Set editedExtensions = 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 (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.msg2"), + NbBundle.getMessage(this.getClass(), "AddFileExtensionAction.msgDlg.title"), + JOptionPane.ERROR_MESSAGE); + logger.log(Level.WARNING, "File extension mismatch settings could not be read, extensions update not available.", ex); } - } } } 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 a3b54e8d41..2bcc005749 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java @@ -18,12 +18,12 @@ */ package org.sleuthkit.autopsy.modules.fileextmismatch; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.List; +import java.util.Set; import java.util.logging.Level; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.coreutils.Logger; @@ -31,9 +31,9 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestMessage; +import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -51,7 +51,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule { private static final Logger logger = Logger.getLogger(FileExtMismatchIngestModule.class.getName()); private final IngestServices services = IngestServices.getInstance(); private final FileExtMismatchDetectorModuleSettings settings; - private HashMap SigTypeToExtMap = new HashMap<>(); + private HashMap> mimeTypeToExtsMap = new HashMap<>(); private long jobId; private static final HashMap totalsForIngestJobs = new HashMap<>(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); @@ -87,12 +87,16 @@ public class FileExtMismatchIngestModule implements FileIngestModule { } @Override + @Messages({"FileExtMismatchIngestModule.readError.message=Could not read settings."}) public void startUp(IngestJobContext context) throws IngestModuleException { jobId = context.getJobId(); refCounter.incrementAndGet(jobId); - FileExtMismatchXML xmlLoader = FileExtMismatchXML.getDefault(); - SigTypeToExtMap = xmlLoader.load(); + try { + mimeTypeToExtsMap = FileExtMismatchSettings.readSettings().getMimeTypeToExtsMap(); + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { + throw new IngestModuleException(Bundle.FileExtMismatchIngestModule_readError_message(), ex); + } try { this.detector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { @@ -104,7 +108,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule { @Override public ProcessResult process(AbstractFile abstractFile) { blackboard = Case.getCurrentCase().getServices().getBlackboard(); - if(this.settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) { + if (this.settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) { return ProcessResult.OK; } @@ -175,16 +179,12 @@ public class FileExtMismatchIngestModule implements FileIngestModule { } //get known allowed values from the map for this type - String[] allowedExtArray = SigTypeToExtMap.get(currActualSigType); - if (allowedExtArray != null) { - List allowedExtList = Arrays.asList(allowedExtArray); - + Set allowedExtSet = mimeTypeToExtsMap.get(currActualSigType); + if (allowedExtSet != null) { // see if the filename ext is in the allowed list - if (allowedExtList != null) { - for (String e : allowedExtList) { - if (e.equals(currActualExt)) { - return false; - } + for (String e : allowedExtSet) { + if (e.equals(currActualExt)) { + return false; } return true; //potential mismatch } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettings.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettings.java new file mode 100755 index 0000000000..e489e55975 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettings.java @@ -0,0 +1,196 @@ +/* + * 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. + * 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.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +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 HashMap> mimeTypeToExtsMap; + 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 { + 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 mime type map + * + * @param mimeTypeToExtsMap + */ + FileExtMismatchSettings(HashMap> mimeTypeToExtsMap) { + this.mimeTypeToExtsMap = mimeTypeToExtsMap; + } + + /** + * @return the mime type to extension map + */ + HashMap> getMimeTypeToExtsMap() { + return mimeTypeToExtsMap; + } + + /** + * Sets the signature to extension map for this settings. + */ + void setMimeTypeToExtsMap(HashMap> mimeTypeToExtsMap) { + this.mimeTypeToExtsMap = mimeTypeToExtsMap; + } + + /** + * Reads the file extension mismatch settings. + * + * @return Loaded settings (empty if there are no settings to load). + */ + static synchronized FileExtMismatchSettings readSettings() throws FileExtMismatchSettingsException { + File serializedFile = new File(DEFAULT_SERIALIZED_FILE_PATH); + //Tries reading the serialized file first, as this is the prioritized settings. + if (serializedFile.exists()) { + return readSerializedSettings(); + } + return readXmlSettings(); + } + + private static FileExtMismatchSettings readSerializedSettings() throws FileExtMismatchSettingsException { + File serializedFile = new File(DEFAULT_SERIALIZED_FILE_PATH); + 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); + } + } + + private static FileExtMismatchSettings readXmlSettings() throws FileExtMismatchSettingsException { + HashMap> sigTypeToExtMap = new HashMap<>(); + //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) { + throw new FileExtMismatchSettingsException("Error loading config file: invalid file format (could not load doc)."); + } + + 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 (no 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) { + Set extStrings = new HashSet<>(); + for (int extIndex = 0; extIndex < numExts; ++extIndex) { + Element extEl = (Element) extNList.item(extIndex); + extStrings.add(extEl.getTextContent()); + } + sigTypeToExtMap.put(mimetype, extStrings); + } else { + sigTypeToExtMap.put(mimetype, null); //ok to have an empty type (the ingest module will not use it) + } + } + + } catch (Exception e) { + throw new FileExtMismatchSettingsException("Error loading config file.", e); //NON-NLS + } + } + return new FileExtMismatchSettings(sigTypeToExtMap); + } + + /** + * Save settings to disk. + * + * @param settings The settings to save to disk + * + * @return Loaded hash map or null on error or null if data does not exist + */ + static synchronized void writeSettings(FileExtMismatchSettings settings) throws FileExtMismatchSettingsException { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(DEFAULT_SERIALIZED_FILE_PATH))) { + out.writeObject(settings); + } 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 56883ef119..35bc8d539c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,19 +20,20 @@ package org.sleuthkit.autopsy.modules.fileextmismatch; import java.awt.Color; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; -import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; /** @@ -42,7 +43,7 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel { private static final Logger logger = Logger.getLogger(FileExtMismatchSettingsPanel.class.getName()); - private HashMap editableMap = new HashMap<>(); + private HashMap> editableMap = new HashMap<>(); private ArrayList mimeList = null; private ArrayList currentExtensions = null; private MimeTableModel mimeTableModel; @@ -382,11 +383,11 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel return; } - ArrayList editedExtensions = new ArrayList<>(Arrays.asList(editableMap.get(selectedMime))); + Set editedExtensions = editableMap.get(selectedMime); editedExtensions.add(newExt); // Old array will be replaced by new array for this key - editableMap.put(selectedMime, editedExtensions.toArray(new String[0])); + editableMap.put(selectedMime, editedExtensions); // Refresh table updateExtList(); @@ -430,7 +431,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel return; } - editableMap.put(newMime, new String[0]); + editableMap.put(newMime, new HashSet()); // Refresh table updateMimeList(); @@ -491,12 +492,12 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel return; } - ArrayList editedExtensions = new ArrayList<>(Arrays.asList(editableMap.get(selectedMime))); + Set editedExtensions = editableMap.get(selectedMime); editedExtensions.remove(selectedExt); String deadExt = selectedExt; // Old array will be replaced by new array for this key - editableMap.put(selectedMime, editedExtensions.toArray(new String[0])); + editableMap.put(selectedMime, editedExtensions); // Refresh tables updateExtList(); @@ -517,10 +518,10 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel } private void updateExtList() { - String[] temp = editableMap.get(selectedMime); + Set temp = editableMap.get(selectedMime); if (temp != null) { - currentExtensions = new ArrayList<>(Arrays.asList(temp)); - if (temp.length > 0) { + currentExtensions = new ArrayList<>(temp); + if (temp.size() > 0) { Collections.sort(currentExtensions); } } else { @@ -530,14 +531,15 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel @Override public void saveSettings() { - if (FileExtMismatchXML.getDefault().save(editableMap)) { + try { + FileExtMismatchSettings.writeSettings(new FileExtMismatchSettings(editableMap)); mimeErrLabel.setText(" "); mimeRemoveErrLabel.setText(" "); extRemoveErrLabel.setText(" "); extErrorLabel.setText(" "); saveMsgLabel.setText(NbBundle.getMessage(this.getClass(), "FileExtMismatchConfigPanel.store.msg")); - } else { + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { //error JOptionPane.showMessageDialog(this, NbBundle.getMessage(this.getClass(), @@ -550,9 +552,20 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel @Override public void load() { - // Load the XML 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(); + 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 = FileExtMismatchSettings.readSettings().getMimeTypeToExtsMap(); + + } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) { + //error + JOptionPane.showMessageDialog(this, + NbBundle.getMessage(this.getClass(), + "AddFileExtensionAction.msgDlg.msg2"), + NbBundle.getMessage(this.getClass(), + "FileExtMismatchConfigPanel.save.msgDlg.title"), + JOptionPane.ERROR_MESSAGE); + } updateMimeList(); updateExtList(); } 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 a85964f921..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchXML.java +++ /dev/null @@ -1,185 +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.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.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 - - 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() { - HashMap sigTypeToExtMap = new HashMap<>(); - - 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) { - boolean success; - - DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); - - try { - DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); - Document doc = docBuilder.newDocument(); - - Element rootEl = doc.createElement(ROOT_EL); - doc.appendChild(rootEl); - - ArrayList mimeTypeList = new ArrayList<>(sigTypeToExtMap.keySet()); - Collections.sort(mimeTypeList); - - for (String mimeType : mimeTypeList) { - Element sigEl = doc.createElement(SIG_EL); - sigEl.setAttribute(SIG_MIMETYPE_ATTR, mimeType.toLowerCase()); - - String[] extArray = sigTypeToExtMap.get(mimeType); - if (extArray != null) { - ArrayList extList = new ArrayList<>(Arrays.asList(extArray)); - Collections.sort(extList); - for (String ext : extList) { - Element extEl = doc.createElement(EXT_EL); - extEl.setTextContent(ext.toLowerCase()); - sigEl.appendChild(extEl); - } - } - rootEl.appendChild(sigEl); - } - - success = XMLUtil.saveDoc(FileExtMismatchXML.class, filePath, ENCODING, doc); - - } catch (ParserConfigurationException e) { - logger.log(Level.SEVERE, "Error saving keyword list: can't initialize parser.", e); //NON-NLS - success = false; - } - return success; - } - -}