Restore precedence of user-defined custom file types

This commit is contained in:
Richard Cordovano 2016-05-12 18:11:24 -04:00
parent 73c2644bc7
commit 1c34459ac1
5 changed files with 281 additions and 299 deletions

View File

@ -29,8 +29,8 @@ FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.title=M
FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title=Save Failed FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title=Save Failed
FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title=Load Failed FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title=Load Failed
FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to file type definitions when ingest is running! FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to file type definitions when ingest is running!
UserDefinedFileTypesManager.loadFileTypes.errorMessage=Failed to load existing file type definitions. FileTypeIdGlobalSettingsPanel.loadFileTypes.errorMessage=Failed to load existing file type definitions.
UserDefinedFileTypesManager.saveFileTypes.errorMessage=Failed to save file type definitions. FileTypeIdGlobalSettingsPanel.saveFileTypes.errorMessage=Failed to save file type definitions.
FileTypeIdGlobalSettingsPanel.newTypeButton.text=New Type FileTypeIdGlobalSettingsPanel.newTypeButton.text=New Type
FileTypeIdGlobalSettingsPanel.jLabel2.text=Custom MIME Types: FileTypeIdGlobalSettingsPanel.jLabel2.text=Custom MIME Types:
FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here. FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here.

View File

@ -26,8 +26,8 @@ FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem=\u30b9\u30c8\u30ea\u30
FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem=\u30d0\u30a4\u30c8\uff08HEX\uff09 FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem=\u30d0\u30a4\u30c8\uff08HEX\uff09
OptionsCategory_Keywords_FileTypeId=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7ID OptionsCategory_Keywords_FileTypeId=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7ID
OptionsCategory_Name_FileTypeId=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 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 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
UserDefinedFileTypesManager.saveFileTypes.errorMessage=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 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.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.startItem=\u958b\u59cb
FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem=\u505c\u6b62 FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem=\u505c\u6b62

View File

