19 package org.sleuthkit.autopsy.modules.filetypeid;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.UnsupportedEncodingException;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.HashMap;
30 import java.util.List;
32 import java.util.logging.Level;
33 import javax.xml.parsers.ParserConfigurationException;
34 import org.w3c.dom.Document;
35 import org.w3c.dom.Element;
36 import org.w3c.dom.NodeList;
37 import javax.xml.bind.DatatypeConverter;
38 import javax.xml.transform.TransformerException;
39 import org.openide.util.NbBundle;
44 import org.xml.sax.SAXException;
61 final class UserDefinedFileTypesManager {
63 private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName());
64 private static final String FILE_TYPE_DEFINITIONS_SCHEMA_FILE =
"FileTypes.xsd";
65 private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE =
"UserFileTypeDefinitions.xml";
66 private static final String FILE_TYPES_TAG_NAME =
"FileTypes";
67 private static final String FILE_TYPE_TAG_NAME =
"FileType";
68 private static final String MIME_TYPE_TAG_NAME =
"MimeType";
69 private static final String SIGNATURE_TAG_NAME =
"Signature";
70 private static final String SIGNATURE_TYPE_ATTRIBUTE =
"type";
71 private static final String BYTES_TAG_NAME =
"Bytes";
72 private static final String OFFSET_TAG_NAME =
"Offset";
73 private static final String INTERESTING_FILES_SET_TAG_NAME =
"InterestingFileSset";
74 private static final String ALERT_ATTRIBUTE =
"alert";
75 private static final String ENCODING_FOR_XML_FILE =
"UTF-8";
76 private static final String ASCII_ENCODING =
"US-ASCII";
77 private static UserDefinedFileTypesManager instance;
85 private final Map<String, FileType> userDefinedFileTypes =
new HashMap<>();
94 private final Map<String, FileType> fileTypes =
new HashMap<>();
103 synchronized static UserDefinedFileTypesManager getInstance() {
104 if (instance == null) {
105 instance =
new UserDefinedFileTypesManager();
114 private UserDefinedFileTypesManager() {
124 synchronized Map<String, FileType> getFileTypes() throws UserDefinedFileTypesException {
133 return new HashMap<>(fileTypes);
143 synchronized Map<String, FileType> getUserDefinedFileTypes() throws UserDefinedFileTypesException {
152 return new HashMap<>(userDefinedFileTypes);
162 private void loadFileTypes() throws UserDefinedFileTypesException {
164 userDefinedFileTypes.clear();
169 loadPredefinedFileTypes();
170 loadUserDefinedFileTypes();
180 private void loadPredefinedFileTypes() throws UserDefinedFileTypesException {
182 FileType fileType =
new FileType(
"text/xml",
new Signature(
"<?xml".getBytes(ASCII_ENCODING), 0L, FileType.Signature.Type.ASCII),
"",
false);
183 fileTypes.put(fileType.getMimeType(), fileType);
185 }
catch (UnsupportedEncodingException ex) {
190 throwUserDefinedFileTypesException(ex,
"UserDefinedFileTypesManager.loadFileTypes.errorMessage");
201 private void loadUserDefinedFileTypes() throws UserDefinedFileTypesException {
203 String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE);
204 File file =
new File(filePath);
205 if (file.exists() && file.canRead()) {
206 for (FileType fileType : XmlReader.readFileTypes(filePath)) {
207 addUserDefinedFileType(fileType);
211 }
catch (IOException | ParserConfigurationException | SAXException ex) {
216 userDefinedFileTypes.clear();
217 throwUserDefinedFileTypesException(ex,
"UserDefinedFileTypesManager.loadFileTypes.errorMessage");
227 private void addUserDefinedFileType(FileType fileType) {
228 userDefinedFileTypes.put(fileType.getMimeType(), fileType);
229 fileTypes.put(fileType.getMimeType(), fileType);
238 synchronized void setUserDefinedFileTypes(Map<String, FileType> newFileTypes)
throws UserDefinedFileTypesException {
240 String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE);
241 XmlWriter.writeFileTypes(newFileTypes.values(), filePath);
242 }
catch (ParserConfigurationException | FileNotFoundException | UnsupportedEncodingException | TransformerException ex) {
243 throwUserDefinedFileTypesException(ex,
"UserDefinedFileTypesManager.saveFileTypes.errorMessage");
244 }
catch (IOException ex) {
245 throwUserDefinedFileTypesException(ex,
"UserDefinedFileTypesManager.saveFileTypes.errorMessage");
255 private static String getFileTypeDefinitionsFilePath(String fileName) {
256 Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName);
257 return filePath.toAbsolutePath().toString();
277 private static void writeFileTypes(Collection<FileType> fileTypes, String filePath)
throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException {
279 Element fileTypesElem = doc.createElement(FILE_TYPES_TAG_NAME);
280 doc.appendChild(fileTypesElem);
281 for (FileType fileType : fileTypes) {
283 fileTypesElem.appendChild(fileTypeElem);
296 Element fileTypeElem = doc.createElement(FILE_TYPE_TAG_NAME);
312 Element typeNameElem = doc.createElement(MIME_TYPE_TAG_NAME);
313 typeNameElem.setTextContent(fileType.getMimeType());
314 fileTypeElem.appendChild(typeNameElem);
325 Signature signature = fileType.getSignature();
326 Element signatureElem = doc.createElement(SIGNATURE_TAG_NAME);
328 Element bytesElem = doc.createElement(BYTES_TAG_NAME);
329 bytesElem.setTextContent(DatatypeConverter.printHexBinary(signature.getSignatureBytes()));
330 signatureElem.appendChild(bytesElem);
332 Element offsetElem = doc.createElement(OFFSET_TAG_NAME);
333 offsetElem.setTextContent(DatatypeConverter.printLong(signature.getOffset()));
334 signatureElem.appendChild(offsetElem);
336 signatureElem.setAttribute(SIGNATURE_TYPE_ATTRIBUTE, signature.getType().toString());
337 fileTypeElem.appendChild(signatureElem);
348 if (!fileType.getFilesSetName().isEmpty()) {
349 Element filesSetElem = doc.createElement(INTERESTING_FILES_SET_TAG_NAME);
350 filesSetElem.setTextContent(fileType.getFilesSetName());
351 fileTypeElem.appendChild(filesSetElem);
362 fileTypeElem.setAttribute(ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch()));
379 private static List<FileType>
readFileTypes(String filePath)
throws IOException, ParserConfigurationException, SAXException {
380 List<FileType> fileTypes =
new ArrayList<>();
381 Document doc =
XMLUtil.
loadDocument(filePath, UserDefinedFileTypesManager.class, FILE_TYPE_DEFINITIONS_SCHEMA_FILE);
383 Element fileTypesElem = doc.getDocumentElement();
384 if (fileTypesElem != null && fileTypesElem.getNodeName().equals(FILE_TYPES_TAG_NAME)) {
385 NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME);
386 for (
int i = 0; i < fileTypeElems.getLength(); ++i) {
387 Element fileTypeElem = (Element) fileTypeElems.item(i);
389 fileTypes.add(fileType);
404 private static FileType
parseFileType(Element fileTypeElem)
throws IllegalArgumentException, NumberFormatException {
409 return new FileType(mimeType, signature, filesSetName, alert);
428 private static Signature
parseSignature(Element fileTypeElem)
throws IllegalArgumentException, NumberFormatException {
429 NodeList signatureElems = fileTypeElem.getElementsByTagName(SIGNATURE_TAG_NAME);
430 Element signatureElem = (Element) signatureElems.item(0);
432 String sigTypeAttribute = signatureElem.getAttribute(SIGNATURE_TYPE_ATTRIBUTE);
433 Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute);
436 byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString);
439 long offset = DatatypeConverter.parseLong(offsetString);
441 return new Signature(signatureBytes, offset, signatureType);
451 String filesSetName =
"";
452 NodeList filesSetElems = fileTypeElem.getElementsByTagName(INTERESTING_FILES_SET_TAG_NAME);
453 if (filesSetElems.getLength() > 0) {
454 Element filesSetElem = (Element) filesSetElems.item(0);
455 filesSetName = filesSetElem.getTextContent();
467 String alertAttribute = fileTypeElem.getAttribute(ALERT_ATTRIBUTE);
468 return Boolean.parseBoolean(alertAttribute);
479 NodeList childElems = elem.getElementsByTagName(tagName);
480 Element childElem = (Element) childElems.item(0);
481 return childElem.getTextContent();
496 private void throwUserDefinedFileTypesException(Exception ex, String messageKey)
throws UserDefinedFileTypesException {
497 String message = NbBundle.getMessage(UserDefinedFileTypesManager.class, messageKey);
498 logger.log(Level.SEVERE, message, ex);
499 throw new UserDefinedFileTypesException(message, ex);
507 static class UserDefinedFileTypesException
extends Exception {
509 UserDefinedFileTypesException(String message) {
513 UserDefinedFileTypesException(String message, Throwable throwable) {
514 super(message, throwable);
static void addSignatureElement(FileType fileType, Element fileTypeElem, Document doc)
static void addAlertAttribute(FileType fileType, Element fileTypeElem)
static void writeFileTypes(Collection< FileType > fileTypes, String filePath)
static String parseMimeType(Element fileTypeElem)
static Element createFileTypeElement(FileType fileType, Document doc)
static Document createDocument()
static void addMimeTypeElement(FileType fileType, Element fileTypeElem, Document doc)
static String parseInterestingFilesSet(Element fileTypeElem)
static Signature parseSignature(Element fileTypeElem)
static String getChildElementTextContent(Element elem, String tagName)
static void addInterestingFilesSetElement(FileType fileType, Element fileTypeElem, Document doc)
static boolean parseAlert(Element fileTypeElem)
static< T > Document loadDocument(String docPath, Class< T > clazz, String schemaResourceName)
static void saveDocument(final Document doc, String encoding, String docPath)
static FileType parseFileType(Element fileTypeElem)
static List< FileType > readFileTypes(String filePath)