Conflicts:
	Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java
	HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbXML.java
This commit is contained in:
adam-m 2012-10-10 15:39:30 -04:00
commit 92fa58bd2c
17 changed files with 680 additions and 407 deletions

View File

@ -57,6 +57,7 @@ public class Case {
private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed
private static final String appName = Version.getName() + " " + autopsyVer; private static final String appName = Version.getName() + " " + autopsyVer;
private static final String XSDFILE = "CaseSchema.xsd";
/** /**
* Property name that indicates the name of the current case has changed. * Property name that indicates the name of the current case has changed.
* Fired with the case is renamed, and when the current case is * Fired with the case is renamed, and when the current case is
@ -195,7 +196,7 @@ public class Case {
XMLCaseManagement xmlcm = new XMLCaseManagement(); XMLCaseManagement xmlcm = new XMLCaseManagement();
xmlcm.create(caseDir, caseName, examiner, caseNumber); // create a new XML config file xmlcm.create(caseDir, caseName, examiner, caseNumber); // create a new XML config file
xmlcm.writeFile(); xmlcm.writeFile();
String dbPath = caseDir + File.separator + "autopsy.db"; String dbPath = caseDir + File.separator + "autopsy.db";
SleuthkitCase db = SleuthkitCase.newCase(dbPath); SleuthkitCase db = SleuthkitCase.newCase(dbPath);

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:element name="Name" type="xs:string"/>
<xs:element name="Number" type="xs:integer" nillable="true"/>
<xs:element name="Examiner" type="xs:string" nillable="true"/>
<xs:attribute name="Relative" type="xs:boolean"/>
<xs:element name="CreatedDate" >
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="([0-9]{4}/)+([0-1][0-9]/)+([0-3][0-9] )+([0-2][0-9]:[0-5][0-9]:[0-9][0-9] )+(\([A-Z][A-Z][A-Z]\))"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ModifiedDate">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="([0-9]{4}/)+([0-1][0-9]/)+([0-3][0-9] )+([0-2][0-9]:[0-5][0-9]:[0-9][0-9] )+(\([A-Z][A-Z][A-Z]\))"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="AutopsyCreatedVersion" type="xs:integer"/>
<xs:element name="AutopsySavedVersion" type="xs:integer"/>
<xs:element name="SchemaVersion" type="xs:decimal"/>
<!-- definition of complex elements -->
<xs:element name="ExportFolder">
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="LogFolder" >
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="TempFolder">
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="CacheFolder" >
<xs:complexType mixed="true">
<xs:attribute ref="Relative" default="true" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="Case">
<xs:complexType>
<xs:sequence>
<xs:element ref="Name"/>
<xs:element ref="Number"/>
<xs:element ref="Examiner"/>
<xs:element ref="ExportFolder"/>
<xs:element ref="LogFolder"/>
<xs:element ref="TempFolder"/>
<xs:element ref="CacheFolder"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="AutopsyCase">
<xs:complexType>
<xs:sequence>
<xs:element ref="CreatedDate" />
<xs:element ref="ModifiedDate" />
<xs:element ref="AutopsyCreatedVersion"/>
<xs:element ref="AutopsySavedVersion"/>
<xs:element ref="SchemaVersion"/>
<xs:element ref="Case"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -23,16 +23,15 @@ import java.io.*;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.TimeZone;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.xml.parsers.*; import javax.xml.parsers.*;
import javax.xml.transform.*; import javax.xml.transform.*;
import javax.xml.transform.dom.*; import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*; import javax.xml.transform.stream.*;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.w3c.dom.*; import org.w3c.dom.*;
/** /**
@ -46,6 +45,7 @@ import org.w3c.dom.*;
* @author jantonius * @author jantonius
*/ */
public class XMLCaseManagement implements CaseConfigFileInterface{ public class XMLCaseManagement implements CaseConfigFileInterface{
final static String XSDFILE = "CaseSchema.xsd";
final static String TOP_ROOT_NAME = "AutopsyCase"; final static String TOP_ROOT_NAME = "AutopsyCase";
final static String CASE_ROOT_NAME = "Case"; final static String CASE_ROOT_NAME = "Case";
@ -617,7 +617,12 @@ public class XMLCaseManagement implements CaseConfigFileInterface{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder(); DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(file); doc = db.parse(file);
doc.getDocumentElement().normalize();
doc.getDocumentElement().normalize(); doc.getDocumentElement().normalize();
if(!XMLUtil.xmlIsValid(doc, XMLCaseManagement.class, XSDFILE)){
Logger.getLogger(XMLCaseManagement.class.getName()).log(Level.WARNING, "Could not validate against [" + XSDFILE + "], results may not accurate");
}
Element rootEl = doc.getDocumentElement(); Element rootEl = doc.getDocumentElement();
String rootName = rootEl.getNodeName(); String rootName = rootEl.getNodeName();

View File

@ -21,16 +21,15 @@ package org.sleuthkit.autopsy.coreutils;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.logging.Level;
import org.openide.modules.InstalledFileLocator; import org.openide.modules.InstalledFileLocator;
import org.openide.modules.Places; import org.openide.modules.Places;
/** /**
* *
* Platform utilities * Platform utilities
@ -42,6 +41,10 @@ public class PlatformUtil {
public static final String OS_VERSION_UNKNOWN = "unknown"; public static final String OS_VERSION_UNKNOWN = "unknown";
public static final String OS_ARCH_UNKNOWN = "unknown"; public static final String OS_ARCH_UNKNOWN = "unknown";
/** /**
* Get root path where the application is installed * Get root path where the application is installed
* *

View File

@ -0,0 +1,183 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.coreutils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
/** XML Utilities
*
* This class provides basic utilities for working with XML files, such as
* -Validating XML files against a given schema
* -Saving documents to disk
* -Loading documents from disk
*
*/
public class XMLUtil {
/** Utility to validate XML files against pre-defined schema files.
*
* The schema files are extracted automatically when this function is called, the XML being validated is not.
* Be sure the XML file is already extracted otherwise it will return false.
* @param xmlfile The XML file to validate, in DOMSource format
* @param type The file name of the schema to validate against, must exist as a resource in the same package as where this function is being called.
*
* For example usages, please see KeywordSearchListsXML, HashDbXML, or IngestModuleLoader.
*
*/
public static boolean xmlIsValid(DOMSource xmlfile, Class clazz, String schemaFile) {
try{
PlatformUtil.extractResourceToUserConfigDir(clazz, schemaFile);
File schemaLoc = new File(PlatformUtil.getUserConfigDirectory() + File.separator + schemaFile);
SchemaFactory schm = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try{
Schema schema = schm.newSchema(schemaLoc);
Validator validator = schema.newValidator();
DOMResult result = new DOMResult();
validator.validate(xmlfile, result);
return true;
}
catch(SAXException e){
Logger.getLogger(clazz.getName()).log(Level.WARNING, "Unable to validate XML file.", e);
return false;
}
}
catch(IOException e){
Logger.getLogger(clazz.getName()).log(Level.WARNING, "Unable to load XML file [" + xmlfile.toString() + "] of type ["+schemaFile+"]", e);
return false;
}
}
/** Evaluates XML files against an XSD.
*
* The schema files are extracted automatically when this function is called, the XML being validated is not.
* Be sure the XML file is already extracted otherwise it will return false.
* @param xmlfile The XML file to validate
* @param type The file name of the schema to validate against, must exist as a resource in the same package as where this function is being called
*
* For example usages, please see KeywordSearchListsXML, HashDbXML, or IngestModuleLoader.
*
*/
public static boolean xmlIsValid(Document doc, Class clazz, String type){
DOMSource dms = new DOMSource(doc);
return xmlIsValid(dms, clazz, type);
}
/** Loads XML files from disk
*
* @param clazz the class this method is invoked from
* @param xmlPath the full path to the file to load
* @param xsdPath the full path to the file to validate against
*
*/
public static Document loadDoc(Class clazz, String xmlPath, String xsdPath) {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
Document ret = null;
try {
DocumentBuilder builder = builderFactory.newDocumentBuilder();
ret = builder.parse(
new FileInputStream(xmlPath));
} catch (ParserConfigurationException e) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error loading XML file: can't initialize parser.", e);
} catch (SAXException e) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error loading XML file: can't parse XML.", e);
} catch (IOException e) {
//error reading file
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error loading XML file: can't read file.", e);
}
if (!XMLUtil.xmlIsValid(ret, clazz, xsdPath)) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error loading XML file: could not validate against [" + xsdPath + "], results may not be accurate");
}
return ret;
}
/** Saves XML files to disk
*
* @param clazz the class this method is invoked from
* @param xmlPath the full path to save the XML to
* @param encoding to encoding, such as "UTF-8", to encode the file with
* @param doc the document to save
*
*/
public static boolean saveDoc(Class clazz, String xmlPath, String encoding, final Document doc) {
TransformerFactory xf = TransformerFactory.newInstance();
xf.setAttribute("indent-number", new Integer(1));
boolean success = false;
try {
Transformer xformer = xf.newTransformer();
xformer.setOutputProperty(OutputKeys.METHOD, "xml");
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
xformer.setOutputProperty(OutputKeys.ENCODING, encoding);
xformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
File file = new File(xmlPath);
FileOutputStream stream = new FileOutputStream(file);
Result out = new StreamResult(new OutputStreamWriter(stream, encoding));
xformer.transform(new DOMSource(doc), out);
stream.flush();
stream.close();
success = true;
} catch (UnsupportedEncodingException e) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Should not happen", e);
} catch (TransformerConfigurationException e) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file", e);
} catch (TransformerException e) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file", e);
} catch (FileNotFoundException e) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file: cannot write to file: " + xmlPath, e);
} catch (IOException e) {
Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file: cannot write to file: " + xmlPath, e);
}
return success;
}
}