@ -45,8 +45,8 @@ import org.xml.sax.SAXException;
*/ */
final class CustomFileTypesManager { 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 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_TYPES_TAG_NAME = "FileTypes"; //NON-NLS
private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS
private static final String MIME_TYPE_TAG_NAME = "MimeType"; //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 OFFSET_TAG_NAME = "Offset"; //NON-NLS
private static final String RELATIVE_ATTRIBUTE = "RelativeToStart"; //NON-NLS private static final String RELATIVE_ATTRIBUTE = "RelativeToStart"; //NON-NLS
private static CustomFileTypesManager instance; private static CustomFileTypesManager instance;
private final List<FileType> userDefinedFileTypes = new ArrayList<>(); private final List<FileType> autopsyDefinedFileTypes = new ArrayList<>();
private final List<FileType> allFileTypes = new ArrayList<>(); private List<FileType> userDefinedFileTypes = new ArrayList<>();
/** /**
* Gets the singleton manager of the custom file types defined by Autopsy * Gets the singleton manager of the custom file types defined by Autopsy
* and by users. * and by users.
* *
* @return The custom file types manager singleton. * @return The custom file types manager singleton.
*
* @throws CustomFileTypesException if there is a problem loading the custom
* file types.
*/ */
synchronized static CustomFileTypesManager getInstance() { synchronized static CustomFileTypesManager getInstance() throws CustomFileTypesException {
if (instance == null) { if (null == instance) {
instance = new CustomFileTypesManager(); instance = new CustomFileTypesManager();
try {
instance.loadUserDefinedFileTypes();
instance.createAutopsyDefinedFileTypes();
} catch (CustomFileTypesException ex) {
instance = null;
throw ex;
}
} }
return instance; 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. * @return A list of custom file types, possibly empty.
*
* @throws CustomFileTypesException if there is a problem accessing the
* file types.
*/ */
synchronized List<FileType> getFileTypes() throws CustomFileTypesException { synchronized List<FileType> getFileTypes() {
loadFileTypes();
/** /**
* It is safe to return references to the internal file type objects * It is safe to return references instead of copies in this snapshot
* because they are immutable. Note that * because FileType objects are immutable.
* Collections.unmodifiableCollection() is not used here because this
* view of the file types is a snapshot.
*/ */
return new ArrayList<>(allFileTypes); List<FileType> 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. * @return A list of file types, possibly empty.
*
* @throws CustomFileTypesException if there is a problem accessing the
* file types.
*/ */
synchronized List<FileType> getUserDefinedFileTypes() throws CustomFileTypesException { synchronized List<FileType> getUserDefinedFileTypes() {
loadFileTypes();
/** /**
* It is safe to return references to the internal file type objects * It is safe to return references instead of copies in this snapshot
* because they are immutable. Note that * because FileType objects are immutable.
* Collections.unmodifiableCollection() is not used here because this
* view of the file types is a snapshot.
*/ */
return new ArrayList<>(userDefinedFileTypes); 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 * @param newFileTypes A list of user-defined file types.
* file types. *
* @throws CustomFileTypesException if there is a problem setting the file
* types.
*/ */
private void loadFileTypes() throws CustomFileTypesException { synchronized void setUserDefinedFileTypes(List<FileType> newFileTypes) throws CustomFileTypesException {
allFileTypes.clear(); String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE);
userDefinedFileTypes.clear(); writeSerializedFileTypes(newFileTypes, filePath);
userDefinedFileTypes = newFileTypes;
/**
* Load the predefined types first so that they can be overwritten by
* any user-defined types with the same names.
*/
loadPredefinedFileTypes();
loadUserDefinedFileTypes();
} }
/** /**
* 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 * @throws CustomFileTypesException if there is a problem creating the file
* file types. * types.
*/ */
private void loadPredefinedFileTypes() throws CustomFileTypesException { private void createAutopsyDefinedFileTypes() throws CustomFileTypesException {
byte[] byteArray; byte[] byteArray;
FileType fileType; FileType fileType;
try { try {
/* /*
* Add type for xml. * Add type for xml.
@ -155,7 +148,7 @@ final class CustomFileTypesManager {
signatureList = new ArrayList<>(); signatureList = new ArrayList<>();
signatureList.add(new Signature("<?xml", 0L)); //NON-NLS signatureList.add(new Signature("<?xml", 0L)); //NON-NLS
fileType = new FileType("text/xml", signatureList); //NON-NLS fileType = new FileType("text/xml", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for gzip. * Add type for gzip.
@ -164,7 +157,7 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature(byteArray, 0L)); signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("application/x-gzip", signatureList); //NON-NLS fileType = new FileType("application/x-gzip", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for wk1. * Add type for wk1.
@ -173,7 +166,7 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature(byteArray, 0L)); signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("application/x-123", signatureList); //NON-NLS fileType = new FileType("application/x-123", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for Radiance images. * Add type for Radiance images.
@ -182,7 +175,7 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature(byteArray, 0L)); signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("image/vnd.radiance", signatureList); //NON-NLS fileType = new FileType("image/vnd.radiance", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for dcx images. * Add type for dcx images.
@ -191,7 +184,7 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature(byteArray, 0L)); signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("image/x-dcx", signatureList); //NON-NLS fileType = new FileType("image/x-dcx", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for ics images. * Add type for ics images.
@ -199,7 +192,7 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("icns", 0L)); //NON-NLS signatureList.add(new Signature("icns", 0L)); //NON-NLS
fileType = new FileType("image/x-icns", signatureList); //NON-NLS fileType = new FileType("image/x-icns", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for pict images. * Add type for pict images.
@ -208,12 +201,12 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature(byteArray, 522L)); signatureList.add(new Signature(byteArray, 522L));
fileType = new FileType("image/x-pict", signatureList); //NON-NLS fileType = new FileType("image/x-pict", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
byteArray = DatatypeConverter.parseHexBinary("1100"); //NON-NLS byteArray = DatatypeConverter.parseHexBinary("1100"); //NON-NLS
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature(byteArray, 522L)); signatureList.add(new Signature(byteArray, 522L));
fileType = new FileType("image/x-pict", signatureList); //NON-NLS fileType = new FileType("image/x-pict", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for pam. * Add type for pam.
@ -221,7 +214,7 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("P7", 0L)); //NON-NLS signatureList.add(new Signature("P7", 0L)); //NON-NLS
fileType = new FileType("image/x-portable-arbitrarymap", signatureList); //NON-NLS fileType = new FileType("image/x-portable-arbitrarymap", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for pfm. * Add type for pfm.
@ -229,11 +222,11 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("PF", 0L)); //NON-NLS signatureList.add(new Signature("PF", 0L)); //NON-NLS
fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("Pf", 0L)); //NON-NLS signatureList.add(new Signature("Pf", 0L)); //NON-NLS
fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for tga. * Add type for tga.
@ -242,7 +235,7 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature(byteArray, 17, false)); signatureList.add(new Signature(byteArray, 17, false));
fileType = new FileType("image/x-tga", signatureList); //NON-NLS fileType = new FileType("image/x-tga", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for ilbm. * Add type for ilbm.
@ -251,12 +244,12 @@ final class CustomFileTypesManager {
signatureList.add(new Signature("FORM", 0L)); //NON-NLS signatureList.add(new Signature("FORM", 0L)); //NON-NLS
signatureList.add(new Signature("ILBM", 8L)); //NON-NLS signatureList.add(new Signature("ILBM", 8L)); //NON-NLS
fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("FORM", 0L)); //NON-NLS signatureList.add(new Signature("FORM", 0L)); //NON-NLS
signatureList.add(new Signature("PBM", 8L)); //NON-NLS signatureList.add(new Signature("PBM", 8L)); //NON-NLS
fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for webp. * Add type for webp.
@ -265,7 +258,7 @@ final class CustomFileTypesManager {
signatureList.add(new Signature("RIFF", 0L)); //NON-NLS signatureList.add(new Signature("RIFF", 0L)); //NON-NLS
signatureList.add(new Signature("WEBP", 8L)); //NON-NLS signatureList.add(new Signature("WEBP", 8L)); //NON-NLS
fileType = new FileType("image/webp", signatureList); //NON-NLS fileType = new FileType("image/webp", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for aiff. * Add type for aiff.
@ -274,17 +267,17 @@ final class CustomFileTypesManager {
signatureList.add(new Signature("FORM", 0L)); //NON-NLS signatureList.add(new Signature("FORM", 0L)); //NON-NLS
signatureList.add(new Signature("AIFF", 8L)); //NON-NLS signatureList.add(new Signature("AIFF", 8L)); //NON-NLS
fileType = new FileType("audio/aiff", signatureList); //NON-NLS fileType = new FileType("audio/aiff", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("FORM", 0L)); //NON-NLS signatureList.add(new Signature("FORM", 0L)); //NON-NLS
signatureList.add(new Signature("AIFC", 8L)); //NON-NLS signatureList.add(new Signature("AIFC", 8L)); //NON-NLS
fileType = new FileType("audio/aiff", signatureList); //NON-NLS fileType = new FileType("audio/aiff", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("FORM", 0L)); //NON-NLS signatureList.add(new Signature("FORM", 0L)); //NON-NLS
signatureList.add(new Signature("8SVX", 8L)); //NON-NLS signatureList.add(new Signature("8SVX", 8L)); //NON-NLS
fileType = new FileType("audio/aiff", signatureList); //NON-NLS fileType = new FileType("audio/aiff", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/* /*
* Add type for iff. * Add type for iff.
@ -292,91 +285,45 @@ final class CustomFileTypesManager {
signatureList.clear(); signatureList.clear();
signatureList.add(new Signature("FORM", 0L)); //NON-NLS signatureList.add(new Signature("FORM", 0L)); //NON-NLS
fileType = new FileType("application/x-iff", signatureList); //NON-NLS fileType = new FileType("application/x-iff", signatureList); //NON-NLS
allFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
/* /*
* parseHexBinary() throws this if the argument passed in is not hex * parseHexBinary() throws this if the argument passed in is not hex
*/ */
throw new CustomFileTypesException("Error creating predefined file types", ex); // throw new CustomFileTypesException("Error creating Autopsy defined custom file types", ex); //NON-NLS
} }
} }
/** /**
* Loads or re-loads the custom file types defined by users. * Loads the custom file types defined by users.
* *
* @throws CustomFileTypesException if there is a problem loading the * @throws CustomFileTypesException if there is a problem loading the file
* file types. * types.
*/ */
private void loadUserDefinedFileTypes() throws CustomFileTypesException { private void loadUserDefinedFileTypes() throws CustomFileTypesException {
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);
}
}
}
} catch (IOException | ParserConfigurationException | SAXException ex) {
/**
* Using an all-or-none policy.
*/
allFileTypes.clear();
userDefinedFileTypes.clear(); userDefinedFileTypes.clear();
throw new CustomFileTypesException("UserDefinedFileTypesManager.loadFileTypes.errorMessage", ex);
}
}
/**
* Adds a custom file type to both internal file type lists.
*
* @param fileType The file type to add.
*/
private void addUserDefinedFileType(FileType fileType) {
userDefinedFileTypes.add(fileType);
allFileTypes.add(fileType);
}
/**
* Sets the user-defined custom file types.
*
* @param newFileTypes A list of user-defined file types.
*/
synchronized void setUserDefinedFileTypes(List<FileType> newFileTypes) throws CustomFileTypesException {
String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE); String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE);
writeFileTypes(newFileTypes, filePath); if (new File(filePath).exists()) {
userDefinedFileTypes = readSerializedFileTypes(filePath);
} else {
filePath = getFileTypeDefinitionsFilePath(XML_SETTINGS_FILE);
if (new File(filePath).exists()) {
userDefinedFileTypes = readFileTypesXML(filePath);
}
}
} }
/** /**
* Gets the absolute path of a file type definitions file. * Writes serialized custom file types to a file.
*
* @param fileName The name of the file.
*
* @return The absolute path to the file.
*/
private static String getFileTypeDefinitionsFilePath(String fileName) {
Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName);
return filePath.toAbsolutePath().toString();
}
/**
* Writes a collection of custom file types to disk.
* *
* @param fileTypes A collection of file types. * @param fileTypes A collection of file types.
* @param filePath The path to the destination file. * @param filePath The path to the file.
* *
* @throws CustomFileTypesException if there is a problem writing the * @throws CustomFileTypesException if there is a problem writing the file
* file types. * types.
*/ */
private static void writeFileTypes(List<FileType> fileTypes, String filePath) throws CustomFileTypesException { private static void writeSerializedFileTypes(List<FileType> fileTypes, String filePath) throws CustomFileTypesException {
try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) {
UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes);
out.writeObject(settings); out.writeObject(settings);
@ -386,49 +333,43 @@ final class CustomFileTypesManager {
} }
/** /**
* Reads a collection of custom file types from disk. * Reads serialized custom file types from a file.
* *
* @param filePath The path of the file from which the custom file types are * @param filePath The path to the file.
* to be read.
* *
* @return The custom file types. * @return The custom file types.
* *
* @throws CustomFileTypesException if there is a problem reading the * @throws CustomFileTypesException if there is a problem reading the file
* file types. * types.
*/ */
private static List<FileType> readSerializedFileTypes() throws CustomFileTypesException { private static List<FileType> readSerializedFileTypes(String filePath) throws CustomFileTypesException {
File serializedDefs = new File(getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE)); File serializedDefs = new File(filePath);
try { try {
try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) {
UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject();
return filesSetsSettings.getUserDefinedFileTypes(); return filesSetsSettings.getUserDefinedFileTypes();
} }
} catch (IOException | ClassNotFoundException ex) { } catch (IOException | ClassNotFoundException ex) {
throw new CustomFileTypesException("Couldn't read serialized settings.", ex); //NON-NLS throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS
} }
} }
/** /**
* Provides a mechanism for reading a set of custom file type definitions * Reads custom file type definitions from an XML file.
* 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. * @param filePath The path to the file.
* *
* @return A collection of custom file types read from the XML file. * @return A collection of custom file types read from the XML file.
* *
* @throws IOException if there is problem reading the * @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. * 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<FileType> readFileTypes(String filePath) throws IOException, SAXException, ParserConfigurationException { private static List<FileType> readFileTypesXML(String filePath) throws CustomFileTypesException {
try {
List<FileType> fileTypes = new ArrayList<>(); List<FileType> fileTypes = new ArrayList<>();
Document doc = XMLUtil.loadDocument(filePath); Document doc = XMLUtil.loadDocument(filePath);
if (doc != null) { if (doc != null) {
@ -437,12 +378,15 @@ final class CustomFileTypesManager {
NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME); NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME);
for (int i = 0; i < fileTypeElems.getLength(); ++i) { for (int i = 0; i < fileTypeElems.getLength(); ++i) {
Element fileTypeElem = (Element) fileTypeElems.item(i); Element fileTypeElem = (Element) fileTypeElems.item(i);
FileType fileType = XMLDefinitionsReader.parseFileType(fileTypeElem); FileType fileType = parseFileType(fileTypeElem);
fileTypes.add(fileType); fileTypes.add(fileType);
} }
} }
} }
return fileTypes; return fileTypes;
} catch (IOException | ParserConfigurationException | SAXException ex) {
throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS
}
} }
/** /**
@ -452,14 +396,14 @@ final class CustomFileTypesManager {
* *
* @return A file type object. * @return A file type object.
* *
* @throws IllegalArgumentException if there is a problem parsing the * @throws IllegalArgumentException if there is a problem parsing the file
* file type. * type.
* @throws NumberFormatException if there is a problem parsing the * @throws NumberFormatException if there is a problem parsing the file
* file type. * type.
*/ */
private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
String mimeType = XMLDefinitionsReader.parseMimeType(fileTypeElem); String mimeType = parseMimeType(fileTypeElem);
Signature signature = XMLDefinitionsReader.parseSignature(fileTypeElem); Signature signature = parseSignature(fileTypeElem);
// File type definitions in the XML file were written prior to the // File type definitions in the XML file were written prior to the
// implementation of multiple signatures per type. // implementation of multiple signatures per type.
List<Signature> sigList = new ArrayList<>(); List<Signature> sigList = new ArrayList<>();
@ -529,12 +473,15 @@ final class CustomFileTypesManager {
} }
/** /**
* Private constructor suppresses creation of instances of this utility * Gets the absolute path of a file type definitions file.
* class. *
* @param fileName The name of the file.
*
* @return The absolute path to the file.
*/ */
private XMLDefinitionsReader() { private static String getFileTypeDefinitionsFilePath(String fileName) {
} Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName);
return filePath.toAbsolutePath().toString();
} }
/** /**

View File

@ -24,9 +24,7 @@ import java.util.SortedSet;
import org.apache.tika.Tika; import org.apache.tika.Tika;
import org.apache.tika.mime.MediaType; import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypes; import org.apache.tika.mime.MimeTypes;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
@ -34,24 +32,22 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
/** /**
* Detects the MIME type of a file by an inspection of its contents, using both * Detects the MIME type of a file by an inspection of its contents, using
* user-defined type definitions and Tika. * 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 { public class FileTypeDetector {
private static final Tika tika = new Tika(); private static final Tika tika = new Tika();
private static final int BUFFER_SIZE = 64 * 1024; private static final int BUFFER_SIZE = 64 * 1024;
private final byte buffer[] = new byte[BUFFER_SIZE]; private final byte buffer[] = new byte[BUFFER_SIZE];
private final List<FileType> userDefinedFileTypes; private final List<FileType> userDefinedFileTypes;
private static final Logger logger = Logger.getLogger(FileTypeDetector.class.getName()); private final List<FileType> autopsyDefinedFileTypes;
/** /**
* Constructs an object that detects the MIME type of a file by an * Constructs an object that detects the MIME type of a file by an
* inspection of its contents, using both user-defined type definitions and * inspection of its contents, using custom file type definitions by users,
* Tika. * custom file type definitions by Autopsy, and Tika.
* *
* @throws FileTypeDetectorInitException if an initialization error occurs, * @throws FileTypeDetectorInitException if an initialization error occurs,
* e.g., user-defined file type * e.g., user-defined file type
@ -61,24 +57,27 @@ public class FileTypeDetector {
public FileTypeDetector() throws FileTypeDetectorInitException { public FileTypeDetector() throws FileTypeDetectorInitException {
try { try {
userDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes(); userDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes();
autopsyDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes();
} catch (CustomFileTypesManager.CustomFileTypesException ex) { } 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. * @return A list of the user-defined MIME types.
*/ */
public List<String> getUserDefinedTypes() { public List<String> getUserDefinedTypes() {
List<String> list = new ArrayList<>(); List<String> customFileTypes = new ArrayList<>();
if (userDefinedFileTypes != null) {
for (FileType fileType : userDefinedFileTypes) { for (FileType fileType : userDefinedFileTypes) {
list.add(fileType.getMimeType()); customFileTypes.add(fileType.getMimeType());
} }
for (FileType fileType : autopsyDefinedFileTypes) {
customFileTypes.add(fileType.getMimeType());
} }
return list; return customFileTypes;
} }
/** /**
@ -90,7 +89,9 @@ public class FileTypeDetector {
* @return True or false. * @return True or false.
*/ */
public boolean isDetectable(String mimeType) { 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. * @return True or false.
*/ */
private boolean isDetectableAsUserDefinedType(String mimeType) { private boolean isDetectableAsCustomType(List<FileType> customTypes, String mimeType) {
for (FileType fileType : userDefinedFileTypes) { for (FileType fileType : customTypes) {
if (fileType.getMimeType().equals(mimeType)) { if (fileType.getMimeType().equals(mimeType)) {
return true; 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) { if (null == mimeType) {
mimeType = detectUserDefinedType(file); 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 * If the file does not match a user-defined type, send the initial
* bytes to Tika. * bytes to Tika.
@ -282,8 +292,8 @@ public class FileTypeDetector {
} }
/** /**
* Determines whether or not the a file matches a user-defined or Autopsy * Determines whether or not the a file matches a user-defined custom file
* predefined file type. * type.
* *
* @param file The file to test. * @param file The file to test.
* *
@ -300,6 +310,25 @@ public class FileTypeDetector {
return null; 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 * Exception thrown when a file type detector experiences an error
* condition. * condition.
@ -345,7 +374,6 @@ public class FileTypeDetector {
* instead of querying the blackboard. * instead of querying the blackboard.
*/ */
@Deprecated @Deprecated
@SuppressWarnings("deprecation")
public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException { public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException {
return getFileType(file); return getFileType(file);
} }

View File

@ -24,6 +24,7 @@ import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@ -32,6 +33,7 @@ import javax.swing.event.ListSelectionListener;
import org.netbeans.spi.options.OptionsPanelController; import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; 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. * appears in the NetBeans options dialog as an options panel.
*/ */
final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel { 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 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 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 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"); 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 * 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 * 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); typesList.setSelectedIndex(0);
} }
} catch (CustomFileTypesException ex) { } catch (CustomFileTypesException ex) {
logger.log(Level.SEVERE, "Failed to get custom file types", ex);
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
ex.getLocalizedMessage(), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.loadFileTypes.errorMessage"),
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title"), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
fileTypes = Collections.emptyList(); fileTypes = Collections.emptyList();
@ -268,8 +274,9 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
try { try {
CustomFileTypesManager.getInstance().setUserDefinedFileTypes(fileTypes); CustomFileTypesManager.getInstance().setUserDefinedFileTypes(fileTypes);
} catch (CustomFileTypesManager.CustomFileTypesException ex) { } catch (CustomFileTypesManager.CustomFileTypesException ex) {
logger.log(Level.SEVERE, "Failed to set custom file types", ex);
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
ex.getLocalizedMessage(), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.saveFileTypes.errorMessage"),
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title"), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} }