Copy the source directory in AddLogicalImageTask, so progress monitor works

This commit is contained in:
Joe Ho 2019-08-14 14:03:31 -04:00
parent bca13c0808
commit 0f15e20fd3
4 changed files with 102 additions and 79 deletions

View File

@ -191,7 +191,6 @@ EditNonFullPathsRulePanel.fileNamesInfoLabel.text=File names are case insensitiv
EditNonFullPathsRulePanel.extensionsInfoLabel.text=Extensions are case insensitive. EditNonFullPathsRulePanel.extensionsInfoLabel.text=Extensions are case insensitive.
ConfigVisualPanel2.promptBeforeExit.text=Prompt before exiting imager ConfigVisualPanel2.promptBeforeExit.text=Prompt before exiting imager
ConfigVisualPanel2.promptBeforeExit.actionCommand= ConfigVisualPanel2.promptBeforeExit.actionCommand=
ConfigVisualPanel2.createVHDCheckBox.toolTipText=
ConfigVisualPanel2.createVHDCheckBox.text=Create VHD ConfigVisualPanel2.createVHDCheckBox.text=Create VHD
NewRuleSetPanel.attributeRule.description=Search for files based on one or more attributes or metadata fields. NewRuleSetPanel.attributeRule.description=Search for files based on one or more attributes or metadata fields.
NewRuleSetPanel.attributeRule.name=Attribute NewRuleSetPanel.attributeRule.name=Attribute

View File

@ -19,12 +19,16 @@
package org.sleuthkit.autopsy.logicalimager.dsp; package org.sleuthkit.autopsy.logicalimager.dsp;
import java.io.File; import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.apache.commons.io.FileUtils;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.AddLocalFilesTask;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
@ -38,24 +42,28 @@ import org.sleuthkit.datamodel.TskCoreException;
* alert.txt and users.txt files to report - add an image data source to the * alert.txt and users.txt files to report - add an image data source to the
* case database. * case database.
*/ */
final class AddLogicalImageTask extends AddMultipleImageTask { final class AddLogicalImageTask implements Runnable {
private final static Logger logger = Logger.getLogger(AddLogicalImageTask.class.getName()); private final static Logger LOGGER = Logger.getLogger(AddLogicalImageTask.class.getName());
private final static String ALERT_TXT = "alert.txt"; //NON-NLS private final static String ALERT_TXT = "alert.txt"; //NON-NLS
private final static String USERS_TXT = "users.txt"; //NON-NLS private final static String USERS_TXT = "users.txt"; //NON-NLS
private final String deviceId;
private final String timeZone;
private final File src; private final File src;
private final File dest; private final File dest;
private final DataSourceProcessorCallback callback; private final DataSourceProcessorCallback callback;
private final DataSourceProcessorProgressMonitor progressMonitor; private final DataSourceProcessorProgressMonitor progressMonitor;
private volatile boolean cancelled;
AddLogicalImageTask(String deviceId, AddLogicalImageTask(String deviceId,
List<String> imagePaths,
String timeZone, String timeZone,
File src, File dest, File src, File dest,
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorProgressMonitor progressMonitor,
DataSourceProcessorCallback callback DataSourceProcessorCallback callback
) throws NoCurrentCaseException { ) throws NoCurrentCaseException {
super(deviceId, imagePaths, timeZone, progressMonitor, callback); this.deviceId = deviceId;
this.timeZone = timeZone;
this.src = src; this.src = src;
this.dest = dest; this.dest = dest;
this.progressMonitor = progressMonitor; this.progressMonitor = progressMonitor;
@ -71,14 +79,34 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
"AddLogicalImageTask.doneCopying=Done copying", "AddLogicalImageTask.doneCopying=Done copying",
"# {0} - src", "# {1} - dest", "AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1}", "# {0} - src", "# {1} - dest", "AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1}",
"# {0} - file", "AddLogicalImageTask.addingToReport=Adding {0} to report", "# {0} - file", "AddLogicalImageTask.addingToReport=Adding {0} to report",
"# {0} - file", "AddLogicalImageTask.doneAddingToReport=Done adding {0} to report" "# {0} - file", "AddLogicalImageTask.doneAddingToReport=Done adding {0} to report",
"AddLogicalImageTask.ingestionCancelled=Ingestion cancelled",
"# {0} - file", "AddLogicalImageTask.failToGetCanonicalPath=Fail to get canonical path for {0}",
"# {0} - sparseImageDirectory", "AddLogicalImageTask.directoryDoesNotContainSparseImage=Directory {0} does not contain any images",
"AddLogicalImageTask.noCurrentCase=No current case",
}) })
@Override @Override
public void run() { public void run() {
List<String> errorList = new ArrayList<>(); List<String> errorList = new ArrayList<>();
List<Content> emptyDataSources = new ArrayList<>(); List<Content> emptyDataSources = new ArrayList<>();
// Add the alert.txt and users.txt to the case report try {
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_copyingImageFromTo(src.toString(), dest.toString()));
FileUtils.copyDirectory(src, dest);
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneCopying());
} catch (IOException ex) {
// Copy directory failed
String msg = Bundle.AddLogicalImageTask_failedToCopyDirectory(src.toString(), dest.toString());
errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
if (cancelled) {
return;
}
// Add the alert.txt and users.txt to the case report
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingToReport(ALERT_TXT)); progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingToReport(ALERT_TXT));
String status = addReport(Paths.get(dest.toString(), ALERT_TXT), ALERT_TXT + " " + src.getName()); String status = addReport(Paths.get(dest.toString(), ALERT_TXT), ALERT_TXT + " " + src.getName());
if (status != null) { if (status != null) {
@ -97,7 +125,50 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
} }
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingToReport(USERS_TXT)); progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingToReport(USERS_TXT));
super.run(); // Get all VHD files in the dest directory
List<String> imagePaths = new ArrayList<>();
for (File f : dest.listFiles()) {
if (f.getName().endsWith(".vhd")) {
try {
imagePaths.add(f.getCanonicalPath());
} catch (IOException ex) {
String msg = Bundle.AddLogicalImageTask_failToGetCanonicalPath(f.getName());
errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
}
}
if (imagePaths.isEmpty()) {
// No VHD in src directory, try ingest directories using Logical File Set
String[] directories = dest.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return Paths.get(dir.toString(), name).toFile().isDirectory();
}
});
for (String dir : directories) {
imagePaths.add(Paths.get(dest.toString(), dir).toFile().getAbsolutePath());
}
if (imagePaths.isEmpty()) {
String msg = Bundle.AddLogicalImageTask_directoryDoesNotContainSparseImage(dest);
errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
// ingest the directories
new Thread(new AddLocalFilesTask(deviceId, null, imagePaths, progressMonitor, callback)).start();
} else {
// ingest the VHDs
try {
new Thread(new AddMultipleImageTask(deviceId, imagePaths, timeZone , progressMonitor, callback)).start();
} catch (NoCurrentCaseException ex) {
String msg = Bundle.AddLogicalImageTask_noCurrentCase();
errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
}
}
} }
/** /**
@ -121,8 +192,17 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
return null; return null;
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = Bundle.AddLogicalImageTask_failedToAddReport(reportPath.toString(), ex.getMessage()); String msg = Bundle.AddLogicalImageTask_failedToAddReport(reportPath.toString(), ex.getMessage());
logger.log(Level.SEVERE, String.format("Failed to add report %s. Reason= %s", reportPath.toString(), ex.getMessage()), ex); LOGGER.log(Level.SEVERE, String.format("Failed to add report %s. Reason= %s", reportPath.toString(), ex.getMessage()), ex);
return msg; return msg;
} }
} }
/**
* Attempts to cancel the processing of the input image files. May result in
* partial processing of the input.
*/
void cancelTask() {
LOGGER.log(Level.WARNING, "AddLogicalImageTask cancelled, processing may be incomplete"); // NON-NLS
cancelled = true;
}
} }

