Serialization of user defined file types

This commit is contained in:
Oliver Spohngellert 2016-03-03 16:21:26 -05:00
parent 118fdafaaa
commit f333c66d01
3 changed files with 113 additions and 50 deletions

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.modules.filetypeid; package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.Serializable;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
@ -31,8 +32,9 @@ import org.sleuthkit.datamodel.TskCoreException;
* <p> * <p>
* Thread-safe (immutable). * Thread-safe (immutable).
*/ */
class FileType { class FileType implements Serializable {
private static final long serialVersionUID = 1L;
private final String mimeType; private final String mimeType;
private final Signature signature; private final Signature signature;
private final String interestingFilesSetName; private final String interestingFilesSetName;
@ -114,9 +116,10 @@ class FileType {
public boolean equals(Object other) { public boolean equals(Object other) {
if (other != null && other instanceof FileType) { if (other != null && other instanceof FileType) {
FileType that = (FileType) other; FileType that = (FileType) other;
if(this.getMimeType().equals(that.getMimeType()) && this.getSignature().equals(that.getSignature())) if (this.getMimeType().equals(that.getMimeType()) && this.getSignature().equals(that.getSignature())) {
return true; return true;
} }
}
return false; return false;
} }
@ -134,14 +137,16 @@ class FileType {
* <p> * <p>
* Thread-safe (immutable). * Thread-safe (immutable).
*/ */
static class Signature { static class Signature implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(Signature.class.getName()); private static final Logger logger = Logger.getLogger(Signature.class.getName());
/** /**
* The way the signature byte sequence should be interpreted. * The way the signature byte sequence should be interpreted.
*/ */
enum Type { enum Type {
RAW, ASCII RAW, ASCII
}; };
@ -156,8 +161,8 @@ class FileType {
* *
* @param signatureBytes The signature bytes. * @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param type The type of data in the byte array. Impacts * @param type The type of data in the byte array. Impacts how
* how it is displayed to the user in the UI. * it is displayed to the user in the UI.
*/ */
Signature(final byte[] signatureBytes, long offset, Type type) { Signature(final byte[] signatureBytes, long offset, Type type) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -167,8 +172,8 @@ class FileType {
} }
/** /**
* Creates a file signature consisting of an ASCII string at a * Creates a file signature consisting of an ASCII string at a specific
* specific offset within a file. * offset within a file.
* *
* @param signatureString The ASCII string * @param signatureString The ASCII string
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
@ -204,7 +209,8 @@ class FileType {
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param type The type of data in the byte array. Impacts * @param type The type of data in the byte array. Impacts
* how it is displayed to the user in the UI. * how it is displayed to the user in the UI.
* @param isRelativeToStart Determines whether this signature is relative to start. * @param isRelativeToStart Determines whether this signature is
* relative to start.
*/ */
Signature(final byte[] signatureBytes, long offset, Type type, boolean isRelativeToStart) { Signature(final byte[] signatureBytes, long offset, Type type, boolean isRelativeToStart) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -214,12 +220,13 @@ class FileType {
} }
/** /**
* Creates a file signature consisting of an ASCII string at a * Creates a file signature consisting of an ASCII string at a specific
* specific offset within a file. * offset within a file.
* *
* @param signatureString The ASCII string * @param signatureString The ASCII string
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is relative to start. * @param isRelativeToStart Determines whether this signature is
* relative to start.
*/ */
Signature(String signatureString, long offset, boolean isRelativeToStart) { Signature(String signatureString, long offset, boolean isRelativeToStart) {
this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
@ -236,7 +243,8 @@ class FileType {
* *
* @param signatureBytes The signature bytes. * @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes. * @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is relative to start. * @param isRelativeToStart Determines whether this signature is
* relative to start.
*/ */
Signature(final byte[] signatureBytes, long offset, boolean isRelativeToStart) { Signature(final byte[] signatureBytes, long offset, boolean isRelativeToStart) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -289,8 +297,9 @@ class FileType {
return false; // File is too small, offset lies outside file. return false; // File is too small, offset lies outside file.
} }
long actualOffset = offset; long actualOffset = offset;
if(!isRelativeToStart) if (!isRelativeToStart) {
actualOffset = file.getSize() - 1 - offset; actualOffset = file.getSize() - 1 - offset;
}
if (file.getSize() < (actualOffset + signatureBytes.length)) { if (file.getSize() < (actualOffset + signatureBytes.length)) {
return false; /// too small, can't contain this signature return false; /// too small, can't contain this signature
} }
@ -315,9 +324,10 @@ class FileType {
Signature that = (Signature) other; Signature that = (Signature) other;
if (Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes()) if (Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes())
&& this.getOffset() == that.getOffset() && this.getOffset() == that.getOffset()
&& this.getType().equals(that.getType())) && this.getType().equals(that.getType())) {
return true; return true;
} }
}
return false; return false;
} }

View File

@ -19,7 +19,9 @@
package org.sleuthkit.autopsy.modules.filetypeid; package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.file.Path; import java.nio.file.Path;
@ -27,6 +29,7 @@ import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.persistence.PersistenceException;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -34,10 +37,13 @@ import org.w3c.dom.NodeList;
import javax.xml.bind.DatatypeConverter; import javax.xml.bind.DatatypeConverter;
import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.io.NbObjectInputStream;
import org.openide.util.io.NbObjectOutputStream;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -60,6 +66,7 @@ final class UserDefinedFileTypesManager {
private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName()); private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName());
private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS
private static final String USER_DEFINED_TYPE_SERIALIZATION_FILE = "UserFileTypeDefinitions.settings";
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
@ -323,14 +330,16 @@ final class UserDefinedFileTypesManager {
* @throws TransformerException * @throws TransformerException
*/ */
private static void writeFileTypes(List<FileType> fileTypes, String filePath) throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException { private static void writeFileTypes(List<FileType> fileTypes, String filePath) throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException {
Document doc = XMLUtil.createDocument(); try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)))) {
Element fileTypesElem = doc.createElement(FILE_TYPES_TAG_NAME); UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes);
doc.appendChild(fileTypesElem); out.writeObject(settings);
for (FileType fileType : fileTypes) { File xmlFile = new File(filePath);
Element fileTypeElem = XmlWriter.createFileTypeElement(fileType, doc); if (xmlFile.exists()) {
fileTypesElem.appendChild(fileTypeElem); xmlFile.delete();
}
} catch (IOException ex) {
throw new PersistenceException(String.format("Failed to write settings to %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex);
} }
XMLUtil.saveDocument(doc, ENCODING_FOR_XML_FILE, filePath);
} }
/** /**
@ -457,6 +466,18 @@ final class UserDefinedFileTypesManager {
fileTypes.add(fileType); fileTypes.add(fileType);
} }
} }
} else {
File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE));
if (serializedDefs.exists()) {
try {
try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) {
UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject();
return filesSetsSettings.getUserDefinedFileTypes();
}
} catch (IOException | ClassNotFoundException ex) {
throw new PersistenceException(String.format("Failed to read settings from %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex);
}
}
} }
return fileTypes; return fileTypes;
} }

View File

@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author oliver
*/
class UserDefinedFileTypesSettings implements Serializable {
private static final long serialVersionUID = 1L;
private List<FileType> userDefinedFileTypes;
UserDefinedFileTypesSettings(List<FileType> userDefinedFileTypes) {
this.userDefinedFileTypes = userDefinedFileTypes;
}
/**
* @return the userDefinedFileTypes
*/
public List<FileType> getUserDefinedFileTypes() {
return userDefinedFileTypes;
}
}