mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 08:56:15 +00:00
Merge branch 'master' of https://github.com/Devin148/autopsy
This commit is contained in:
commit
93d7340e3e
@ -6,6 +6,15 @@
|
|||||||
<code-name-base>org.sleuthkit.autopsy.datamodel</code-name-base>
|
<code-name-base>org.sleuthkit.autopsy.datamodel</code-name-base>
|
||||||
<suite-component/>
|
<suite-component/>
|
||||||
<module-dependencies>
|
<module-dependencies>
|
||||||
|
<dependency>
|
||||||
|
<code-name-base>org.netbeans.api.progress</code-name-base>
|
||||||
|
<build-prerequisite/>
|
||||||
|
<compile-dependency/>
|
||||||
|
<run-dependency>
|
||||||
|
<release-version>1</release-version>
|
||||||
|
<specification-version>1.28.1</specification-version>
|
||||||
|
</run-dependency>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<code-name-base>org.openide.awt</code-name-base>
|
<code-name-base>org.openide.awt</code-name-base>
|
||||||
<build-prerequisite/>
|
<build-prerequisite/>
|
||||||
|
@ -28,6 +28,8 @@ import java.util.List;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
@ -214,25 +216,47 @@ public final class ContentUtils {
|
|||||||
* it does
|
* it does
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static void writeToFile(Content content, java.io.File outputFile) throws IOException {
|
public static void writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, SwingWorker worker, boolean source) throws IOException {
|
||||||
|
|
||||||
InputStream in = new ReadContentInputStream(content);
|
InputStream in = new ReadContentInputStream(content);
|
||||||
|
|
||||||
boolean append = false;
|
boolean append = false;
|
||||||
FileOutputStream out = new FileOutputStream(outputFile, append);
|
FileOutputStream out = new FileOutputStream(outputFile, append);
|
||||||
|
|
||||||
|
// Get the unit size for a progress bar
|
||||||
|
int unit = (int) (content.getSize() / 100);
|
||||||
|
long totalRead = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
|
byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
|
||||||
int len = in.read(buffer);
|
int len = in.read(buffer);
|
||||||
while (len != -1) {
|
while (len != -1) {
|
||||||
|
// If there is a worker, check for a cancelation
|
||||||
|
if (worker!=null && worker.isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
out.write(buffer, 0, len);
|
out.write(buffer, 0, len);
|
||||||
len = in.read(buffer);
|
len = in.read(buffer);
|
||||||
|
totalRead+=len;
|
||||||
|
// If there is a progress bar and this is the source file,
|
||||||
|
// report any progress
|
||||||
|
if(progress!=null && source) {
|
||||||
|
int totalProgress = (int) (totalRead / unit);
|
||||||
|
progress.progress(content.getName(), totalProgress);
|
||||||
|
// If it's not the source, just update the file being processed
|
||||||
|
} else if(progress!=null && !source) {
|
||||||
|
progress.progress(content.getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void writeToFile(Content content, java.io.File outputFile) throws IOException {
|
||||||
|
writeToFile(content, outputFile, null, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to ignore the '.' and '..' directories
|
* Helper to ignore the '.' and '..' directories
|
||||||
*/
|
*/
|
||||||
@ -250,11 +274,21 @@ public final class ContentUtils {
|
|||||||
public static class ExtractFscContentVisitor extends ContentVisitor.Default<Void> {
|
public static class ExtractFscContentVisitor extends ContentVisitor.Default<Void> {
|
||||||
|
|
||||||
java.io.File dest;
|
java.io.File dest;
|
||||||
|
ProgressHandle progress;
|
||||||
|
SwingWorker worker;
|
||||||
|
boolean source = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make new extractor for a specific destination
|
* Make new extractor for a specific destination
|
||||||
* @param dest The file/folder visited will be extracted as this file
|
* @param dest The file/folder visited will be extracted as this file
|
||||||
*/
|
*/
|
||||||
|
public ExtractFscContentVisitor(java.io.File dest, ProgressHandle progress, SwingWorker worker, boolean source) {
|
||||||
|
this.dest = dest;
|
||||||
|
this.progress = progress;
|
||||||
|
this.worker = worker;
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
public ExtractFscContentVisitor(java.io.File dest) {
|
public ExtractFscContentVisitor(java.io.File dest) {
|
||||||
this.dest = dest;
|
this.dest = dest;
|
||||||
}
|
}
|
||||||
@ -263,13 +297,13 @@ public final class ContentUtils {
|
|||||||
* Convenience method to make a new instance for given destination
|
* Convenience method to make a new instance for given destination
|
||||||
* and extract given content
|
* and extract given content
|
||||||
*/
|
*/
|
||||||
public static void extract(Content cntnt, java.io.File dest) {
|
public static void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker worker) {
|
||||||
cntnt.accept(new ExtractFscContentVisitor(dest));
|
cntnt.accept(new ExtractFscContentVisitor(dest, progress, worker, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Void visit(File f) {
|
public Void visit(File f) {
|
||||||
try {
|
try {
|
||||||
ContentUtils.writeToFile(f, dest);
|
ContentUtils.writeToFile(f, dest, progress, worker, source);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.SEVERE,
|
logger.log(Level.SEVERE,
|
||||||
"Trouble extracting file to " + dest.getAbsolutePath(),
|
"Trouble extracting file to " + dest.getAbsolutePath(),
|
||||||
@ -292,12 +326,23 @@ public final class ContentUtils {
|
|||||||
DestFileContentVisitor destFileCV = new DestFileContentVisitor();
|
DestFileContentVisitor destFileCV = new DestFileContentVisitor();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
int numProcessed = 0;
|
||||||
// recurse on children
|
// recurse on children
|
||||||
for (Content child : dir.getChildren()) {
|
for (Content child : dir.getChildren()) {
|
||||||
java.io.File childFile = child.accept(destFileCV);
|
java.io.File childFile = child.accept(destFileCV);
|
||||||
ExtractFscContentVisitor childVisitor =
|
ExtractFscContentVisitor childVisitor =
|
||||||
new ExtractFscContentVisitor(childFile);
|
new ExtractFscContentVisitor(childFile, progress, worker, false);
|
||||||
|
// If this is the source directory of an extract it
|
||||||
|
// will have a progress and worker, and will keep track
|
||||||
|
// of the progress bar's progress
|
||||||
|
if(worker!=null && worker.isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(progress!=null && source) {
|
||||||
|
progress.progress(child.getName(), numProcessed);
|
||||||
|
}
|
||||||
child.accept(childVisitor);
|
child.accept(childVisitor);
|
||||||
|
numProcessed++;
|
||||||
}
|
}
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.SEVERE,
|
logger.log(Level.SEVERE,
|
||||||
|
@ -6,6 +6,15 @@
|
|||||||
<code-name-base>org.sleuthkit.autopsy.directorytree</code-name-base>
|
<code-name-base>org.sleuthkit.autopsy.directorytree</code-name-base>
|
||||||
<suite-component/>
|
<suite-component/>
|
||||||
<module-dependencies>
|
<module-dependencies>
|
||||||
|
<dependency>
|
||||||
|
<code-name-base>org.netbeans.api.progress</code-name-base>
|
||||||
|
<build-prerequisite/>
|
||||||
|
<compile-dependency/>
|
||||||
|
<run-dependency>
|
||||||
|
<release-version>1</release-version>
|
||||||
|
<specification-version>1.28.1</specification-version>
|
||||||
|
</run-dependency>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<code-name-base>org.netbeans.modules.settings</code-name-base>
|
<code-name-base>org.netbeans.modules.settings</code-name-base>
|
||||||
<build-prerequisite/>
|
<build-prerequisite/>
|
||||||
|
@ -18,17 +18,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.directorytree;
|
package org.sleuthkit.autopsy.directorytree;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import javax.swing.JFileChooser;
|
|
||||||
import java.io.File;
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
|
import org.netbeans.api.progress.ProgressHandleFactory;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
|
import org.openide.util.Cancellable;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
||||||
import org.sleuthkit.autopsy.coreutils.Log;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
@ -41,6 +47,7 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
|
|
||||||
private static final InitializeContentVisitor initializeCV = new InitializeContentVisitor();
|
private static final InitializeContentVisitor initializeCV = new InitializeContentVisitor();
|
||||||
private FsContent fsContent;
|
private FsContent fsContent;
|
||||||
|
private Logger logger = Logger.getLogger(ExtractAction.class.getName());
|
||||||
|
|
||||||
public ExtractAction(String title, Node contentNode) {
|
public ExtractAction(String title, Node contentNode) {
|
||||||
super(title);
|
super(title);
|
||||||
@ -78,8 +85,7 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Log.noteAction(this.getClass());
|
// Get file and check that it's okay to overwrite existing file
|
||||||
|
|
||||||
JFileChooser fc = new JFileChooser();
|
JFileChooser fc = new JFileChooser();
|
||||||
fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory()));
|
fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory()));
|
||||||
fc.setSelectedFile(new File(this.fsContent.getName()));
|
fc.setSelectedFile(new File(this.fsContent.getName()));
|
||||||
@ -88,7 +94,7 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
||||||
File destination = fc.getSelectedFile();
|
File destination = fc.getSelectedFile();
|
||||||
|
|
||||||
// check that it's okay to overwrite existing file
|
// do the check
|
||||||
if (destination.exists()) {
|
if (destination.exists()) {
|
||||||
int choice = JOptionPane.showConfirmDialog(
|
int choice = JOptionPane.showConfirmDialog(
|
||||||
(Component) e.getSource(),
|
(Component) e.getSource(),
|
||||||
@ -97,7 +103,7 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
JOptionPane.OK_CANCEL_OPTION);
|
JOptionPane.OK_CANCEL_OPTION);
|
||||||
|
|
||||||
if (choice != JOptionPane.OK_OPTION) {
|
if (choice != JOptionPane.OK_OPTION) {
|
||||||
return;
|
return; // Just exit the function
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!destination.delete()) {
|
if (!destination.delete()) {
|
||||||
@ -107,12 +113,133 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractFscContentVisitor.extract(fsContent, destination);
|
try {
|
||||||
if(fsContent.isDir())
|
ExtractFileThread extract = new ExtractFileThread();
|
||||||
JOptionPane.showMessageDialog((Component) e.getSource(), "Directory extracted.");
|
extract.init(this.fsContent, e, destination);
|
||||||
else if(fsContent.isFile()){
|
extract.execute();
|
||||||
JOptionPane.showMessageDialog((Component) e.getSource(), "File extracted.");
|
} catch (Exception ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to start background thread.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ExtractFileThread extends SwingWorker<Object,Void> {
|
||||||
|
private Logger logger = Logger.getLogger(ExtractFileThread.class.getName());
|
||||||
|
private ProgressHandle progress;
|
||||||
|
private FsContent fsContent;
|
||||||
|
ActionEvent e;
|
||||||
|
File destination;
|
||||||
|
|
||||||
|
private void init(FsContent fsContent, ActionEvent e, File destination) {
|
||||||
|
this.fsContent = fsContent;
|
||||||
|
this.e = e;
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object doInBackground() throws Exception {
|
||||||
|
logger.log(Level.INFO, "Starting background processing for file extraction.");
|
||||||
|
|
||||||
|
// Setup progress bar
|
||||||
|
final String displayName = "Extracting";
|
||||||
|
progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
|
||||||
|
@Override
|
||||||
|
public boolean cancel() {
|
||||||
|
if (progress != null)
|
||||||
|
progress.setDisplayName(displayName + " (Cancelling...)");
|
||||||
|
return ExtractAction.ExtractFileThread.this.cancel(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start the progress bar as indeterminate
|
||||||
|
progress.start();
|
||||||
|
progress.switchToIndeterminate();
|
||||||
|
if(fsContent.isFile()) {
|
||||||
|
// Max file size of 200GB
|
||||||
|
long filesize = fsContent.getSize();
|
||||||
|
int unit = (int) (filesize / 100);
|
||||||
|
progress.switchToDeterminate(100);
|
||||||
|
} else if(fsContent.isDir()) {
|
||||||
|
// If dir base progress off number of children
|
||||||
|
int toProcess = fsContent.getChildren().size();
|
||||||
|
progress.switchToDeterminate(toProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start extracting the file/directory
|
||||||
|
ExtractFscContentVisitor.extract(fsContent, destination, progress, this);
|
||||||
|
logger.log(Level.INFO, "Done background processing");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
try {
|
||||||
|
super.get(); //block and get all exceptions thrown while doInBackground()
|
||||||
|
} catch (CancellationException ex) {
|
||||||
|
logger.log(Level.INFO, "Extraction was canceled.");
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
logger.log(Level.INFO, "Extraction was interrupted.");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.log(Level.SEVERE, "Fatal error during file extraction.", ex);
|
||||||
|
} finally {
|
||||||
|
progress.finish();
|
||||||
|
if (!this.isCancelled()) {
|
||||||
|
logger.log(Level.INFO, "Extracting completed without cancellation.");
|
||||||
|
// Alert the user extraction is over
|
||||||
|
if(fsContent.isDir()) {
|
||||||
|
JOptionPane.showMessageDialog((Component) e.getSource(), "Directory extracted.");
|
||||||
|
} else if(fsContent.isFile()){
|
||||||
|
JOptionPane.showMessageDialog((Component) e.getSource(), "File extracted.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.log(Level.INFO, "Attempting to delete file(s).");
|
||||||
|
if(delete(destination)) {
|
||||||
|
logger.log(Level.INFO, "Finished deletion sucessfully.");
|
||||||
|
} else {
|
||||||
|
logger.log(Level.WARNING, "Deletion attempt complete; not all files were sucessfully deleted.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean delete(File file) {
|
||||||
|
boolean sucess = true;
|
||||||
|
// If it's a file
|
||||||
|
if(file.isFile()) {
|
||||||
|
if(!file.delete()) {
|
||||||
|
sucess = false;
|
||||||
|
logger.log(Level.WARNING, "Failed to delete file {0}", file.getPath());
|
||||||
|
}
|
||||||
|
// If it's a directory
|
||||||
|
} else {
|
||||||
|
// If the dir is empty
|
||||||
|
if(file.list().length==0) {
|
||||||
|
if(!file.delete()) {
|
||||||
|
sucess = false;
|
||||||
|
logger.log(Level.WARNING, "Failed to delete the empty directory at {0}", file.getPath());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String files[] = file.list();
|
||||||
|
for(String s:files) {
|
||||||
|
File sub = new File(file, s);
|
||||||
|
sucess = delete(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the newly-empty dir
|
||||||
|
if(file.list().length==0) {
|
||||||
|
if(!file.delete()) {
|
||||||
|
sucess = false;
|
||||||
|
logger.log(Level.WARNING, "Failed to delete the empty directory at {0}", file.getPath());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sucess = false;
|
||||||
|
logger.log(Level.WARNING, "Directory {0} did not recursivly delete sucessfully.", file.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sucess;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
13
Testing/script/config.xml
Normal file
13
Testing/script/config.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="ASCII"?>
|
||||||
|
<!-- This file is an example config file for regression.py.
|
||||||
|
the following tags are mandatory:
|
||||||
|
1 "indir" tag that specifies where the program can find the hash databases
|
||||||
|
any number of "image" tags that specify where the images are stored. They do not have to be local.
|
||||||
|
invalid paths and images are ignored by the tester.
|
||||||
|
|
||||||
|
in this file, the first three tags are accepted by the tester, while the last two are disregarded as errors-->
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<indir name="indir" value="C:\Users\dhurd\Documents\GitHub\autopsy\Testing\script\input" />
|
||||||
|
<!--<image name="image1" value="P:\shared\Testing\script\input\64mb2.img"/>-->
|
||||||
|
</Properties>
|
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
#en_US.UTF-8
|
||||||
import sys
|
import sys
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import re
|
import re
|
||||||
@ -6,18 +7,24 @@ import subprocess
|
|||||||
import os.path
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
import xml
|
||||||
|
from xml.dom.minidom import parse, parseString
|
||||||
|
|
||||||
# Last modified 7/13/12 3@ pm
|
|
||||||
# Usage: ./regression.py [-i FILE] [OPTIONS]
|
# Last modified 7/17/12 @5pm
|
||||||
|
# Usage: ./regression.py [-s FILE] OR [-l CONFIG] [OPTIONS]
|
||||||
# Run the RegressionTest.java file, and compare the result with a gold standard
|
# Run the RegressionTest.java file, and compare the result with a gold standard
|
||||||
# When the -i flag is set, this script only tests the image given by FILE.
|
# When the -i flag is set, this script only tests the image given by FILE.
|
||||||
# By default, it tests every image in ./input/
|
|
||||||
# An indexed NSRL database is expected at ./input/nsrl.txt-md5.idx,
|
# An indexed NSRL database is expected at ./input/nsrl.txt-md5.idx,
|
||||||
# and an indexed notable hash database at ./input/notablehashes.txt-md5.idx
|
# and an indexed notable hash database at ./input/notablehashes.txt-md5.idx
|
||||||
# In addition, any keywords to search for must be in ./input/notablekeywords.xml
|
# In addition, any keywords to search for must be in ./input/notablekeywords.xml
|
||||||
|
# When the -l flag is set, the script looks for a config.xml file of the given name
|
||||||
|
# where images are stored. For usage notes please see the example "config.xml" in
|
||||||
|
# the /script folder.
|
||||||
# Options:
|
# Options:
|
||||||
# -r, --rebuild Rebuild the gold standards from the test results for each image
|
# -r, --rebuild Rebuild the gold standards from the test results for each image
|
||||||
# -u, --ignore
|
# -i, --ignore Ignores unallocated space when ingesting. Faster, but less accurate results.
|
||||||
|
|
||||||
|
|
||||||
hadErrors = False # If any of the tests failed
|
hadErrors = False # If any of the tests failed
|
||||||
results = {} # Dictionary in which to store map ({imgname}->errors)
|
results = {} # Dictionary in which to store map ({imgname}->errors)
|
||||||
@ -28,14 +35,18 @@ outDir = os.path.join("output",time.strftime("%Y.%m.%d-%H.%M"))
|
|||||||
|
|
||||||
|
|
||||||
# Run ingest on all the images in 'input', using notablekeywords.xml and notablehashes.txt-md5.idx
|
# Run ingest on all the images in 'input', using notablekeywords.xml and notablehashes.txt-md5.idx
|
||||||
def testAddImageIngest(inFile, ignoreUnalloc):
|
def testAddImageIngest(inFile, ignoreUnalloc, list):
|
||||||
print "================================================"
|
print "================================================"
|
||||||
print "Ingesting Image: " + inFile
|
print "Ingesting Image: " + inFile
|
||||||
|
|
||||||
# Set up case directory path
|
# Set up case directory path
|
||||||
testCaseName = imageName(inFile)
|
testCaseName = imageName(inFile)
|
||||||
|
|
||||||
|
#check for flags to append to folder name
|
||||||
if ignoreUnalloc:
|
if ignoreUnalloc:
|
||||||
testCaseName+="-u"
|
testCaseName+="-i"
|
||||||
|
if list:
|
||||||
|
testCaseName+="-l"
|
||||||
if os.path.exists(os.path.join(outDir,testCaseName)):
|
if os.path.exists(os.path.join(outDir,testCaseName)):
|
||||||
shutil.rmtree(os.path.join(outDir,testCaseName))
|
shutil.rmtree(os.path.join(outDir,testCaseName))
|
||||||
os.makedirs(os.path.join(outDir,testCaseName))
|
os.makedirs(os.path.join(outDir,testCaseName))
|
||||||
@ -44,20 +55,27 @@ def testAddImageIngest(inFile, ignoreUnalloc):
|
|||||||
|
|
||||||
cwd = wgetcwd()
|
cwd = wgetcwd()
|
||||||
testInFile = wabspath(inFile)
|
testInFile = wabspath(inFile)
|
||||||
|
|
||||||
# NEEDS windows path (backslashes) for .E00 images to work
|
# NEEDS windows path (backslashes) for .E00 images to work
|
||||||
testInFile = testInFile.replace("/", "\\")
|
testInFile = testInFile.replace("/", "\\")
|
||||||
knownBadPath = os.path.join(cwd,inDir,"notablehashes.txt-md5.idx")
|
if list:
|
||||||
|
knownBadPath = os.path.join(inDir, "notablehashes.txt-md5.idx")
|
||||||
|
keywordPath = os.path.join(inDir, "notablekeywords.xml")
|
||||||
|
nsrlPath = os.path.join(inDir, "nsrl.txt-md5.idx")
|
||||||
|
else:
|
||||||
|
knownBadPath = os.path.join(cwd,inDir,"notablehashes.txt-md5.idx")
|
||||||
|
keywordPath = os.path.join(cwd,inDir,"notablekeywords.xml")
|
||||||
|
nsrlPath = os.path.join(cwd,inDir,"nsrl.txt-md5.idx")
|
||||||
|
|
||||||
knownBadPath = knownBadPath.replace("/", "\\")
|
knownBadPath = knownBadPath.replace("/", "\\")
|
||||||
keywordPath = os.path.join(cwd,inDir,"notablekeywords.xml")
|
|
||||||
keywordPath = keywordPath.replace("/", "\\")
|
keywordPath = keywordPath.replace("/", "\\")
|
||||||
nsrlPath = os.path.join(cwd,inDir,"nsrl.txt-md5.idx")
|
|
||||||
nsrlPath = nsrlPath.replace("/", "\\")
|
nsrlPath = nsrlPath.replace("/", "\\")
|
||||||
|
|
||||||
antlog = os.path.join(cwd,outDir,testCaseName,"antlog.txt")
|
antlog = os.path.join(cwd,outDir,testCaseName,"antlog.txt")
|
||||||
antlog = antlog.replace("/", "\\")
|
antlog = antlog.replace("/", "\\")
|
||||||
|
|
||||||
timeout = 24 * 60 * 60 * 1000 # default of 24 hours, just to be safe
|
timeout = 24 * 60 * 60 * 1000 # default of 24 hours, just to be safe
|
||||||
size = getImageSize(inFile) # get the size in bytes
|
size = getImageSize(inFile, list) # get the size in bytes
|
||||||
timeout = (size / 1000) / 1000 # convert to MB
|
timeout = (size / 1000) / 1000 # convert to MB
|
||||||
timeout = timeout * 1000 # convert sec to ms
|
timeout = timeout * 1000 # convert sec to ms
|
||||||
timeout = timeout * 1.5 # add a little extra umph
|
timeout = timeout * 1.5 # add a little extra umph
|
||||||
@ -80,7 +98,6 @@ def testAddImageIngest(inFile, ignoreUnalloc):
|
|||||||
args.append("-Dignore_unalloc=" + "%s" % ignoreUnalloc)
|
args.append("-Dignore_unalloc=" + "%s" % ignoreUnalloc)
|
||||||
args.append("-Dtest.timeout=" + str(timeout))
|
args.append("-Dtest.timeout=" + str(timeout))
|
||||||
|
|
||||||
|
|
||||||
# print the ant testing command
|
# print the ant testing command
|
||||||
print "CMD: " + " ".join(args)
|
print "CMD: " + " ".join(args)
|
||||||
|
|
||||||
@ -90,17 +107,21 @@ def testAddImageIngest(inFile, ignoreUnalloc):
|
|||||||
#fnull.close();
|
#fnull.close();
|
||||||
subprocess.call(args)
|
subprocess.call(args)
|
||||||
|
|
||||||
def getImageSize(inFile):
|
def getImageSize(inFile, list):
|
||||||
name = imageName(inFile)
|
name = imageName(inFile)
|
||||||
path = os.path.join(".",inDir)
|
|
||||||
size = 0
|
size = 0
|
||||||
for files in os.listdir(path):
|
if list:
|
||||||
filename = os.path.splitext(files)[0]
|
size += os.path.getsize(inFile)
|
||||||
if filename == name:
|
else:
|
||||||
filepath = os.path.join(path, files)
|
path = os.path.join(".",inDir)
|
||||||
if not os.path.samefile(filepath, inFile):
|
|
||||||
size += os.path.getsize(filepath)
|
for files in os.listdir(path):
|
||||||
size += os.path.getsize(inFile)
|
filename = os.path.splitext(files)[0]
|
||||||
|
if filename == name:
|
||||||
|
filepath = os.path.join(path, files)
|
||||||
|
if not os.path.samefile(filepath, inFile):
|
||||||
|
size += os.path.getsize(filepath)
|
||||||
|
size += os.path.getsize(inFile)
|
||||||
return size
|
return size
|
||||||
|
|
||||||
def testCompareToGold(inFile, ignore):
|
def testCompareToGold(inFile, ignore):
|
||||||
@ -109,7 +130,7 @@ def testCompareToGold(inFile, ignore):
|
|||||||
|
|
||||||
name = imageName(inFile)
|
name = imageName(inFile)
|
||||||
if ignore:
|
if ignore:
|
||||||
name += ("-u")
|
name += ("-i")
|
||||||
cwd = wgetcwd()
|
cwd = wgetcwd()
|
||||||
goldFile = os.path.join("./",goldDir,name,"standard.db")
|
goldFile = os.path.join("./",goldDir,name,"standard.db")
|
||||||
testFile = os.path.join("./",outDir,name,"AutopsyTestCase","autopsy.db")
|
testFile = os.path.join("./",outDir,name,"AutopsyTestCase","autopsy.db")
|
||||||
@ -166,32 +187,38 @@ def testCompareToGold(inFile, ignore):
|
|||||||
else:
|
else:
|
||||||
print("Object counts match!")
|
print("Object counts match!")
|
||||||
|
|
||||||
def clearGoldDir(inFile, ignore):
|
def clearGoldDir(inFile, ignore, list):
|
||||||
cwd = wgetcwd()
|
cwd = wgetcwd()
|
||||||
inFile = imageName(inFile)
|
inFile = imageName(inFile)
|
||||||
if ignore:
|
if ignore:
|
||||||
inFile += "-u"
|
inFile += "-i"
|
||||||
|
if list:
|
||||||
|
inFile += "-l"
|
||||||
if os.path.exists(os.path.join(cwd,goldDir,inFile)):
|
if os.path.exists(os.path.join(cwd,goldDir,inFile)):
|
||||||
shutil.rmtree(os.path.join(cwd,goldDir,inFile))
|
shutil.rmtree(os.path.join(cwd,goldDir,inFile))
|
||||||
os.makedirs(os.path.join(cwd,goldDir,inFile))
|
os.makedirs(os.path.join(cwd,goldDir,inFile))
|
||||||
|
|
||||||
def copyTestToGold(inFile, ignore):
|
def copyTestToGold(inFile, ignore, list):
|
||||||
print "------------------------------------------------"
|
print "------------------------------------------------"
|
||||||
print "Recreating gold standard from results."
|
print "Recreating gold standard from results."
|
||||||
inFile = imageName(inFile)
|
inFile = imageName(inFile)
|
||||||
if ignore:
|
if ignore:
|
||||||
inFile += "-u"
|
inFile += "-i"
|
||||||
|
if list:
|
||||||
|
inFile += "-l"
|
||||||
cwd = wgetcwd()
|
cwd = wgetcwd()
|
||||||
goldFile = os.path.join("./",goldDir,inFile,"standard.db")
|
goldFile = os.path.join("./",goldDir,inFile,"standard.db")
|
||||||
testFile = os.path.join("./",outDir,inFile,"AutopsyTestCase","autopsy.db")
|
testFile = os.path.join("./",outDir,inFile,"AutopsyTestCase","autopsy.db")
|
||||||
shutil.copy(testFile, goldFile)
|
shutil.copy(testFile, goldFile)
|
||||||
|
|
||||||
def copyReportToGold(inFile, ignore):
|
def copyReportToGold(inFile, ignore, list):
|
||||||
print "------------------------------------------------"
|
print "------------------------------------------------"
|
||||||
print "Recreating gold report from results."
|
print "Recreating gold report from results."
|
||||||
inFile = imageName(inFile)
|
inFile = imageName(inFile)
|
||||||
if ignore:
|
if ignore:
|
||||||
inFile += "-u"
|
inFile += "-i"
|
||||||
|
if list:
|
||||||
|
inFile += "-l"
|
||||||
cwd = wgetcwd()
|
cwd = wgetcwd()
|
||||||
goldReport = os.path.join("./",goldDir,inFile,"report.html")
|
goldReport = os.path.join("./",goldDir,inFile,"report.html")
|
||||||
testReportPath = os.path.join("./",outDir,inFile,"AutopsyTestCase","Reports")
|
testReportPath = os.path.join("./",outDir,inFile,"AutopsyTestCase","Reports")
|
||||||
@ -208,12 +235,14 @@ def copyReportToGold(inFile, ignore):
|
|||||||
else:
|
else:
|
||||||
shutil.copy(testReport, goldReport)
|
shutil.copy(testReport, goldReport)
|
||||||
|
|
||||||
def testCompareReports(inFile, ignore):
|
def testCompareReports(inFile, ignore, list):
|
||||||
print "------------------------------------------------"
|
print "------------------------------------------------"
|
||||||
print "Comparing report to golden report."
|
print "Comparing report to golden report."
|
||||||
name = imageName(inFile)
|
name = imageName(inFile)
|
||||||
if ignore:
|
if ignore:
|
||||||
name += "-u"
|
name += "-i"
|
||||||
|
if list:
|
||||||
|
name += "-l"
|
||||||
goldReport = os.path.join("./",goldDir,name,"report.html")
|
goldReport = os.path.join("./",goldDir,name,"report.html")
|
||||||
testReportPath = os.path.join("./",outDir,name,"AutopsyTestCase","Reports")
|
testReportPath = os.path.join("./",outDir,name,"AutopsyTestCase","Reports")
|
||||||
# Because Java adds a timestamp to the report file, one can't call it
|
# Because Java adds a timestamp to the report file, one can't call it
|
||||||
@ -276,15 +305,20 @@ def imageType(inFile):
|
|||||||
|
|
||||||
def imageName(inFile):
|
def imageName(inFile):
|
||||||
pathEnd = inFile.rfind("/")
|
pathEnd = inFile.rfind("/")
|
||||||
|
pathEnd2 = inFile.rfind("\\")
|
||||||
extStart = inFile.rfind(".")
|
extStart = inFile.rfind(".")
|
||||||
if(extStart == -1 and extStart == -1):
|
if(extStart == -1 and extStart == -1):
|
||||||
return inFile
|
return inFile
|
||||||
|
if(pathEnd2 != -1):
|
||||||
|
return inFile[pathEnd2+1:extStart]
|
||||||
elif(extStart == -1):
|
elif(extStart == -1):
|
||||||
return inFile[pathEnd+1:]
|
return inFile[pathEnd+1:]
|
||||||
elif(pathEnd == -1):
|
elif(pathEnd == -1):
|
||||||
return inFile[:extStart]
|
return inFile[:extStart]
|
||||||
else:
|
elif(pathEnd!=-1 and extStart!=-1):
|
||||||
return inFile[pathEnd+1:extStart]
|
return inFile[pathEnd+1:extStart]
|
||||||
|
else:
|
||||||
|
return inFile[pathEnd2+1:extStart]
|
||||||
|
|
||||||
def markError(errString, inFile):
|
def markError(errString, inFile):
|
||||||
global hadErrors
|
global hadErrors
|
||||||
@ -300,41 +334,47 @@ def wgetcwd():
|
|||||||
return out.rstrip()
|
return out.rstrip()
|
||||||
|
|
||||||
def wabspath(inFile):
|
def wabspath(inFile):
|
||||||
proc = subprocess.Popen(("cygpath", "-m", os.path.abspath(inFile)), stdout=subprocess.PIPE)
|
if(inFile[1:2] == ":"):
|
||||||
out,err = proc.communicate()
|
proc = subprocess.Popen(("cygpath", "-m", inFile), stdout=subprocess.PIPE)
|
||||||
|
out,err = proc.communicate()
|
||||||
|
else:
|
||||||
|
proc = subprocess.Popen(("cygpath", "-m", os.path.abspath(inFile)), stdout=subprocess.PIPE)
|
||||||
|
out,err = proc.communicate()
|
||||||
return out.rstrip()
|
return out.rstrip()
|
||||||
|
|
||||||
def copyLogs(inFile, ignore):
|
def copyLogs(inFile, ignore, list):
|
||||||
name = imageName(inFile)
|
name = imageName(inFile)
|
||||||
if ignore:
|
if ignore:
|
||||||
name +="-u"
|
name +="-i"
|
||||||
|
if list:
|
||||||
|
name+="-l"
|
||||||
logDir = os.path.join("..","build","test","qa-functional","work","userdir0","var","log")
|
logDir = os.path.join("..","build","test","qa-functional","work","userdir0","var","log")
|
||||||
shutil.copytree(logDir,os.path.join(outDir,name,"logs"))
|
shutil.copytree(logDir,os.path.join(outDir,name,"logs"))
|
||||||
|
|
||||||
def testFile(image, rebuild, ignore):
|
def testFile(image, rebuild, ignore, list):
|
||||||
if imageType(image) != ImgType.UNKNOWN:
|
if imageType(image) != ImgType.UNKNOWN:
|
||||||
if ignore:
|
testAddImageIngest(image, ignore, list)
|
||||||
testAddImageIngest(image, True)
|
copyLogs(image, ignore, list)
|
||||||
else:
|
|
||||||
testAddImageIngest(image, False)
|
|
||||||
copyLogs(image, ignore)
|
|
||||||
if rebuild:
|
if rebuild:
|
||||||
clearGoldDir(image, ignore)
|
clearGoldDir(image, ignore, list)
|
||||||
copyTestToGold(image, ignore)
|
copyTestToGold(image, ignore, list)
|
||||||
copyReportToGold(image, ignore)
|
copyReportToGold(image, ignore, list)
|
||||||
else:
|
else:
|
||||||
testCompareToGold(image, ignore)
|
testCompareToGold(image, ignore, list)
|
||||||
testCompareReports(image, ignore)
|
testCompareReports(image, ignore, list)
|
||||||
|
|
||||||
def usage() :
|
def usage():
|
||||||
usage = "\
|
usage = "\
|
||||||
Usage: ./regression.py [-i FILE] [OPTIONS] \n\n\
|
Usage: ./regression.py [-s FILE] [OPTIONS] \n\n\
|
||||||
Run the RegressionTest.java file, and compare the result with a gold standard \n\n\
|
Run the RegressionTest.java file, and compare the result with a gold standard \n\n\
|
||||||
When the -i flag is set, this script only tests the image given by FILE.\n\
|
When the -i flag is set, this script only tests the image given by FILE.\n\
|
||||||
By default, it tests every image in ./input/\n\n\
|
By default, it tests every image in ./input/\n\n\
|
||||||
An indexed NSRL database is expected at ./input/nsrl.txt-md5.idx,\n\
|
An indexed NSRL database is expected at ./input/nsrl.txt-md5.idx,\n\
|
||||||
and an indexed notable hash database at ./input/notablehashes.txt-md5.idx\n\
|
and an indexed notable hash database at ./input/notablehashes.txt-md5.idx\n\
|
||||||
In addition, any keywords to search for must be in ./input/notablekeywords.xml\n\n\
|
In addition, any keywords to search for must be in ./input/notablekeywords.xml\n\n\
|
||||||
|
When the -l flag is set, the script looks for a config.xml file of the given name\n\
|
||||||
|
where images are stored. For usage notes please see the example config.xml in\n\
|
||||||
|
the /script folder.\
|
||||||
Options:\n\n\
|
Options:\n\n\
|
||||||
-r, --rebuild\t\tRebuild the gold standards from the test results for each image\n\n\
|
-r, --rebuild\t\tRebuild the gold standards from the test results for each image\n\n\
|
||||||
-u, --ignore\t\tIgnore unallocated space while ingesting"
|
-u, --ignore\t\tIgnore unallocated space while ingesting"
|
||||||
@ -344,19 +384,36 @@ def main():
|
|||||||
rebuild = False
|
rebuild = False
|
||||||
single = False
|
single = False
|
||||||
ignore = False
|
ignore = False
|
||||||
|
list = False
|
||||||
test = True
|
test = True
|
||||||
argi = 1
|
argi = 1
|
||||||
|
Config = None #file pointed to by --list
|
||||||
|
imgListB = [] #list of legal images from config
|
||||||
|
cwd = wgetcwd()
|
||||||
while argi < len(sys.argv):
|
while argi < len(sys.argv):
|
||||||
arg = sys.argv[argi]
|
arg = sys.argv[argi]
|
||||||
if arg == "-i" and argi+1 < len(sys.argv):
|
if arg == "-s" and argi+1 < len(sys.argv): #check for single
|
||||||
single = True
|
single = True
|
||||||
argi+=1
|
argi+=1
|
||||||
image = sys.argv[argi]
|
image = sys.argv[argi]
|
||||||
print "Running on single image: " + image
|
print "Running on single image: " + image
|
||||||
elif (arg == "--rebuild") or (arg == "-r"):
|
if arg == "-l" or arg == "--list": #check for config file
|
||||||
|
list = True
|
||||||
|
argi+=1
|
||||||
|
#check for file in ./
|
||||||
|
if(os.path.isfile(os.path.join("./", sys.argv[argi]))):
|
||||||
|
Config = parse(os.path.join("./", sys.argv[argi]))
|
||||||
|
#else check if it is a specified path
|
||||||
|
elif (os.path.exists(wabspath(sys.argv[argi]))):
|
||||||
|
Config = parse(sys.argv[argi])
|
||||||
|
else:
|
||||||
|
print sys.argv[argi]
|
||||||
|
print wabspath(sys.argv[argi])
|
||||||
|
markError("Ran with " + arg +" but no such file exists", arg)
|
||||||
|
elif (arg == "--rebuild") or (arg == "-r"): #check for rebuild flag
|
||||||
rebuild = True
|
rebuild = True
|
||||||
print "Running in REBUILD mode"
|
print "Running in REBUILD mode"
|
||||||
elif (arg == "--ignore") or (arg == "-u"):
|
elif (arg == "--ignore") or (arg == "-i"): #check for ignore flag
|
||||||
ignore = True
|
ignore = True
|
||||||
print "Ignoring unallocated space"
|
print "Ignoring unallocated space"
|
||||||
else:
|
else:
|
||||||
@ -365,9 +422,28 @@ def main():
|
|||||||
argi+=1
|
argi+=1
|
||||||
if single:
|
if single:
|
||||||
testFile(image, rebuild, ignore)
|
testFile(image, rebuild, ignore)
|
||||||
|
if list:
|
||||||
|
listImages = []
|
||||||
|
errors = 0
|
||||||
|
global inDir
|
||||||
|
out = Config.getElementsByTagName("indir")[0].getAttribute("value").encode() #there should only be one indir element in the config
|
||||||
|
inDir = out
|
||||||
|
for element in Config.getElementsByTagName("image"):
|
||||||
|
elem = element.getAttribute("value").encode()
|
||||||
|
proc2 = subprocess.Popen(("cygpath", "-i", elem), stdout=subprocess.PIPE)
|
||||||
|
out2,err = proc2.communicate()
|
||||||
|
out2 = out2.rstrip()
|
||||||
|
if(os.path.exists(out2) and os.path.isfile(out2)):
|
||||||
|
listImages.append(elem)
|
||||||
|
else:
|
||||||
|
print out2 + " is not a valid path or is not an image"
|
||||||
|
errors+=1
|
||||||
|
print "Illegal files specified: " + str(errors)
|
||||||
|
for image in listImages:
|
||||||
|
testFile(image, rebuild, ignore, list)
|
||||||
elif test:
|
elif test:
|
||||||
for inFile in os.listdir(inDir):
|
for inFile in os.listdir(inDir):
|
||||||
testFile(os.path.join(inDir,inFile), rebuild, ignore)
|
testFile(os.path.join(inDir,inFile), rebuild, ignore, list)
|
||||||
|
|
||||||
if hadErrors == True:
|
if hadErrors == True:
|
||||||
print "**********************************************"
|
print "**********************************************"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user