Merge pull request #2076 from BasisOlivers/aut-2034

Serialization for file extension mismatch
This commit is contained in:
Richard Cordovano 2016-04-19 14:52:25 -04:00
commit cee800dba3
8 changed files with 301 additions and 266 deletions

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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<String, String[]> editableMap = FileExtMismatchXML.getDefault().load();
ArrayList<String> editedExtensions = new ArrayList<>(Arrays.asList(editableMap.get(mimeTypeStr)));
HashMap<String, Set<String>> editableMap;
editableMap = settings.getMimeTypeToExtsMap();
Set<String> 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);
}
}
}

View File

@ -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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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<Action> 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<String, String[]> editableMap = FileExtMismatchXML.getDefault().load();
ArrayList<String> 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<String, Set<String>> editableMap;
try {
FileExtMismatchSettings settings = FileExtMismatchSettings.readSettings();
editableMap = settings.getMimeTypeToExtsMap();
actions.add(new AddFileExtensionAction(menuItemStr, extStr, mimeTypeStr, settings));
Set<String> 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);
}
}
}
}

View File

@ -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);
}

View File

@ -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<String, String[]> SigTypeToExtMap = new HashMap<>();
private HashMap<String, Set<String>> mimeTypeToExtsMap = new HashMap<>();
private long jobId;
private static final HashMap<Long, IngestJobTotals> 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<String> allowedExtList = Arrays.asList(allowedExtArray);
Set<String> 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
}

View File

@ -0,0 +1,196 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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<String, Set<String>> 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<String, Set<String>> mimeTypeToExtsMap) {
this.mimeTypeToExtsMap = mimeTypeToExtsMap;
}
/**
* @return the mime type to extension map
*/
HashMap<String, Set<String>> getMimeTypeToExtsMap() {
return mimeTypeToExtsMap;
}
/**
* Sets the signature to extension map for this settings.
*/
void setMimeTypeToExtsMap(HashMap<String, Set<String>> 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<String, Set<String>> 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<String> 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);
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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<String, String[]> editableMap = new HashMap<>();
private HashMap<String, Set<String>> editableMap = new HashMap<>();
private ArrayList<String> mimeList = null;
private ArrayList<String> currentExtensions = null;
private MimeTableModel mimeTableModel;
@ -382,11 +383,11 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
return;
}
ArrayList<String> editedExtensions = new ArrayList<>(Arrays.asList(editableMap.get(selectedMime)));
Set<String> 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<String>());
// Refresh table
updateMimeList();
@ -491,12 +492,12 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
return;
}
ArrayList<String> editedExtensions = new ArrayList<>(Arrays.asList(editableMap.get(selectedMime)));
Set<String> 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<String> 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();
}

View File

@ -1,185 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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<String, String[]> load() {
HashMap<String, String[]> 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<String> 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<String, String[]> 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<String> 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<String> 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;
}
}