mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge branch 'master' of https://github.com/0xNF/autopsy
Conflicts: Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbXML.java
This commit is contained in:
commit
92fa58bd2c
@ -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);
|
||||||
|
|
||||||
|
97
Core/src/org/sleuthkit/autopsy/casemodule/CaseSchema.xsd
Normal file
97
Core/src/org/sleuthkit/autopsy/casemodule/CaseSchema.xsd
Normal 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>
|
@ -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();
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
183
Core/src/org/sleuthkit/autopsy/coreutils/XMLUtil.java
Normal file
183
Core/src/org/sleuthkit/autopsy/coreutils/XMLUtil.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
@ -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
|
||||||
|
@ -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"/>
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
@ -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.
|
||||||
|
|
||||||
|
@ -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>
|
@ -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
|
||||||
|
BIN
thirdparty/crt/x86-32/10.0.40219.1/crt.zip
vendored
Normal file
BIN
thirdparty/crt/x86-32/10.0.40219.1/crt.zip
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user