19 package org.sleuthkit.autopsy.modules.fileextmismatch;
 
   22 import java.io.FileInputStream;
 
   23 import java.io.FileOutputStream;
 
   24 import java.io.IOException;
 
   25 import java.io.Serializable;
 
   26 import java.util.HashMap;
 
   27 import java.util.HashSet;
 
   29 import java.util.logging.Level;
 
   30 import org.openide.util.io.NbObjectInputStream;
 
   31 import org.openide.util.io.NbObjectOutputStream;
 
   35 import org.w3c.dom.Document;
 
   36 import org.w3c.dom.Element;
 
   37 import org.w3c.dom.NodeList;
 
   44 class FileExtMismatchSettings 
implements Serializable {
 
   46     private static final long serialVersionUID = 1L;
 
   47     private HashMap<String, Set<String>> mimeTypeToExtsMap;
 
   48     private static final Logger logger = Logger.getLogger(FileExtMismatchSettings.class.getName());
 
   49     private static final String SIG_EL = 
"signature"; 
 
   50     private static final String EXT_EL = 
"ext";     
 
   51     private static final String SIG_MIMETYPE_ATTR = 
"mimetype"; 
 
   53     private static final String DEFAULT_CONFIG_FILE_NAME = 
"mismatch_config.xml";   
 
   54     private static final String FILTER_CONFIG_FILE = PlatformUtil.getUserConfigDirectory() + File.separator + DEFAULT_CONFIG_FILE_NAME;
 
   55     private static final String DEFAULT_SERIALIZED_FILE_NAME = 
"mismatch_config.settings";
 
   56     private static final String DEFAULT_SERIALIZED_FILE_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + DEFAULT_SERIALIZED_FILE_NAME;
 
   60             PlatformUtil.extractResourceToUserConfigDir(FileExtMismatchSettings.class, DEFAULT_CONFIG_FILE_NAME, 
false);
 
   61         } 
catch (IOException ex) {
 
   62             logger.log(Level.SEVERE, 
"Error copying default mismatch configuration to user dir ", ex); 
 
   71     FileExtMismatchSettings(HashMap<String, Set<String>> mimeTypeToExtsMap) {
 
   72         this.mimeTypeToExtsMap = mimeTypeToExtsMap;
 
   78     HashMap<String, Set<String>> getMimeTypeToExtsMap() {
 
   79         return mimeTypeToExtsMap;
 
   85     void setMimeTypeToExtsMap(HashMap<String, Set<String>> mimeTypeToExtsMap) {
 
   86         this.mimeTypeToExtsMap = mimeTypeToExtsMap;
 
   94     static synchronized FileExtMismatchSettings readSettings() throws FileExtMismatchSettingsException {
 
   95         File serializedFile = 
new File(DEFAULT_SERIALIZED_FILE_PATH);
 
   97         if (serializedFile.exists()) {
 
   98             return readSerializedSettings();
 
  100         return readXmlSettings();
 
  103     private static FileExtMismatchSettings readSerializedSettings() throws FileExtMismatchSettingsException {
 
  104         File serializedFile = 
new File(DEFAULT_SERIALIZED_FILE_PATH);
 
  106             try (NbObjectInputStream in = 
new NbObjectInputStream(
new FileInputStream(serializedFile))) {
 
  107                 FileExtMismatchSettings fileExtMismatchSettings = (FileExtMismatchSettings) in.readObject();
 
  108                 return fileExtMismatchSettings;
 
  110         } 
catch (IOException | ClassNotFoundException ex) {
 
  111             throw new FileExtMismatchSettingsException(
"Couldn't read serialized settings.", ex);
 
  115     private static FileExtMismatchSettings readXmlSettings() throws FileExtMismatchSettingsException {
 
  116         HashMap<String, Set<String>> sigTypeToExtMap = 
new HashMap<>();
 
  118         File xmlFile = 
new File(FILTER_CONFIG_FILE);
 
  119         if (xmlFile.exists()) {
 
  121                 final Document doc = XMLUtil.loadDoc(FileExtMismatchSettings.class, FILTER_CONFIG_FILE);
 
  123                     throw new FileExtMismatchSettingsException(
"Error loading config file: invalid file format (could not load doc).");
 
  126                 Element root = doc.getDocumentElement();
 
  128                     throw new FileExtMismatchSettingsException(
"Error loading config file: invalid file format (bad root)."); 
 
  131                 NodeList sigNList = root.getElementsByTagName(SIG_EL);
 
  132                 final int numSigs = sigNList.getLength();
 
  135                     throw new FileExtMismatchSettingsException(
"Error loading config file: invalid file format (no signature)."); 
 
  138                 for (
int sigIndex = 0; sigIndex < numSigs; ++sigIndex) {
 
  139                     Element sigEl = (Element) sigNList.item(sigIndex);
 
  140                     final String mimetype = sigEl.getAttribute(SIG_MIMETYPE_ATTR);
 
  142                     NodeList extNList = sigEl.getElementsByTagName(EXT_EL);
 
  143                     final int numExts = extNList.getLength();
 
  146                         Set<String> extStrings = 
new HashSet<>();
 
  147                         for (
int extIndex = 0; extIndex < numExts; ++extIndex) {
 
  148                             Element extEl = (Element) extNList.item(extIndex);
 
  149                             extStrings.add(extEl.getTextContent());
 
  151                         sigTypeToExtMap.put(mimetype, extStrings);
 
  153                         sigTypeToExtMap.put(mimetype, null); 
 
  157             } 
catch (Exception e) {
 
  158                 throw new FileExtMismatchSettingsException(
"Error loading config file.", e); 
 
  161         return new FileExtMismatchSettings(sigTypeToExtMap);
 
  171     static synchronized void writeSettings(FileExtMismatchSettings settings) 
throws FileExtMismatchSettingsException {
 
  172         try (NbObjectOutputStream out = 
new NbObjectOutputStream(
new FileOutputStream(DEFAULT_SERIALIZED_FILE_PATH))) {
 
  173             out.writeObject(settings);
 
  174         } 
catch (IOException ex) {
 
  175             throw new FileExtMismatchSettingsException(String.format(
"Failed to write settings to %s", DEFAULT_SERIALIZED_FILE_PATH), ex);
 
  184     static class FileExtMismatchSettingsException 
extends Exception {
 
  186         private static final long serialVersionUID = 1L;
 
  188         FileExtMismatchSettingsException(String message) {
 
  192         FileExtMismatchSettingsException(String message, Throwable throwable) {
 
  193             super(message, throwable);