View File

@ -7,6 +7,8 @@ AddLogicalImageTask.addingToReport=Adding {0} to report
# {0} - src # {0} - src
# {1} - dest # {1} - dest
AddLogicalImageTask.copyingImageFromTo=Copying image from {0} to {1} AddLogicalImageTask.copyingImageFromTo=Copying image from {0} to {1}
# {0} - sparseImageDirectory
AddLogicalImageTask.directoryDoesNotContainSparseImage=Directory {0} does not contain any images
# {0} - file # {0} - file
AddLogicalImageTask.doneAddingToReport=Done adding {0} to report AddLogicalImageTask.doneAddingToReport=Done adding {0} to report
AddLogicalImageTask.doneCopying=Done copying AddLogicalImageTask.doneCopying=Done copying
@ -16,6 +18,10 @@ AddLogicalImageTask.failedToAddReport=Failed to add report {0}. Reason= {1}
# {0} - src # {0} - src
# {1} - dest # {1} - dest
AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1} AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1}
# {0} - file
AddLogicalImageTask.failToGetCanonicalPath=Fail to get canonical path for {0}
AddLogicalImageTask.ingestionCancelled=Ingestion cancelled
AddLogicalImageTask.noCurrentCase=No current case
# {0} - imageFilePath # {0} - imageFilePath
AddMultipleImageTask.adding=Adding: {0} AddMultipleImageTask.adding=Adding: {0}
# {0} - file # {0} - file
@ -39,12 +45,8 @@ AddMultipleImageTask.nonCriticalErrorAdding=Non-critical error adding {0} for de
LogicalImagerDSProcessor.dataSourceType=Autopsy Logical Imager Results LogicalImagerDSProcessor.dataSourceType=Autopsy Logical Imager Results
# {0} - directory # {0} - directory
LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists
# {0} - sparseImageDirectory
LogicalImagerDSProcessor.directoryDoesNotContainSparseImage=Directory {0} does not contain any images
# {0} - directory # {0} - directory
LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0} LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0}
# {0} - file
LogicalImagerDSProcessor.failToGetCanonicalPath=Fail to get canonical path for {0}
# {0} - imageDirPath # {0} - imageDirPath
LogicalImagerDSProcessor.imageDirPathNotFound={0} not found.\nUSB drive has been ejected. LogicalImagerDSProcessor.imageDirPathNotFound={0} not found.\nUSB drive has been ejected.
LogicalImagerDSProcessor.noCurrentCase=No current case LogicalImagerDSProcessor.noCurrentCase=No current case

