From 1c34459ac14ad6a18e702ec2ba5b87f380bbf16e Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 12 May 2016 18:11:24 -0400 Subject: [PATCH] Restore precedence of user-defined custom file types --- .../modules/filetypeid/Bundle.properties | 4 +- .../modules/filetypeid/Bundle_ja.properties | 4 +- .../filetypeid/CustomFileTypesManager.java | 483 ++++++++---------- .../modules/filetypeid/FileTypeDetector.java | 78 ++- .../FileTypeIdGlobalSettingsPanel.java | 11 +- 5 files changed, 281 insertions(+), 299 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties index 3625d53e68..2e4e6187f6 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties @@ -29,8 +29,8 @@ FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.title=M FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title=Save Failed FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title=Load Failed FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to file type definitions when ingest is running! -UserDefinedFileTypesManager.loadFileTypes.errorMessage=Failed to load existing file type definitions. -UserDefinedFileTypesManager.saveFileTypes.errorMessage=Failed to save file type definitions. +FileTypeIdGlobalSettingsPanel.loadFileTypes.errorMessage=Failed to load existing file type definitions. +FileTypeIdGlobalSettingsPanel.saveFileTypes.errorMessage=Failed to save file type definitions. FileTypeIdGlobalSettingsPanel.newTypeButton.text=New Type FileTypeIdGlobalSettingsPanel.jLabel2.text=Custom MIME Types: FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here. diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties index f8eaeea272..ef48c700dc 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties @@ -26,8 +26,8 @@ FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem=\u30b9\u30c8\u30ea\u30 FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem=\u30d0\u30a4\u30c8\uff08HEX\uff09 OptionsCategory_Keywords_FileTypeId=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7ID OptionsCategory_Name_FileTypeId=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 -UserDefinedFileTypesManager.loadFileTypes.errorMessage=\u65e2\u5b58\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f -UserDefinedFileTypesManager.saveFileTypes.errorMessage=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +FileTypeIdGlobalSettingsPanel.loadFileTypes.errorMessage=\u65e2\u5b58\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f +FileTypeIdGlobalSettingsPanel.saveFileTypes.errorMessage=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.message=\u30a2\u30e9\u30fc\u30c8\u3092\u8a2d\u5b9a\u3059\u308b\u306b\u306f\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u540d\u304c\u5fc5\u8981\u3067\u3059\u3002 FileTypeIdGlobalSettingsPanel.offsetComboBox.startItem=\u958b\u59cb FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem=\u505c\u6b62 diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java index 60b5479608..784dea47b9 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java @@ -45,8 +45,8 @@ import org.xml.sax.SAXException; */ final class CustomFileTypesManager { - private static final String XML_SETTINGS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS private static final String SERIALIZED_SETTINGS_FILE = "UserFileTypeDefinitions.settings"; //NON-NLS + private static final String XML_SETTINGS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS private static final String MIME_TYPE_TAG_NAME = "MimeType"; //NON-NLS @@ -56,18 +56,28 @@ final class CustomFileTypesManager { private static final String OFFSET_TAG_NAME = "Offset"; //NON-NLS private static final String RELATIVE_ATTRIBUTE = "RelativeToStart"; //NON-NLS private static CustomFileTypesManager instance; - private final List userDefinedFileTypes = new ArrayList<>(); - private final List allFileTypes = new ArrayList<>(); + private final List autopsyDefinedFileTypes = new ArrayList<>(); + private List userDefinedFileTypes = new ArrayList<>(); /** * Gets the singleton manager of the custom file types defined by Autopsy * and by users. * * @return The custom file types manager singleton. + * + * @throws CustomFileTypesException if there is a problem loading the custom + * file types. */ - synchronized static CustomFileTypesManager getInstance() { - if (instance == null) { + synchronized static CustomFileTypesManager getInstance() throws CustomFileTypesException { + if (null == instance) { instance = new CustomFileTypesManager(); + try { + instance.loadUserDefinedFileTypes(); + instance.createAutopsyDefinedFileTypes(); + } catch (CustomFileTypesException ex) { + instance = null; + throw ex; + } } return instance; } @@ -80,73 +90,56 @@ final class CustomFileTypesManager { } /** - * Gets all of the custom file types defined by Autopsy and by users. + * Gets the custom file types defined by Autopsy and by users. * - * @return A list of file types, possibly empty. - * - * @throws CustomFileTypesException if there is a problem accessing the - * file types. + * @return A list of custom file types, possibly empty. */ - synchronized List getFileTypes() throws CustomFileTypesException { - loadFileTypes(); - + synchronized List getFileTypes() { /** - * It is safe to return references to the internal file type objects - * because they are immutable. Note that - * Collections.unmodifiableCollection() is not used here because this - * view of the file types is a snapshot. + * It is safe to return references instead of copies in this snapshot + * because FileType objects are immutable. */ - return new ArrayList<>(allFileTypes); + List customTypes = new ArrayList<>(userDefinedFileTypes); + customTypes.addAll(autopsyDefinedFileTypes); + return customTypes; } /** - * Gets the custom file types defined by users. + * Gets the user-defined custom file types. * * @return A list of file types, possibly empty. - * - * @throws CustomFileTypesException if there is a problem accessing the - * file types. */ - synchronized List getUserDefinedFileTypes() throws CustomFileTypesException { - loadFileTypes(); - + synchronized List getUserDefinedFileTypes() { /** - * It is safe to return references to the internal file type objects - * because they are immutable. Note that - * Collections.unmodifiableCollection() is not used here because this - * view of the file types is a snapshot. + * It is safe to return references instead of copies in this snapshot + * because FileType objects are immutable. */ return new ArrayList<>(userDefinedFileTypes); } /** - * Loads or re-loads the custom file types defined by Autopsy and by users. + * Sets the user-defined custom file types. * - * @throws CustomFileTypesException if there is a problem loading the - * file types. + * @param newFileTypes A list of user-defined file types. + * + * @throws CustomFileTypesException if there is a problem setting the file + * types. */ - private void loadFileTypes() throws CustomFileTypesException { - allFileTypes.clear(); - userDefinedFileTypes.clear(); - - /** - * Load the predefined types first so that they can be overwritten by - * any user-defined types with the same names. - */ - loadPredefinedFileTypes(); - loadUserDefinedFileTypes(); + synchronized void setUserDefinedFileTypes(List newFileTypes) throws CustomFileTypesException { + String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE); + writeSerializedFileTypes(newFileTypes, filePath); + userDefinedFileTypes = newFileTypes; } /** - * Loads or re-loads the custom file types defined by Autopsy. + * Creates the custom file types defined by Autopsy. * - * @throws CustomFileTypesException if there is a problem loading the - * file types. + * @throws CustomFileTypesException if there is a problem creating the file + * types. */ - private void loadPredefinedFileTypes() throws CustomFileTypesException { + private void createAutopsyDefinedFileTypes() throws CustomFileTypesException { byte[] byteArray; FileType fileType; - try { /* * Add type for xml. @@ -155,7 +148,7 @@ final class CustomFileTypesManager { signatureList = new ArrayList<>(); signatureList.add(new Signature(" fileTypes, String filePath) throws CustomFileTypesException { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { + UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); + out.writeObject(settings); + } catch (IOException ex) { + throw new CustomFileTypesException(String.format("Failed to write settings to %s", filePath), ex); //NON-NLS + } + } + + /** + * Reads serialized custom file types from a file. + * + * @param filePath The path to the file. + * + * @return The custom file types. + * + * @throws CustomFileTypesException if there is a problem reading the file + * types. + */ + private static List readSerializedFileTypes(String filePath) throws CustomFileTypesException { + File serializedDefs = new File(filePath); try { - File serialized = new File(getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE)); - if (serialized.exists()) { - for (FileType fileType : readSerializedFileTypes()) { - addUserDefinedFileType(fileType); - } - } else { - String filePath = getFileTypeDefinitionsFilePath(XML_SETTINGS_FILE); - File xmlFile = new File(filePath); - if (xmlFile.exists()) { - for (FileType fileType : XMLDefinitionsReader.readFileTypes(filePath)) { - addUserDefinedFileType(fileType); + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { + UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); + return filesSetsSettings.getUserDefinedFileTypes(); + } + } catch (IOException | ClassNotFoundException ex) { + throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS + } + } + + /** + * Reads custom file type definitions from an XML file. + * + * @param filePath The path to the file. + * + * @return A collection of custom file types read from the XML file. + * + * @throws IOException if there is problem reading the XML + * file. + * @throws SAXException if there is a problem parsing the + * XML file. + * @throws ParserConfigurationException if there is a problem parsing the + * XML file. + */ + private static List readFileTypesXML(String filePath) throws CustomFileTypesException { + try { + List fileTypes = new ArrayList<>(); + Document doc = XMLUtil.loadDocument(filePath); + if (doc != null) { + Element fileTypesElem = doc.getDocumentElement(); + if (fileTypesElem != null && fileTypesElem.getNodeName().equals(FILE_TYPES_TAG_NAME)) { + NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME); + for (int i = 0; i < fileTypeElems.getLength(); ++i) { + Element fileTypeElem = (Element) fileTypeElems.item(i); + FileType fileType = parseFileType(fileTypeElem); + fileTypes.add(fileType); } } } - + return fileTypes; } catch (IOException | ParserConfigurationException | SAXException ex) { - /** - * Using an all-or-none policy. - */ - allFileTypes.clear(); - userDefinedFileTypes.clear(); - throw new CustomFileTypesException("UserDefinedFileTypesManager.loadFileTypes.errorMessage", ex); + throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS } } /** - * Adds a custom file type to both internal file type lists. + * Gets a custom file type definition from a file type XML element. * - * @param fileType The file type to add. + * @param fileTypeElem The XML element. + * + * @return A file type object. + * + * @throws IllegalArgumentException if there is a problem parsing the file + * type. + * @throws NumberFormatException if there is a problem parsing the file + * type. */ - private void addUserDefinedFileType(FileType fileType) { - userDefinedFileTypes.add(fileType); - allFileTypes.add(fileType); + private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { + String mimeType = parseMimeType(fileTypeElem); + Signature signature = parseSignature(fileTypeElem); + // File type definitions in the XML file were written prior to the + // implementation of multiple signatures per type. + List sigList = new ArrayList<>(); + sigList.add(signature); + return new FileType(mimeType, sigList); } /** - * Sets the user-defined custom file types. + * Gets the MIME type from a file type XML element. * - * @param newFileTypes A list of user-defined file types. + * @param fileTypeElem The element + * + * @return A MIME type string. */ - synchronized void setUserDefinedFileTypes(List newFileTypes) throws CustomFileTypesException { - String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE); - writeFileTypes(newFileTypes, filePath); + private static String parseMimeType(Element fileTypeElem) { + return getChildElementTextContent(fileTypeElem, MIME_TYPE_TAG_NAME); + } + + /** + * Gets the signature from a file type XML element. + * + * @param fileTypeElem The XML element. + * + * @return The signature. + */ + private static Signature parseSignature(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { + NodeList signatureElems = fileTypeElem.getElementsByTagName(SIGNATURE_TAG_NAME); + Element signatureElem = (Element) signatureElems.item(0); + + String sigTypeAttribute = signatureElem.getAttribute(SIGNATURE_TYPE_ATTRIBUTE); + Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute); + + String sigBytesString = getChildElementTextContent(signatureElem, BYTES_TAG_NAME); + byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString); + + Element offsetElem = (Element) signatureElem.getElementsByTagName(OFFSET_TAG_NAME).item(0); + String offsetString = offsetElem.getTextContent(); + long offset = DatatypeConverter.parseLong(offsetString); + + boolean isRelativeToStart; + String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE); + if (null == relativeString || relativeString.equals("")) { + isRelativeToStart = true; + } else { + isRelativeToStart = DatatypeConverter.parseBoolean(relativeString); + } + + return new Signature(signatureBytes, offset, signatureType, isRelativeToStart); + } + + /** + * Gets the text content of a single child element. + * + * @param elem The parent element. + * @param tagName The tag name of the child element. + * + * @return The text content or null if the tag doesn't exist. + */ + private static String getChildElementTextContent(Element elem, String tagName) { + NodeList childElems = elem.getElementsByTagName(tagName); + Node childNode = childElems.item(0); + if (childNode == null) { + return null; + } + Element childElem = (Element) childNode; + return childElem.getTextContent(); } /** @@ -367,176 +484,6 @@ final class CustomFileTypesManager { return filePath.toAbsolutePath().toString(); } - /** - * Writes a collection of custom file types to disk. - * - * @param fileTypes A collection of file types. - * @param filePath The path to the destination file. - * - * @throws CustomFileTypesException if there is a problem writing the - * file types. - */ - private static void writeFileTypes(List fileTypes, String filePath) throws CustomFileTypesException { - try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { - UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); - out.writeObject(settings); - } catch (IOException ex) { - throw new CustomFileTypesException(String.format("Failed to write settings to %s", filePath), ex); //NON-NLS - } - } - - /** - * Reads a collection of custom file types from disk. - * - * @param filePath The path of the file from which the custom file types are - * to be read. - * - * @return The custom file types. - * - * @throws CustomFileTypesException if there is a problem reading the - * file types. - */ - private static List readSerializedFileTypes() throws CustomFileTypesException { - File serializedDefs = new File(getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE)); - try { - try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { - UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); - return filesSetsSettings.getUserDefinedFileTypes(); - } - } catch (IOException | ClassNotFoundException ex) { - throw new CustomFileTypesException("Couldn't read serialized settings.", ex); //NON-NLS - } - } - - /** - * Provides a mechanism for reading a set of custom file type definitions - * from an XML file. - */ - private static class XMLDefinitionsReader { - - /** - * Reads a set of custom file type definitions from an XML file. - * - * @param filePath The path to the XML file. - * - * @return A collection of custom file types read from the XML file. - * - * @throws IOException if there is problem reading the - * XML file. - * @throws SAXException if there is a problem parsing - * the XML file. - * @throws ParserConfigurationException if there is a problem parsing - * the XML file. - */ - private static List readFileTypes(String filePath) throws IOException, SAXException, ParserConfigurationException { - List fileTypes = new ArrayList<>(); - Document doc = XMLUtil.loadDocument(filePath); - if (doc != null) { - Element fileTypesElem = doc.getDocumentElement(); - if (fileTypesElem != null && fileTypesElem.getNodeName().equals(FILE_TYPES_TAG_NAME)) { - NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME); - for (int i = 0; i < fileTypeElems.getLength(); ++i) { - Element fileTypeElem = (Element) fileTypeElems.item(i); - FileType fileType = XMLDefinitionsReader.parseFileType(fileTypeElem); - fileTypes.add(fileType); - } - } - } - return fileTypes; - } - - /** - * Gets a custom file type definition from a file type XML element. - * - * @param fileTypeElem The XML element. - * - * @return A file type object. - * - * @throws IllegalArgumentException if there is a problem parsing the - * file type. - * @throws NumberFormatException if there is a problem parsing the - * file type. - */ - private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { - String mimeType = XMLDefinitionsReader.parseMimeType(fileTypeElem); - Signature signature = XMLDefinitionsReader.parseSignature(fileTypeElem); - // File type definitions in the XML file were written prior to the - // implementation of multiple signatures per type. - List sigList = new ArrayList<>(); - sigList.add(signature); - return new FileType(mimeType, sigList); - } - - /** - * Gets the MIME type from a file type XML element. - * - * @param fileTypeElem The element - * - * @return A MIME type string. - */ - private static String parseMimeType(Element fileTypeElem) { - return getChildElementTextContent(fileTypeElem, MIME_TYPE_TAG_NAME); - } - - /** - * Gets the signature from a file type XML element. - * - * @param fileTypeElem The XML element. - * - * @return The signature. - */ - private static Signature parseSignature(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { - NodeList signatureElems = fileTypeElem.getElementsByTagName(SIGNATURE_TAG_NAME); - Element signatureElem = (Element) signatureElems.item(0); - - String sigTypeAttribute = signatureElem.getAttribute(SIGNATURE_TYPE_ATTRIBUTE); - Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute); - - String sigBytesString = getChildElementTextContent(signatureElem, BYTES_TAG_NAME); - byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString); - - Element offsetElem = (Element) signatureElem.getElementsByTagName(OFFSET_TAG_NAME).item(0); - String offsetString = offsetElem.getTextContent(); - long offset = DatatypeConverter.parseLong(offsetString); - - boolean isRelativeToStart; - String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE); - if (null == relativeString || relativeString.equals("")) { - isRelativeToStart = true; - } else { - isRelativeToStart = DatatypeConverter.parseBoolean(relativeString); - } - - return new Signature(signatureBytes, offset, signatureType, isRelativeToStart); - } - - /** - * Gets the text content of a single child element. - * - * @param elem The parent element. - * @param tagName The tag name of the child element. - * - * @return The text content or null if the tag doesn't exist. - */ - private static String getChildElementTextContent(Element elem, String tagName) { - NodeList childElems = elem.getElementsByTagName(tagName); - Node childNode = childElems.item(0); - if (childNode == null) { - return null; - } - Element childElem = (Element) childNode; - return childElem.getTextContent(); - } - - /** - * Private constructor suppresses creation of instances of this utility - * class. - */ - private XMLDefinitionsReader() { - } - - } - /** * .An exception thrown by the custom file types manager. */ diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index bb65ad7376..44a7cda7da 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -24,9 +24,7 @@ import java.util.SortedSet; import org.apache.tika.Tika; import org.apache.tika.mime.MediaType; import org.apache.tika.mime.MimeTypes; -import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -34,24 +32,22 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** - * Detects the MIME type of a file by an inspection of its contents, using both - * user-defined type definitions and Tika. + * Detects the MIME type of a file by an inspection of its contents, using + * custom file type definitions by users, custom file type definitions by + * Autopsy, and Tika. */ -@NbBundle.Messages({ - "CouldNotInitializeFileTypeDetector=Error loading user-defined file types." -}) public class FileTypeDetector { private static final Tika tika = new Tika(); private static final int BUFFER_SIZE = 64 * 1024; private final byte buffer[] = new byte[BUFFER_SIZE]; private final List userDefinedFileTypes; - private static final Logger logger = Logger.getLogger(FileTypeDetector.class.getName()); + private final List autopsyDefinedFileTypes; /** * Constructs an object that detects the MIME type of a file by an - * inspection of its contents, using both user-defined type definitions and - * Tika. + * inspection of its contents, using custom file type definitions by users, + * custom file type definitions by Autopsy, and Tika. * * @throws FileTypeDetectorInitException if an initialization error occurs, * e.g., user-defined file type @@ -61,24 +57,27 @@ public class FileTypeDetector { public FileTypeDetector() throws FileTypeDetectorInitException { try { userDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes(); + autopsyDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes(); } catch (CustomFileTypesManager.CustomFileTypesException ex) { - throw new FileTypeDetectorInitException(Bundle.CouldNotInitializeFileTypeDetector(), ex); + throw new FileTypeDetectorInitException("Error loading custom file types", ex); //NON-NLS } } /** - * Gets the names of the user-defined MIME types. + * Gets the names of the custom file types defined by the user or by + * Autopsy. * * @return A list of the user-defined MIME types. */ public List getUserDefinedTypes() { - List list = new ArrayList<>(); - if (userDefinedFileTypes != null) { - for (FileType fileType : userDefinedFileTypes) { - list.add(fileType.getMimeType()); - } + List customFileTypes = new ArrayList<>(); + for (FileType fileType : userDefinedFileTypes) { + customFileTypes.add(fileType.getMimeType()); } - return list; + for (FileType fileType : autopsyDefinedFileTypes) { + customFileTypes.add(fileType.getMimeType()); + } + return customFileTypes; } /** @@ -90,7 +89,9 @@ public class FileTypeDetector { * @return True or false. */ public boolean isDetectable(String mimeType) { - return isDetectableAsUserDefinedType(mimeType) || isDetectableByTika(mimeType); + return isDetectableAsCustomType(userDefinedFileTypes, mimeType) + || isDetectableAsCustomType(autopsyDefinedFileTypes, mimeType) + || isDetectableByTika(mimeType); } /** @@ -101,8 +102,8 @@ public class FileTypeDetector { * * @return True or false. */ - private boolean isDetectableAsUserDefinedType(String mimeType) { - for (FileType fileType : userDefinedFileTypes) { + private boolean isDetectableAsCustomType(List customTypes, String mimeType) { + for (FileType fileType : customTypes) { if (fileType.getMimeType().equals(mimeType)) { return true; } @@ -204,12 +205,21 @@ public class FileTypeDetector { } /* - * If the file is a regular file, give precedence to user-defined types. + * If the file is a regular file, give precedence to user-defined custom + * file types. */ if (null == mimeType) { mimeType = detectUserDefinedType(file); } + /* + * If the file does not match a user-defined type, give precedence to + * custom file types defined by Autopsy. + */ + if (null == mimeType) { + mimeType = detectAutopsyDefinedType(file); + } + /* * If the file does not match a user-defined type, send the initial * bytes to Tika. @@ -282,8 +292,8 @@ public class FileTypeDetector { } /** - * Determines whether or not the a file matches a user-defined or Autopsy - * predefined file type. + * Determines whether or not the a file matches a user-defined custom file + * type. * * @param file The file to test. * @@ -300,6 +310,25 @@ public class FileTypeDetector { return null; } + /** + * Determines whether or not the a file matches a custom file type defined + * by Autopsy. + * + * @param file The file to test. + * + * @return The file type name string or null, if no match is detected. + * + * @throws TskCoreException + */ + private String detectAutopsyDefinedType(AbstractFile file) throws TskCoreException { + for (FileType fileType : autopsyDefinedFileTypes) { + if (fileType.matches(file)) { + return fileType.getMimeType(); + } + } + return null; + } + /* * Exception thrown when a file type detector experiences an error * condition. @@ -345,7 +374,6 @@ public class FileTypeDetector { * instead of querying the blackboard. */ @Deprecated - @SuppressWarnings("deprecation") public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException { return getFileType(file); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java index 72e45983ba..5bb72154e5 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java @@ -24,6 +24,7 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.Collections; import java.util.List; +import java.util.logging.Level; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListModel; import javax.swing.JOptionPane; @@ -32,6 +33,7 @@ import javax.swing.event.ListSelectionListener; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; @@ -43,12 +45,15 @@ import org.sleuthkit.autopsy.modules.filetypeid.CustomFileTypesManager.CustomFil * appears in the NetBeans options dialog as an options panel. */ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel { + private static final long serialVersionUID = 1L; + private static final Logger logger = Logger.getLogger(FileTypeIdGlobalSettingsPanel.class.getName()); private static final String RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem"); private static final String ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem"); private static final String START_OFFSET_RELATIVE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.offsetComboBox.startItem"); private static final String END_OFFSET_RELATIVE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem"); + /** * The list model for the file types list component of this panel is the set * of MIME types associated with the user-defined file types. A mapping of @@ -213,8 +218,9 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane typesList.setSelectedIndex(0); } } catch (CustomFileTypesException ex) { + logger.log(Level.SEVERE, "Failed to get custom file types", ex); JOptionPane.showMessageDialog(null, - ex.getLocalizedMessage(), + NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.loadFileTypes.errorMessage"), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title"), JOptionPane.ERROR_MESSAGE); fileTypes = Collections.emptyList(); @@ -268,8 +274,9 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane try { CustomFileTypesManager.getInstance().setUserDefinedFileTypes(fileTypes); } catch (CustomFileTypesManager.CustomFileTypesException ex) { + logger.log(Level.SEVERE, "Failed to set custom file types", ex); JOptionPane.showMessageDialog(null, - ex.getLocalizedMessage(), + NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.saveFileTypes.errorMessage"), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title"), JOptionPane.ERROR_MESSAGE); }