View File

@ -21,12 +21,8 @@ package org.sleuthkit.autopsy.ingest;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -51,15 +47,6 @@ import java.util.logging.Level;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.openide.filesystems.FileSystem;
import org.openide.modules.ModuleInfo; import org.openide.modules.ModuleInfo;
import org.openide.util.Exceptions; import org.openide.util.Exceptions;
import org.openide.util.Lookup; import org.openide.util.Lookup;
@ -71,14 +58,13 @@ import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ConfigurationBuilder; import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder; import org.reflections.util.FilterBuilder;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.w3c.dom.Comment; import org.w3c.dom.Comment;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.openide.filesystems.Repository;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
/** /**
* Class responsible for discovery and loading ingest modules specified in * Class responsible for discovery and loading ingest modules specified in
@ -107,10 +93,11 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings;
public final class IngestModuleLoader { public final class IngestModuleLoader {
private static final String PIPELINE_CONFIG_XML = "pipeline_config.xml"; private static final String PIPELINE_CONFIG_XML = "pipeline_config.xml";
private static final String XSDFILE = "PipelineConfigSchema.xsd";
private String absFilePath; private String absFilePath;
private static IngestModuleLoader instance; private static IngestModuleLoader instance;
//raw XML pipeline representation for validation //raw XML pipeline representation for validation
private final List<XmlPipelineRaw> pipelinesXML; private final List<IngestModuleLoader.XmlPipelineRaw> pipelinesXML;
//validated pipelines with instantiated modules //validated pipelines with instantiated modules
private final List<IngestModuleAbstractFile> filePipeline; private final List<IngestModuleAbstractFile> filePipeline;
private final List<IngestModuleImage> imagePipeline; private final List<IngestModuleImage> imagePipeline;
@ -132,7 +119,7 @@ public final class IngestModuleLoader {
}; };
private IngestModuleLoader() { private IngestModuleLoader() {
pipelinesXML = new ArrayList<XmlPipelineRaw>(); pipelinesXML = new ArrayList<IngestModuleLoader.XmlPipelineRaw>();
filePipeline = new ArrayList<IngestModuleAbstractFile>(); filePipeline = new ArrayList<IngestModuleAbstractFile>();
imagePipeline = new ArrayList<IngestModuleImage>(); imagePipeline = new ArrayList<IngestModuleImage>();
dateFormatter = new SimpleDateFormat(DATE_FORMAT); dateFormatter = new SimpleDateFormat(DATE_FORMAT);
@ -193,16 +180,16 @@ public final class IngestModuleLoader {
* @throws IngestModuleLoaderException * @throws IngestModuleLoaderException
*/ */
private void validate() throws IngestModuleLoaderException { private void validate() throws IngestModuleLoaderException {
for (XmlPipelineRaw pRaw : pipelinesXML) { for (IngestModuleLoader.XmlPipelineRaw pRaw : pipelinesXML) {
boolean pipelineErrors = false; boolean pipelineErrors = false;
//check pipelineType //check pipelineType
String pipelineType = pRaw.type; String pipelineType = pRaw.type;
XmlPipelineRaw.PIPELINE_TYPE pType = null; IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE pType = null;
try { try {
pType = XmlPipelineRaw.getPipelineType(pipelineType); pType = IngestModuleLoader.XmlPipelineRaw.getPipelineType(pipelineType);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
pipelineErrors = true; pipelineErrors = true;
logger.log(Level.SEVERE, "Unknown pipeline type: " + pipelineType); logger.log(Level.SEVERE, "Unknown pipeline type: " + pipelineType);
@ -211,7 +198,7 @@ public final class IngestModuleLoader {
//ordering store //ordering store
Map<Integer, Integer> orderings = new HashMap<Integer, Integer>(); Map<Integer, Integer> orderings = new HashMap<Integer, Integer>();
for (XmlModuleRaw pMod : pRaw.modules) { for (IngestModuleLoader.XmlModuleRaw pMod : pRaw.modules) {
boolean moduleErrors = false; boolean moduleErrors = false;
//record ordering for validation //record ordering for validation
@ -224,7 +211,7 @@ public final class IngestModuleLoader {
//check pipelineType //check pipelineType
String modType = pMod.type; String modType = pMod.type;
if (!modType.equals(XmlModuleRaw.MODULE_TYPE.PLUGIN.toString())) { if (!modType.equals(IngestModuleLoader.XmlModuleRaw.MODULE_TYPE.PLUGIN.toString())) {
moduleErrors = true; moduleErrors = true;
logger.log(Level.SEVERE, "Unknown module type: " + modType); logger.log(Level.SEVERE, "Unknown module type: " + modType);
} }
@ -267,7 +254,7 @@ public final class IngestModuleLoader {
} }
//if file module: check if has public static getDefault() //if file module: check if has public static getDefault()
if (pType == XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS) { if (pType == IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS) {
try { try {
Method getDefaultMethod = moduleClass.getMethod("getDefault"); Method getDefaultMethod = moduleClass.getMethod("getDefault");
int modifiers = getDefaultMethod.getModifiers(); int modifiers = getDefaultMethod.getModifiers();
@ -285,7 +272,7 @@ public final class IngestModuleLoader {
Exceptions.printStackTrace(ex); Exceptions.printStackTrace(ex);
} }
} //if image module: check if has public constructor with no args } //if image module: check if has public constructor with no args
else if (pType == XmlPipelineRaw.PIPELINE_TYPE.IMAGE_ANALYSIS) { else if (pType == IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.IMAGE_ANALYSIS) {
try { try {
Constructor<?> constr = moduleClass.getConstructor(); Constructor<?> constr = moduleClass.getConstructor();
int modifiers = constr.getModifiers(); int modifiers = constr.getModifiers();
@ -519,12 +506,12 @@ public final class IngestModuleLoader {
boolean exists = false; boolean exists = false;
Class<IngestModuleAbstractFile> foundClass = (Class<IngestModuleAbstractFile>) it.next(); Class<IngestModuleAbstractFile> foundClass = (Class<IngestModuleAbstractFile>) it.next();
for (XmlPipelineRaw rawP : pipelinesXML) { for (IngestModuleLoader.XmlPipelineRaw rawP : pipelinesXML) {
if (!rawP.type.equals(XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS.toString())) { if (!rawP.type.equals(IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS.toString())) {
continue; //skip continue; //skip
} }
for (XmlModuleRaw rawM : rawP.modules) { for (IngestModuleLoader.XmlModuleRaw rawM : rawP.modules) {
//logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName()); //logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName());
if (foundClass.getName().equals(rawM.location)) { if (foundClass.getName().equals(rawM.location)) {
exists = true; exists = true;
@ -539,7 +526,7 @@ public final class IngestModuleLoader {
if (exists == false) { if (exists == false) {
logger.log(Level.INFO, "Discovered a new file module to load: " + foundClass.getName()); logger.log(Level.INFO, "Discovered a new file module to load: " + foundClass.getName());
//ADD MODULE //ADD MODULE
addModuleToRawPipeline(foundClass, XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS); addModuleToRawPipeline(foundClass, IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS);
modulesChanged = true; modulesChanged = true;
} }
@ -550,13 +537,13 @@ public final class IngestModuleLoader {
boolean exists = false; boolean exists = false;
Class<IngestModuleImage> foundClass = (Class<IngestModuleImage>) it.next(); Class<IngestModuleImage> foundClass = (Class<IngestModuleImage>) it.next();
for (XmlPipelineRaw rawP : pipelinesXML) { for (IngestModuleLoader.XmlPipelineRaw rawP : pipelinesXML) {
if (!rawP.type.equals(XmlPipelineRaw.PIPELINE_TYPE.IMAGE_ANALYSIS.toString())) { if (!rawP.type.equals(IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.IMAGE_ANALYSIS.toString())) {
continue; //skip continue; //skip
} }
for (XmlModuleRaw rawM : rawP.modules) { for (IngestModuleLoader.XmlModuleRaw rawM : rawP.modules) {
//logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName()); //logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName());
if (foundClass.getName().equals(rawM.location)) { if (foundClass.getName().equals(rawM.location)) {
exists = true; exists = true;
@ -571,7 +558,7 @@ public final class IngestModuleLoader {
if (exists == false) { if (exists == false) {
logger.log(Level.INFO, "Discovered a new image module to load: " + foundClass.getName()); logger.log(Level.INFO, "Discovered a new image module to load: " + foundClass.getName());
//ADD MODULE //ADD MODULE
addModuleToRawPipeline(foundClass, XmlPipelineRaw.PIPELINE_TYPE.IMAGE_ANALYSIS); addModuleToRawPipeline(foundClass, IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.IMAGE_ANALYSIS);
modulesChanged = true; modulesChanged = true;
} }
@ -579,7 +566,7 @@ public final class IngestModuleLoader {
if (modulesChanged) { if (modulesChanged) {
save(); save();
pcs.firePropertyChange(Event.ModulesReloaded.toString(), 0, 1); pcs.firePropertyChange(IngestModuleLoader.Event.ModulesReloaded.toString(), 0, 1);
} }
/* /*
@ -604,7 +591,7 @@ public final class IngestModuleLoader {
* class path * class path
* @param newOrder new order to set * @param newOrder new order to set
*/ */
void setModuleOrder(XmlPipelineRaw.PIPELINE_TYPE pipeLineType, String moduleLocation, int newOrder) throws IngestModuleLoaderException { void setModuleOrder(IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE pipeLineType, String moduleLocation, int newOrder) throws IngestModuleLoaderException {
throw new IngestModuleLoaderException("Not yet implemented"); throw new IngestModuleLoaderException("Not yet implemented");
} }
@ -615,22 +602,22 @@ public final class IngestModuleLoader {
* @param moduleClass * @param moduleClass
* @param pipelineType * @param pipelineType
*/ */
private void addModuleToRawPipeline(Class<?> moduleClass, XmlPipelineRaw.PIPELINE_TYPE pipelineType) throws IngestModuleLoaderException { private void addModuleToRawPipeline(Class<?> moduleClass, IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE pipelineType) throws IngestModuleLoaderException {
String moduleLocation = moduleClass.getName(); String moduleLocation = moduleClass.getName();
XmlModuleRaw modRaw = new XmlModuleRaw(); IngestModuleLoader.XmlModuleRaw modRaw = new IngestModuleLoader.XmlModuleRaw();
modRaw.arguments = ""; //default, no arguments modRaw.arguments = ""; //default, no arguments
modRaw.location = moduleLocation; modRaw.location = moduleLocation;
modRaw.order = Integer.MAX_VALUE - (numModDiscovered++); //add to end modRaw.order = Integer.MAX_VALUE - (numModDiscovered++); //add to end
modRaw.type = XmlModuleRaw.MODULE_TYPE.PLUGIN.toString(); modRaw.type = IngestModuleLoader.XmlModuleRaw.MODULE_TYPE.PLUGIN.toString();
modRaw.valid = false; //to be validated modRaw.valid = false; //to be validated
//save the current numModDiscovered //save the current numModDiscovered
ModuleSettings.setConfigSetting(IngestManager.MODULE_PROPERTIES, CUR_MODULES_DISCOVERED_SETTING, Integer.toString(numModDiscovered)); ModuleSettings.setConfigSetting(IngestManager.MODULE_PROPERTIES, CUR_MODULES_DISCOVERED_SETTING, Integer.toString(numModDiscovered));
//find the pipeline of that type //find the pipeline of that type
XmlPipelineRaw pipeline = null; IngestModuleLoader.XmlPipelineRaw pipeline = null;
for (XmlPipelineRaw rawP : this.pipelinesXML) { for (IngestModuleLoader.XmlPipelineRaw rawP : this.pipelinesXML) {
if (rawP.type.equals(pipelineType.toString())) { if (rawP.type.equals(pipelineType.toString())) {
pipeline = rawP; pipeline = rawP;
break; break;
@ -681,27 +668,27 @@ public final class IngestModuleLoader {
Comment comment = doc.createComment("Saved by: " + getClass().getName() Comment comment = doc.createComment("Saved by: " + getClass().getName()
+ " on: " + dateFormatter.format(System.currentTimeMillis())); + " on: " + dateFormatter.format(System.currentTimeMillis()));
doc.appendChild(comment); doc.appendChild(comment);
Element rootEl = doc.createElement(XmlPipelineRaw.XML_PIPELINE_ROOT); Element rootEl = doc.createElement(IngestModuleLoader.XmlPipelineRaw.XML_PIPELINE_ROOT);
doc.appendChild(rootEl); doc.appendChild(rootEl);
for (XmlPipelineRaw rawP : this.pipelinesXML) { for (IngestModuleLoader.XmlPipelineRaw rawP : this.pipelinesXML) {
Element pipelineEl = doc.createElement(XmlPipelineRaw.XML_PIPELINE_EL); Element pipelineEl = doc.createElement(IngestModuleLoader.XmlPipelineRaw.XML_PIPELINE_EL);
pipelineEl.setAttribute(XmlPipelineRaw.XML_PIPELINE_TYPE_ATTR, rawP.type); pipelineEl.setAttribute(IngestModuleLoader.XmlPipelineRaw.XML_PIPELINE_TYPE_ATTR, rawP.type);
rootEl.appendChild(pipelineEl); rootEl.appendChild(pipelineEl);
for (XmlModuleRaw rawM : rawP.modules) { for (IngestModuleLoader.XmlModuleRaw rawM : rawP.modules) {
Element moduleEl = doc.createElement(XmlModuleRaw.XML_MODULE_EL); Element moduleEl = doc.createElement(IngestModuleLoader.XmlModuleRaw.XML_MODULE_EL);
moduleEl.setAttribute(XmlModuleRaw.XML_MODULE_LOC_ATTR, rawM.location); moduleEl.setAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_LOC_ATTR, rawM.location);
moduleEl.setAttribute(XmlModuleRaw.XML_MODULE_TYPE_ATTR, rawM.type); moduleEl.setAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_TYPE_ATTR, rawM.type);
moduleEl.setAttribute(XmlModuleRaw.XML_MODULE_ORDER_ATTR, Integer.toString(rawM.order)); moduleEl.setAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_ORDER_ATTR, Integer.toString(rawM.order));
moduleEl.setAttribute(XmlModuleRaw.XML_MODULE_TYPE_ATTR, rawM.type); moduleEl.setAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_TYPE_ATTR, rawM.type);
pipelineEl.appendChild(moduleEl); pipelineEl.appendChild(moduleEl);
} }
} }
saveDoc(doc); XMLUtil.saveDoc(IngestModuleLoader.class, absFilePath, ENCODING, doc);
logger.log(Level.INFO, "Pipeline configuration saved to: " + this.absFilePath); logger.log(Level.INFO, "Pipeline configuration saved to: " + this.absFilePath);
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
logger.log(Level.SEVERE, "Error saving pipeline config XML: can't initialize parser.", e); logger.log(Level.SEVERE, "Error saving pipeline config XML: can't initialize parser.", e);
@ -709,39 +696,6 @@ public final class IngestModuleLoader {
} }
private boolean saveDoc(final Document doc) {
TransformerFactory xf = TransformerFactory.newInstance();
xf.setAttribute("indent-number", new Integer(1));
boolean success = false;
try {
Transformer xformer = xf.newTransformer();
xformer.setOutputProperty(OutputKeys.METHOD, "xml");
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
xformer.setOutputProperty(OutputKeys.ENCODING, ENCODING);
xformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
File file = new File(this.absFilePath);
FileOutputStream stream = new FileOutputStream(file);
Result out = new StreamResult(new OutputStreamWriter(stream, ENCODING));
xformer.transform(new DOMSource(doc), out);
stream.flush();
stream.close();
success = true;
} catch (UnsupportedEncodingException e) {
logger.log(Level.SEVERE, "Should not happen", e);
} catch (TransformerConfigurationException e) {
logger.log(Level.SEVERE, "Error writing pipeline config XML", e);
} catch (TransformerException e) {
logger.log(Level.SEVERE, "Error writing pipeline config XML", e);
} catch (FileNotFoundException e) {
logger.log(Level.SEVERE, "Error writing pipeline config XML: cannot write to file: " + this.absFilePath, e);
} catch (IOException e) {
logger.log(Level.SEVERE, "Error writing pipeline config XML: cannot write to file: " + this.absFilePath, e);
}
return success;
}
/** /**
* Instantiate valid pipeline and modules and store the module object * Instantiate valid pipeline and modules and store the module object
* references * references
@ -762,24 +716,24 @@ public final class IngestModuleLoader {
validate(); validate();
for (XmlPipelineRaw pRaw : pipelinesXML) { for (IngestModuleLoader.XmlPipelineRaw pRaw : pipelinesXML) {
if (pRaw.valid == false) { if (pRaw.valid == false) {
//skip invalid pipelines //skip invalid pipelines
continue; continue;
} }
//sort modules by order parameter, in case XML order is different //sort modules by order parameter, in case XML order is different
Collections.sort(pRaw.modules, new Comparator<XmlModuleRaw>() { Collections.sort(pRaw.modules, new Comparator<IngestModuleLoader.XmlModuleRaw>() {
@Override @Override
public int compare(XmlModuleRaw o1, XmlModuleRaw o2) { public int compare(IngestModuleLoader.XmlModuleRaw o1, IngestModuleLoader.XmlModuleRaw o2) {
return Integer.valueOf(o1.order).compareTo(Integer.valueOf(o2.order)); return Integer.valueOf(o1.order).compareTo(Integer.valueOf(o2.order));
} }
}); });
//check pipelineType, add to right pipeline collection //check pipelineType, add to right pipeline collection
XmlPipelineRaw.PIPELINE_TYPE pType = XmlPipelineRaw.getPipelineType(pRaw.type); IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE pType = IngestModuleLoader.XmlPipelineRaw.getPipelineType(pRaw.type);
for (XmlModuleRaw pMod : pRaw.modules) { for (IngestModuleLoader.XmlModuleRaw pMod : pRaw.modules) {
try { try {
if (pMod.valid == false) { if (pMod.valid == false) {
//skip invalid modules //skip invalid modules
@ -906,31 +860,6 @@ public final class IngestModuleLoader {
} }
private Document loadDoc() {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
Document ret = null;
try {
DocumentBuilder builder = builderFactory.newDocumentBuilder();
ret = builder.parse(
new FileInputStream(absFilePath));
} catch (ParserConfigurationException e) {
logger.log(Level.SEVERE, "Error loading pipeline configuration: can't initialize parser.", e);
} catch (SAXException e) {
logger.log(Level.SEVERE, "Error loading pipeline configuration: can't parse XML.", e);
} catch (IOException e) {
//error reading file
logger.log(Level.SEVERE, "Error loading pipeline configuration: can't read file.", e);
}
return ret;
}
/** /**
* Load XML into raw pipeline representation * Load XML into raw pipeline representation
@ -938,7 +867,7 @@ public final class IngestModuleLoader {
* @throws IngestModuleLoaderException * @throws IngestModuleLoaderException
*/ */
private void loadRawPipeline() throws IngestModuleLoaderException { private void loadRawPipeline() throws IngestModuleLoaderException {
final Document doc = loadDoc(); final Document doc = XMLUtil.loadDoc(IngestModuleLoader.class, absFilePath, XSDFILE);
if (doc == null) { if (doc == null) {
throw new IngestModuleLoaderException("Could not load pipeline config XML: " + this.absFilePath); throw new IngestModuleLoaderException("Could not load pipeline config XML: " + this.absFilePath);
} }
@ -948,7 +877,7 @@ public final class IngestModuleLoader {
logger.log(Level.SEVERE, msg); logger.log(Level.SEVERE, msg);
throw new IngestModuleLoaderException(msg); throw new IngestModuleLoaderException(msg);
} }
NodeList pipelineNodes = root.getElementsByTagName(XmlPipelineRaw.XML_PIPELINE_EL); NodeList pipelineNodes = root.getElementsByTagName(IngestModuleLoader.XmlPipelineRaw.XML_PIPELINE_EL);
int numPipelines = pipelineNodes.getLength(); int numPipelines = pipelineNodes.getLength();
if (numPipelines == 0) { if (numPipelines == 0) {
throw new IngestModuleLoaderException("No pipelines found in the pipeline configuration: " + absFilePath); throw new IngestModuleLoaderException("No pipelines found in the pipeline configuration: " + absFilePath);
@ -956,15 +885,15 @@ public final class IngestModuleLoader {
for (int pipelineNum = 0; pipelineNum < numPipelines; ++pipelineNum) { for (int pipelineNum = 0; pipelineNum < numPipelines; ++pipelineNum) {
//process pipelines //process pipelines
Element pipelineEl = (Element) pipelineNodes.item(pipelineNum); Element pipelineEl = (Element) pipelineNodes.item(pipelineNum);
final String pipelineType = pipelineEl.getAttribute(XmlPipelineRaw.XML_PIPELINE_TYPE_ATTR); final String pipelineType = pipelineEl.getAttribute(IngestModuleLoader.XmlPipelineRaw.XML_PIPELINE_TYPE_ATTR);
logger.log(Level.INFO, "Found pipeline type: " + pipelineType); logger.log(Level.INFO, "Found pipeline type: " + pipelineType);
XmlPipelineRaw pipelineRaw = new XmlPipelineRaw(); IngestModuleLoader.XmlPipelineRaw pipelineRaw = new IngestModuleLoader.XmlPipelineRaw();
pipelineRaw.type = pipelineType; pipelineRaw.type = pipelineType;
this.pipelinesXML.add(pipelineRaw); this.pipelinesXML.add(pipelineRaw);
//process modules //process modules
NodeList modulesNodes = pipelineEl.getElementsByTagName(XmlModuleRaw.XML_MODULE_EL); NodeList modulesNodes = pipelineEl.getElementsByTagName(IngestModuleLoader.XmlModuleRaw.XML_MODULE_EL);
int numModules = modulesNodes.getLength(); int numModules = modulesNodes.getLength();
if (numModules == 0) { if (numModules == 0) {
logger.log(Level.WARNING, "Pipeline: " + pipelineType + " has no modules defined."); logger.log(Level.WARNING, "Pipeline: " + pipelineType + " has no modules defined.");
@ -972,11 +901,11 @@ public final class IngestModuleLoader {
for (int moduleNum = 0; moduleNum < numModules; ++moduleNum) { for (int moduleNum = 0; moduleNum < numModules; ++moduleNum) {
//process modules //process modules
Element moduleEl = (Element) modulesNodes.item(moduleNum); Element moduleEl = (Element) modulesNodes.item(moduleNum);
final String moduleType = moduleEl.getAttribute(XmlModuleRaw.XML_MODULE_TYPE_ATTR); final String moduleType = moduleEl.getAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_TYPE_ATTR);
final String moduleOrder = moduleEl.getAttribute(XmlModuleRaw.XML_MODULE_ORDER_ATTR); final String moduleOrder = moduleEl.getAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_ORDER_ATTR);
final String moduleLoc = moduleEl.getAttribute(XmlModuleRaw.XML_MODULE_LOC_ATTR); final String moduleLoc = moduleEl.getAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_LOC_ATTR);
final String moduleArgs = moduleEl.getAttribute(XmlModuleRaw.XML_MODULE_ARGS_ATTR); final String moduleArgs = moduleEl.getAttribute(IngestModuleLoader.XmlModuleRaw.XML_MODULE_ARGS_ATTR);
XmlModuleRaw module = new XmlModuleRaw(); IngestModuleLoader.XmlModuleRaw module = new IngestModuleLoader.XmlModuleRaw();
module.arguments = moduleArgs; module.arguments = moduleArgs;
module.location = moduleLoc; module.location = moduleLoc;
try { try {
@ -1073,8 +1002,8 @@ public final class IngestModuleLoader {
* @param s string equals to one of the types toString() representation * @param s string equals to one of the types toString() representation
* @return matching type * @return matching type
*/ */
static PIPELINE_TYPE getPipelineType(String s) throws IllegalArgumentException { static IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE getPipelineType(String s) throws IllegalArgumentException {
PIPELINE_TYPE[] types = PIPELINE_TYPE.values(); IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE[] types = IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.values();
for (int i = 0; i < types.length; ++i) { for (int i = 0; i < types.length; ++i) {
if (types[i].toString().equals(s)) { if (types[i].toString().equals(s)) {
return types[i]; return types[i];
@ -1086,7 +1015,7 @@ public final class IngestModuleLoader {
private static final String XML_PIPELINE_EL = "PIPELINE"; private static final String XML_PIPELINE_EL = "PIPELINE";
private static final String XML_PIPELINE_TYPE_ATTR = "type"; private static final String XML_PIPELINE_TYPE_ATTR = "type";
String type; String type;
List<XmlModuleRaw> modules = new ArrayList<XmlModuleRaw>(); List<IngestModuleLoader.XmlModuleRaw> modules = new ArrayList<IngestModuleLoader.XmlModuleRaw>();
boolean valid = false; // if passed validation boolean valid = false; // if passed validation
} }

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:attribute name="order" type="xs:positiveInteger"/>
<xs:attribute name="type" type="xs:string"/>
<xs:attribute name="arguments" type="xs:string"/>
<xs:attribute name="location" type="xs:string"/>
<!-- definition of complex elements -->
<xs:element name="MODULE">
<xs:complexType>
<xs:attribute ref="location" use="required"/>
<xs:attribute ref="order" use="required"/>
<xs:attribute ref="type" use="required"/>
<xs:attribute ref="arguments" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="PIPELINE">
<xs:complexType>
<xs:sequence>
<xs:element ref="MODULE" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="PIPELINE_CONFIG">
<xs:complexType>
<xs:sequence>
<xs:element ref="PIPELINE" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -20,12 +20,9 @@
*/ */
package org.sleuthkit.autopsy.report; package org.sleuthkit.autopsy.report;
import java.io.FileOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -33,12 +30,14 @@ import java.util.Map.Entry;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringEscapeUtils;
import org.jdom.Comment; import org.w3c.dom.Element;
import org.jdom.Document; import org.w3c.dom.Document;
import org.jdom.Element; import org.w3c.dom.Comment;
import org.jdom.output.XMLOutputter;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.*; import org.sleuthkit.datamodel.*;
@ -47,7 +46,7 @@ import org.sleuthkit.datamodel.*;
*/ */
public class ReportXML implements ReportModule { public class ReportXML implements ReportModule {
public static Document xmldoc = new Document(); public static Document xmldoc;
private ReportConfiguration reportconfig; private ReportConfiguration reportconfig;
private String xmlPath; private String xmlPath;
private static ReportXML instance = null; private static ReportXML instance = null;
@ -75,41 +74,61 @@ public class ReportXML implements ReportModule {
Integer filesystemcount = currentCase.getRootObjectsCount(); Integer filesystemcount = currentCase.getRootObjectsCount();
Integer totalfiles = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG); Integer totalfiles = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG);
Integer totaldirs = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR); Integer totaldirs = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR);
Element root = new Element("Case"); DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
xmldoc = new Document(root); Document ret = builder.newDocument();
Element root = ret.createElement("Case");
DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
Date date = new Date(); Date date = new Date();
String datetime = datetimeFormat.format(date); String datetime = datetimeFormat.format(date);
String datenotime = dateFormat.format(date); String datenotime = dateFormat.format(date);
Comment comment = new Comment("XML Report Generated by Autopsy 3 on " + datetime); Comment comment = ret.createComment("XML Report Generated by Autopsy 3 on " + datetime);
root.addContent(comment); root.appendChild(comment);
//Create summary node involving how many of each type //Create summary node involving how many of each type
Element summary = new Element("Summary"); Element summary = ret.createElement("Summary");
if (IngestManager.getDefault().isIngestRunning()) { if (IngestManager.getDefault().isIngestRunning()) {
summary.addContent(new Element("Warning").setText("Report was run before ingest services completed!")); Element warning = ret.createElement("Warning");
warning.setTextContent("Report was run before ingest services completed!");
summary.appendChild(warning);
} }
summary.addContent(new Element("Name").setText(caseName)); Element name = ret.createElement("Name");
summary.addContent(new Element("Total-Images").setText(imagecount.toString())); name.setTextContent(caseName);
summary.addContent(new Element("Total-FileSystems").setText(filesystemcount.toString())); summary.appendChild(name);
summary.addContent(new Element("Total-Files").setText(totalfiles.toString()));
summary.addContent(new Element("Total-Directories").setText(totaldirs.toString())); Element timages = ret.createElement("Total-Images");
root.addContent(summary); timages.setTextContent(imagecount.toString());
summary.appendChild(timages);
Element tfilesys = ret.createElement("Total-FileSystems");
tfilesys.setTextContent(filesystemcount.toString());
summary.appendChild(tfilesys);
Element tfiles = ret.createElement("Total-Files");
tfiles.setTextContent(totalfiles.toString());
summary.appendChild(tfiles);
Element tdir = ret.createElement("Total-Directories");
tdir.setTextContent(totaldirs.toString());
summary.appendChild(tdir);
root.appendChild(summary);
//generate the nodes for each of the types so we can use them later //generate the nodes for each of the types so we can use them later
Element nodeGen = new Element("General-Information");
Element nodeWebBookmark = new Element("Web-Bookmarks"); Element nodeGen = ret.createElement("General-Information");
Element nodeWebCookie = new Element("Web-Cookies"); Element nodeWebBookmark = ret.createElement("Web-Bookmarks");
Element nodeWebHistory = new Element("Web-History"); Element nodeWebCookie = ret.createElement("Web-Cookies");
Element nodeWebDownload = new Element("Web-Downloads"); Element nodeWebHistory = ret.createElement("Web-History");
Element nodeRecentObjects = new Element("Recent-Documents"); Element nodeWebDownload = ret.createElement("Web-Downloads");
Element nodeTrackPoint = new Element("Track-Points"); Element nodeRecentObjects =ret.createElement("Recent-Documents");
Element nodeInstalled = new Element("Installed-Programfiles"); Element nodeTrackPoint = ret.createElement("Track-Points");
Element nodeKeyword = new Element("Keyword-Search-Hits"); Element nodeInstalled = ret.createElement("Installed-Programfiles");
Element nodeHash = new Element("Hashset-Hits"); Element nodeKeyword = ret.createElement("Keyword-Search-Hits");
Element nodeDevice = new Element("Attached-Devices"); Element nodeHash = ret.createElement("Hashset-Hits");
Element nodeEmail = new Element("Email-Messages"); Element nodeDevice = ret.createElement("Attached-Devices");
Element nodeWebSearch = new Element("Web-Search-Queries"); Element nodeEmail = ret.createElement("Email-Messages");
Element nodeExif = new Element("Exif-Metadata"); Element nodeWebSearch = ret.createElement("Web-Search-Queries");
Element nodeExif = ret.createElement("Exif-Metadata");
//remove bytes //remove bytes
Pattern INVALID_XML_CHARS = Pattern.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]"); Pattern INVALID_XML_CHARS = Pattern.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]");
for (Entry<BlackboardArtifact, List<BlackboardAttribute>> entry : report.entrySet()) { for (Entry<BlackboardArtifact, List<BlackboardAttribute>> entry : report.entrySet()) {
@ -117,7 +136,7 @@ public class ReportXML implements ReportModule {
break; break;
} }
int cc = 0; int cc = 0;
Element artifact = new Element("Artifact"); Element artifact = ret.createElement("Artifact");
Long objId = entry.getKey().getObjectID(); Long objId = entry.getKey().getObjectID();
Content cont = skCase.getContentById(objId); Content cont = skCase.getContentById(objId);
Long filesize = cont.getSize(); Long filesize = cont.getSize();
@ -133,14 +152,17 @@ public class ReportXML implements ReportModule {
if (ReportFilter.cancel == true) { if (ReportFilter.cancel == true) {
break; break;
} }
Element attribute = new Element("Attribute").setAttribute("Type", tempatt.getAttributeTypeDisplayName()); Element attribute = ret.createElement("Attribute");
attribute.setAttribute("Type", tempatt.getAttributeTypeDisplayName());
String tempvalue = tempatt.getValueString(); String tempvalue = tempatt.getValueString();
//INVALID_XML_CHARS.matcher(tempvalue).replaceAll(""); //INVALID_XML_CHARS.matcher(tempvalue).replaceAll("");
Element value = new Element("Value").setText(StringEscapeUtils.escapeXml(tempvalue)); Element value = ret.createElement("Value");
attribute.addContent(value); value.setTextContent(StringEscapeUtils.escapeXml(tempvalue));
Element context = new Element("Context").setText(StringEscapeUtils.escapeXml(tempatt.getContext())); attribute.appendChild(value);
attribute.addContent(context); Element context = ret.createElement("Context");
artifact.addContent(attribute); context.setTextContent(StringEscapeUtils.escapeXml(tempatt.getContext()));
attribute.appendChild(context);
artifact.appendChild(attribute);
cc++; cc++;
} }
@ -148,71 +170,74 @@ public class ReportXML implements ReportModule {
//while (entry.getValue().iterator().hasNext()) //while (entry.getValue().iterator().hasNext())
// { // {
// } // }
nodeGen.addContent(artifact); nodeGen.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()) {
nodeWebBookmark.addContent(artifact); nodeWebBookmark.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()) {
nodeWebCookie.addContent(artifact); nodeWebCookie.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) {
nodeWebHistory.addContent(artifact); nodeWebHistory.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) {
nodeWebDownload.addContent(artifact); nodeWebDownload.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID()) {
nodeRecentObjects.addContent(artifact); nodeRecentObjects.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TRACKPOINT.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TRACKPOINT.getTypeID()) {
nodeTrackPoint.addContent(artifact); nodeTrackPoint.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) {
nodeInstalled.addContent(artifact); nodeInstalled.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
nodeKeyword.addContent(artifact); nodeKeyword.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
nodeHash.addContent(artifact); nodeHash.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) {
nodeDevice.addContent(artifact); nodeDevice.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) {
nodeEmail.addContent(artifact); nodeEmail.appendChild(artifact);
} }
if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) {
nodeWebSearch.addContent(artifact); nodeWebSearch.appendChild(artifact);
} }
if(entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()){ if(entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()){
nodeExif.addContent(artifact); nodeExif.appendChild(artifact);
} }
//end of master loop //end of master loop
} }
//add them in the order we want them to the document //add them in the order we want them to the document
root.addContent(nodeGen); root.appendChild(nodeGen);
root.addContent(nodeWebBookmark); root.appendChild(nodeWebBookmark);
root.addContent(nodeWebCookie); root.appendChild(nodeWebCookie);
root.addContent(nodeWebHistory); root.appendChild(nodeWebHistory);
root.addContent(nodeWebDownload); root.appendChild(nodeWebDownload);
root.addContent(nodeRecentObjects); root.appendChild(nodeRecentObjects);
root.addContent(nodeTrackPoint); root.appendChild(nodeTrackPoint);
root.addContent(nodeInstalled); root.appendChild(nodeInstalled);
root.addContent(nodeKeyword); root.appendChild(nodeKeyword);
root.addContent(nodeHash); root.appendChild(nodeHash);
root.addContent(nodeDevice); root.appendChild(nodeDevice);
root.addContent(nodeEmail); root.appendChild(nodeEmail);
root.addContent(nodeWebSearch); root.appendChild(nodeWebSearch);
root.addContent(nodeExif); root.appendChild(nodeExif);
ret.appendChild(root);
xmldoc = ret;
//Export it the first time //Export it the first time
xmlPath = currentCase.getCaseDirectory() + File.separator + "Reports" + File.separator + caseName + "-" + datenotime + ".xml"; xmlPath = currentCase.getCaseDirectory() + File.separator + "Reports" + File.separator + caseName + "-" + datenotime + ".xml";
@ -227,18 +252,7 @@ public class ReportXML implements ReportModule {
@Override @Override
public void save(String path) { public void save(String path) {
XMLUtil.saveDoc(ReportXML.class, xmlPath, "UTF-8", xmldoc);
try {
FileOutputStream out = new FileOutputStream(path);
XMLOutputter serializer = new XMLOutputter();
serializer.output(xmldoc, out);
out.flush();
out.close();
} catch (IOException e) {
System.err.println(e);
}
} }
@Override @Override

View File

@ -21,8 +21,6 @@
<dependency conf="autopsy_core->*" org="commons-logging" name="commons-logging" rev="1.1.1"/> <dependency conf="autopsy_core->*" org="commons-logging" name="commons-logging" rev="1.1.1"/>
<dependency conf="autopsy_core->*" org="log4j" name="log4j" rev="1.2.17"/> <dependency conf="autopsy_core->*" org="log4j" name="log4j" rev="1.2.17"/>
<!-- reporting -->
<dependency conf="autopsy_core->*" org="dom4j" name="dom4j" rev="1.6.1"/>
<!-- <dependency conf="autopsy_core->*" org="org.jdom" name="jdom" rev="1.1.3"/> --> <!-- <dependency conf="autopsy_core->*" org="org.jdom" name="jdom" rev="1.1.3"/> -->
<dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-excelant" rev="3.8"/> <dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-excelant" rev="3.8"/>
<dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-scratchpad" rev="3.8"/> <dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-scratchpad" rev="3.8"/>

View File

@ -19,38 +19,25 @@
package org.sleuthkit.autopsy.hashdatabase; package org.sleuthkit.autopsy.hashdatabase;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
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.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.hashdatabase.HashDb.DBType; import org.sleuthkit.autopsy.hashdatabase.HashDb.DBType;
import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.SleuthkitJNI;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class HashDbXML { public class HashDbXML {
private static final String ROOT_EL = "hash_sets"; private static final String ROOT_EL = "hash_sets";
@ -62,6 +49,7 @@ public class HashDbXML {
private static final String PATH_EL = "hash_set_path"; private static final String PATH_EL = "hash_set_path";
private static final String PATH_NUMBER_ATTR = "number"; private static final String PATH_NUMBER_ATTR = "number";
private static final String CUR_HASHSETS_FILE_NAME = "hashsets.xml"; private static final String CUR_HASHSETS_FILE_NAME = "hashsets.xml";
private static final String XSDFILE = "HashsetsSchema.xsd";
private static final String ENCODING = "UTF-8"; private static final String ENCODING = "UTF-8";
private static final String CUR_HASHSET_FILE = PlatformUtil.getUserConfigDirectory() + File.separator + CUR_HASHSETS_FILE_NAME; private static final String CUR_HASHSET_FILE = PlatformUtil.getUserConfigDirectory() + File.separator + CUR_HASHSETS_FILE_NAME;
private static final String SET_CALC = "hash_calculate"; private static final String SET_CALC = "hash_calculate";
@ -263,7 +251,7 @@ public class HashDbXML {
setCalc.setAttribute(SET_VALUE, calcValue); setCalc.setAttribute(SET_VALUE, calcValue);
rootEl.appendChild(setCalc); rootEl.appendChild(setCalc);
success = saveDoc(doc); success = XMLUtil.saveDoc(HashDbXML.class, xmlFile, ENCODING, doc);
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
logger.log(Level.SEVERE, "Error saving hash sets: can't initialize parser.", e); logger.log(Level.SEVERE, "Error saving hash sets: can't initialize parser.", e);
} }
@ -274,7 +262,7 @@ public class HashDbXML {
* load and parse XML, then dispose * load and parse XML, then dispose
*/ */
public boolean load() { public boolean load() {
final Document doc = loadDoc(); final Document doc = XMLUtil.loadDoc(HashDbXML.class, xmlFile, XSDFILE);
if (doc == null) { if (doc == null) {
return false; return false;
} }
@ -432,65 +420,6 @@ public class HashDbXML {
File f = new File(xmlFile); File f = new File(xmlFile);
return f.exists() && f.canRead() && f.canWrite(); return f.exists() && f.canRead() && f.canWrite();
} }
private Document loadDoc() {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
Document ret = null;
try {
DocumentBuilder builder = builderFactory.newDocumentBuilder();
ret = builder.parse(
new FileInputStream(xmlFile));
} catch (ParserConfigurationException e) {
logger.log(Level.SEVERE, "Error loading hash sets: can't initialize parser.", e);
} catch (SAXException e) {
logger.log(Level.SEVERE, "Error loading hash sets: can't parse XML.", e);
} catch (IOException e) {
//error reading file
logger.log(Level.SEVERE, "Error loading hash sets: can't read file.", e);
}
return ret;
}
private boolean saveDoc(final Document doc) {
TransformerFactory xf = TransformerFactory.newInstance();
xf.setAttribute("indent-number", new Integer(1));
boolean success = false;
try {
Transformer xformer = xf.newTransformer();
xformer.setOutputProperty(OutputKeys.METHOD, "xml");
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
xformer.setOutputProperty(OutputKeys.ENCODING, ENCODING);
xformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
File file = new File(xmlFile);
FileOutputStream stream = new FileOutputStream(file);
Result out = new StreamResult(new OutputStreamWriter(stream, ENCODING));
xformer.transform(new DOMSource(doc), out);
stream.flush();
stream.close();
success = true;
} catch (UnsupportedEncodingException e) {
logger.log(Level.SEVERE, "Should not happen", e);
} catch (TransformerConfigurationException e) {
logger.log(Level.SEVERE, "Error writing hash sets XML", e);
} catch (TransformerException e) {
logger.log(Level.SEVERE, "Error writing hash sets XML", e);
} catch (FileNotFoundException e) {
logger.log(Level.SEVERE, "Error writing hash sets XML: cannot write to file: " + xmlFile, e);
} catch (IOException e) {
logger.log(Level.SEVERE, "Error writing hash sets XML: cannot write to file: " + xmlFile, e);
}
return success;
}
} }

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple types -->
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="show_inbox_messages" type="xs:boolean"/>
<xs:attribute name="type" type="xs:string"/>
<xs:attribute name="use_for_ingest" type="xs:boolean"/>
<xs:attribute name="number" type="xs:nonNegativeInteger"/>
<xs:attribute name="value" type="xs:boolean"/>
<!-- definition of complex types -->
<xs:element name="hash_set_path">
<xs:complexType mixed="true">
<xs:sequence/>
<xs:attribute ref="number" default="0" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="hash_set">
<xs:complexType>
<xs:sequence>
<xs:element ref="hash_set_path"/>
</xs:sequence>
<xs:attribute ref="name" use="required"/>
<xs:attribute ref="show_inbox_messages" default="true" use="optional"/>
<xs:attribute ref="type" use="required"/>
<xs:attribute ref="use_for_ingest" default="false" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="hash_calculate">
<xs:complexType>
<xs:sequence/>
<xs:attribute ref="value" default="false" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="hash_sets">
<xs:complexType>
<xs:sequence>
<xs:element ref="hash_set" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="hash_calculate" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -18,13 +18,6 @@
*/ */
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -35,20 +28,12 @@ import java.util.logging.Level;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/** /**
* Manages reading and writing of keyword lists to user settings XML file keywords.xml * Manages reading and writing of keyword lists to user settings XML file keywords.xml
@ -68,6 +53,7 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
private static final String KEYWORD_SELECTOR_ATTR = "selector"; private static final String KEYWORD_SELECTOR_ATTR = "selector";
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String ENCODING = "UTF-8"; private static final String ENCODING = "UTF-8";
private static final String XSDFILE = "KeywordsSchema.xsd";
private static final Logger logger = Logger.getLogger(KeywordSearchListsXML.class.getName()); private static final Logger logger = Logger.getLogger(KeywordSearchListsXML.class.getName());
private DateFormat dateFormatter; private DateFormat dateFormatter;
@ -132,7 +118,7 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
rootEl.appendChild(listEl); rootEl.appendChild(listEl);
} }
success = saveDoc(doc); success = XMLUtil.saveDoc(KeywordSearchListsXML.class, filePath, ENCODING, doc);
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
logger.log(Level.SEVERE, "Error saving keyword list: can't initialize parser.", e); logger.log(Level.SEVERE, "Error saving keyword list: can't initialize parser.", e);
} }
@ -144,7 +130,7 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
*/ */
@Override @Override
public boolean load() { public boolean load() {
final Document doc = loadDoc(); final Document doc = XMLUtil.loadDoc(KeywordSearchListsXML.class, filePath, XSDFILE);
if (doc == null) { if (doc == null) {
return false; return false;
} }
@ -212,63 +198,4 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
} }
return true; return true;
} }
private Document loadDoc() {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
Document ret = null;
try {
DocumentBuilder builder = builderFactory.newDocumentBuilder();
ret = builder.parse(
new FileInputStream(filePath));
} catch (ParserConfigurationException e) {
logger.log(Level.SEVERE, "Error loading keyword list: can't initialize parser.", e);
} catch (SAXException e) {
logger.log(Level.SEVERE, "Error loading keyword list: can't parse XML.", e);
} catch (IOException e) {
//error reading file
logger.log(Level.SEVERE, "Error loading keyword list: can't read file.", e);
}
return ret;
}
private boolean saveDoc(final Document doc) {
TransformerFactory xf = TransformerFactory.newInstance();
xf.setAttribute("indent-number", new Integer(1));
boolean success = false;
try {
Transformer xformer = xf.newTransformer();
xformer.setOutputProperty(OutputKeys.METHOD, "xml");
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
xformer.setOutputProperty(OutputKeys.ENCODING, ENCODING);
xformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
File file = new File(filePath);
FileOutputStream stream = new FileOutputStream(file);
Result out = new StreamResult(new OutputStreamWriter(stream, ENCODING));
xformer.transform(new DOMSource(doc), out);
stream.flush();
stream.close();
success = true;
} catch (UnsupportedEncodingException e) {
logger.log(Level.SEVERE, "Should not happen", e);
} catch (TransformerConfigurationException e) {
logger.log(Level.SEVERE, "Error writing keyword lists XML", e);
} catch (TransformerException e) {
logger.log(Level.SEVERE, "Error writing keyword lists XML", e);
} catch (FileNotFoundException e) {
logger.log(Level.SEVERE, "Error writing keyword lists XML: cannot write to file: " + filePath, e);
} catch (IOException e) {
logger.log(Level.SEVERE, "Error writing keyword lists XML: cannot write to file: " + filePath, e);
}
return success;
}
} }

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="literal" type="xs:boolean"/>
<xs:attribute name="ingest_messages" type="xs:boolean"/>
<xs:attribute name="use_for_ingest" type="xs:boolean"/>
<xs:attribute name="key" type="xs:string"/>
<xs:attribute name="created" >
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="([0-9]{4}-)+([0-1][0-9]-)+([0-3][0-9] )+([0-2][0-9]:[0-5][0-9]:[0-9][0-9])"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="modified">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="([0-9]{4}-)+([0-1][0-9]-)+([0-3][0-9] )+([0-2][0-9]:[0-5][0-9]:[0-9][0-9])"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<!-- definition of complex elements -->
<xs:element name="keyword">
<xs:complexType mixed="true">
<xs:attribute ref="literal" default="false" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="keyword_list">
<xs:complexType>
<xs:sequence>
<xs:element ref="keyword" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="created" use="required"/>
<xs:attribute ref="ingest_messages" use="optional"/>
<xs:attribute ref="modified" use="optional"/>
<xs:attribute ref="name" use="required"/>
<xs:attribute ref="use_for_ingest" default="false" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="keyword_lists">
<xs:complexType>
<xs:sequence>
<xs:element ref="keyword_list" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--- <!---
This file contains the parameters for search engines inside Autopsy for the SearchEngineURLQueryAnalyzer (SEUQA) module. This file contains the parameters for search engines inside Autopsy for the SearchEngineURLQueryAnalyzer (SEUQA) module.

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:attribute name="engine" type="xs:string"/>
<xs:attribute name="domainSubstring" type="xs:string"/>
<xs:attribute name="plainToken" type="xs:string"/>
<xs:attribute name="regexToken" type="xs:string"/>
<!-- definition of complex elements -->
<xs:element name="splitToken">
<xs:complexType>
<xs:sequence/>
<xs:attribute ref="plainToken" use="required"/>
<xs:attribute ref="regexToken" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="SearchEngine">
<xs:complexType>
<xs:sequence>
<xs:element ref="splitToken" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="engine" use="required"/>
<xs:attribute ref="domainSubstring" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="SES">
<xs:complexType>
<xs:sequence>
<xs:element ref="SearchEngine" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -33,7 +34,9 @@ import javax.swing.JPanel;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController; import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
import org.sleuthkit.autopsy.ingest.IngestModuleAbstract;
import org.sleuthkit.autopsy.ingest.IngestModuleImage; import org.sleuthkit.autopsy.ingest.IngestModuleImage;
import org.sleuthkit.autopsy.ingest.IngestModuleInit; import org.sleuthkit.autopsy.ingest.IngestModuleInit;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
@ -65,13 +68,14 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
public final static String MODULE_VERSION = "1.0"; public final static String MODULE_VERSION = "1.0";
private String args; private String args;
public static final String XMLFile = "SEUQAMappings.xml"; public static final String XMLFILE = "SEUQAMappings.xml";
private static final String XSDFILE = "SearchEngineSchema.xsd";
private static String[] searchEngineNames; private static String[] searchEngineNames;
private static SearchEngine[] engines; private static SearchEngineURLQueryAnalyzer.SearchEngine[] engines;
private static Document xmlinput; private static Document xmlinput;
private static final SearchEngine NullEngine = new SearchEngine("NONE", "NONE", new HashMap<String,String>()); private static final SearchEngineURLQueryAnalyzer.SearchEngine NullEngine = new SearchEngineURLQueryAnalyzer.SearchEngine("NONE", "NONE", new HashMap<String,String>());
//hide public constructor to prevent from instantiation by ingest module loader //hide public constructor to prevent from instantiation by ingest module loader
@ -123,10 +127,9 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
} }
private void createEngines(){ private void createEngines(){
NodeList nlist = xmlinput.getElementsByTagName("SearchEngine"); NodeList nlist = xmlinput.getElementsByTagName("SearchEngine");
SearchEngine[] listEngines = new SearchEngine[nlist.getLength()]; SearchEngineURLQueryAnalyzer.SearchEngine[] listEngines = new SearchEngineURLQueryAnalyzer.SearchEngine[nlist.getLength()];
for(int i = 0;i < nlist.getLength(); i++){ for(int i = 0;i < nlist.getLength(); i++){
try{ try{
NamedNodeMap nnm = nlist.item(i).getAttributes(); NamedNodeMap nnm = nlist.item(i).getAttributes();
@ -142,7 +145,7 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
} }
} }
SearchEngine Se = new SearchEngine(EngineName, EnginedomainSubstring, splits); SearchEngineURLQueryAnalyzer.SearchEngine Se = new SearchEngineURLQueryAnalyzer.SearchEngine(EngineName, EnginedomainSubstring, splits);
System.out.println("Search Engine: " + Se.toString()); System.out.println("Search Engine: " + Se.toString());
listEngines[i] = Se; listEngines[i] = Se;
} }
@ -162,7 +165,7 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
* *
*/ */
private static SearchEngine getSearchEngine(String domain){ private static SearchEngineURLQueryAnalyzer.SearchEngine getSearchEngine(String domain){
if (engines == null) { if (engines == null) {
return SearchEngineURLQueryAnalyzer.NullEngine; return SearchEngineURLQueryAnalyzer.NullEngine;
} }
@ -196,7 +199,7 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
private String extractSearchEngineQuery(String url){ private String extractSearchEngineQuery(String url){
String x = "NoQuery"; String x = "NoQuery";
SearchEngine eng = getSearchEngine(url); SearchEngineURLQueryAnalyzer.SearchEngine eng = getSearchEngine(url);
for(Map.Entry<String,String> kvp : eng.getSplits()){ for(Map.Entry<String,String> kvp : eng.getSplits()){
if(url.contains(kvp.getKey())){ if(url.contains(kvp.getKey())){
x = split2(url, kvp.getValue()); x = split2(url, kvp.getValue());
@ -257,7 +260,7 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
long last_accessed = -1; long last_accessed = -1;
//from tsk_files //from tsk_files
FsContent fs = this.extractFiles(image, "select * from tsk_files where `obj_id` = '" + artifact.getObjectID() + "'").get(0); //associated file FsContent fs = this.extractFiles(image, "select * from tsk_files where `obj_id` = '" + artifact.getObjectID() + "'").get(0); //associated file
SearchEngine se = NullEngine; SearchEngineURLQueryAnalyzer.SearchEngine se = NullEngine;
//from blackboard_attributes //from blackboard_attributes
Collection<BlackboardAttribute> listAttributes = currentCase.getSleuthkitCase().getMatchingAttributes("Where `artifact_id` = " + artifact.getArtifactID()); Collection<BlackboardAttribute> listAttributes = currentCase.getSleuthkitCase().getMatchingAttributes("Where `artifact_id` = " + artifact.getArtifactID());
getAttributes: getAttributes:
@ -322,7 +325,7 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
if (engines == null) { if (engines == null) {
return total; return total;
} }
for (SearchEngine se : engines) { for (SearchEngineURLQueryAnalyzer.SearchEngine se : engines) {
total+= se.getEngineName() + " : "+ se.getTotal() + "\n"; total+= se.getEngineName() + " : "+ se.getTotal() + "\n";
} }
return total; return total;
@ -330,6 +333,7 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
@Override @Override
public void process(Image image, IngestImageWorkerController controller) { public void process(Image image, IngestImageWorkerController controller) {
logger.info("LAUNCHING COOKIES, ALL COOKIES ENGAGE.");
this.getURLs(image, controller); this.getURLs(image, controller);
logger.info("Search Engine stats: \n" + getTotals()); logger.info("Search Engine stats: \n" + getTotals());
} }
@ -338,40 +342,40 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
public void init(IngestModuleInit initContext) { public void init(IngestModuleInit initContext) {
try{ try{
services = IngestServices.getDefault(); services = IngestServices.getDefault();
if(PlatformUtil.extractResourceToUserConfigDir(SearchEngineURLQueryAnalyzer.class, XMLFile)){ PlatformUtil.extractResourceToUserConfigDir(SearchEngineURLQueryAnalyzer.class, XMLFILE);
init2(); init2();
}
else{
logger.warning("Unable to find " + XMLFile);
}
} }
catch(IOException e){ catch(IOException e){
logger.log(Level.WARNING, "Unable to find " + XMLFile , e); logger.log(Level.WARNING, "Unable to find " + XMLFILE , e);
} }
} }
private void init2(){ private void init2() {
try{ try {
String path = PlatformUtil.getUserConfigDirectory() + File.separator + XMLFile; String path = PlatformUtil.getUserConfigDirectory() + File.separator + XMLFILE;
File f = new File(path); File f = new File(path);
System.out.println("Load successful"); System.out.println("Load successful");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder(); DocumentBuilder db = dbf.newDocumentBuilder();
Document xml = db.parse(f); Document xml = db.parse(f);
xmlinput = xml; xmlinput = xml;
try{
createEngines(); if (!XMLUtil.xmlIsValid(xml, SearchEngineURLQueryAnalyzer.class, XSDFILE)) {
getSearchEngineNames(); logger.log(Level.WARNING, "Error loading Search Engines: could not validate against [" + XSDFILE + "], results may not be accurate.");
}
catch(Exception e){
logger.log(Level.WARNING, "Unable to create Search Engines!", e);
}
} }
catch(Exception e){ try {
logger.log(Level.WARNING, "Was not able to load SEUQAMappings.xml", e); createEngines();
getSearchEngineNames();
} catch (Exception e) {
logger.log(Level.WARNING, "Unable to create Search Engines!", e);
} }
} catch (Exception e) {
logger.log(Level.WARNING, "Was not able to load SEUQAMappings.xml", e);
}
} }
@Override @Override
public void complete() { public void complete() {
@ -414,8 +418,8 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModul
} }
@Override @Override
public ModuleType getType() { public IngestModuleAbstract.ModuleType getType() {
return ModuleType.Image; return IngestModuleAbstract.ModuleType.Image;
} }
@Override @Override

Binary file not shown.