View File

@ -19,8 +19,6 @@
package org.sleuthkit.autopsy.logicalimager.dsp; package org.sleuthkit.autopsy.logicalimager.dsp;
import java.io.File; import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
@ -28,11 +26,9 @@ import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.apache.commons.io.FileUtils;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders; import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.casemodule.AddLocalFilesTask;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
@ -133,10 +129,7 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
"# {0} - imageDirPath", "LogicalImagerDSProcessor.imageDirPathNotFound={0} not found.\nUSB drive has been ejected.", "# {0} - imageDirPath", "LogicalImagerDSProcessor.imageDirPathNotFound={0} not found.\nUSB drive has been ejected.",
"# {0} - directory", "LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0}", "# {0} - directory", "LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0}",
"# {0} - directory", "LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists", "# {0} - directory", "LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists",
"# {0} - file", "LogicalImagerDSProcessor.failToGetCanonicalPath=Fail to get canonical path for {0}",
"LogicalImagerDSProcessor.noCurrentCase=No current case", "LogicalImagerDSProcessor.noCurrentCase=No current case",
"# {0} - sparseImageDirectory", "LogicalImagerDSProcessor.directoryDoesNotContainSparseImage=Directory {0} does not contain any images",
}) })
@Override @Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
@ -177,64 +170,14 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
File src = imageDirPath.toFile(); File src = imageDirPath.toFile();
try { try {
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_copyingImageFromTo(src.toString(), dest.toString())); String deviceId = UUID.randomUUID().toString();
FileUtils.copyDirectory(src, dest); String timeZone = Calendar.getInstance().getTimeZone().getID();
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneCopying()); run(deviceId, timeZone, src, dest,
} catch (IOException ex) { progressMonitor, callback);
// Copy directory failed } catch (NoCurrentCaseException ex) {
String msg = Bundle.AddLogicalImageTask_failedToCopyDirectory(src.toString(), dest.toString()); String msg = Bundle.LogicalImagerDSProcessor_noCurrentCase();
errorList.add(msg); errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources); callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
// Get all VHD files in the src directory
List<String> imagePaths = new ArrayList<>();
for (File f : dest.listFiles()) {
if (f.getName().endsWith(".vhd")) {
try {
imagePaths.add(f.getCanonicalPath());
} catch (IOException ex) {
String msg = Bundle.LogicalImagerDSProcessor_failToGetCanonicalPath(f.getName());
errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
}
}
String deviceId = UUID.randomUUID().toString();
if (imagePaths.isEmpty()) {
// No VHD in src directory, try ingest directories using Logical File Set
String[] directories = dest.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return Paths.get(dir.toString(), name).toFile().isDirectory();
}
});
for (String dir : directories) {
imagePaths.add(Paths.get(dest.toString(), dir).toFile().getAbsolutePath());
}
if (imagePaths.isEmpty()) {
String msg = Bundle.LogicalImagerDSProcessor_directoryDoesNotContainSparseImage(dest);
errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
// ingest the directories
new Thread(new AddLocalFilesTask(deviceId, null, imagePaths, progressMonitor, callback)).start();
} else {
try {
String timeZone = Calendar.getInstance().getTimeZone().getID();
run(deviceId, imagePaths,
timeZone, src, dest,
progressMonitor, callback);
} catch (NoCurrentCaseException ex) {
String msg = Bundle.LogicalImagerDSProcessor_noCurrentCase();
errorList.add(msg);
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
}
} }
} }
@ -248,7 +191,6 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
* @param deviceId An ASCII-printable identifier for the device * @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is intended * associated with the data source that is intended
* to be unique across multiple cases (e.g., a UUID). * to be unique across multiple cases (e.g., a UUID).
* @param imagePaths Paths to the image files.
* @param timeZone The time zone to use when processing dates and * @param timeZone The time zone to use when processing dates and
* times for the image, obtained from * times for the image, obtained from
* java.util.TimeZone.getID. * java.util.TimeZone.getID.
@ -258,11 +200,11 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
* processing. * processing.
* @param callback Callback to call when processing is done. * @param callback Callback to call when processing is done.
*/ */
private void run(String deviceId, List<String> imagePaths, String timeZone, private void run(String deviceId, String timeZone,
File src, File dest, File src, File dest,
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback
) throws NoCurrentCaseException { ) throws NoCurrentCaseException {
addLogicalImageTask = new AddLogicalImageTask(deviceId, imagePaths, timeZone, src, dest, addLogicalImageTask = new AddLogicalImageTask(deviceId, timeZone, src, dest,
progressMonitor, callback); progressMonitor, callback);
new Thread(addLogicalImageTask).start(); new Thread(addLogicalImageTask).start();
} }