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.
ConfigVisualPanel2.promptBeforeExit.text=Prompt before exiting imager
ConfigVisualPanel2.promptBeforeExit.actionCommand=
ConfigVisualPanel2.createVHDCheckBox.toolTipText=
ConfigVisualPanel2.createVHDCheckBox.text=Create VHD
NewRuleSetPanel.attributeRule.description=Search for files based on one or more attributes or metadata fields.
NewRuleSetPanel.attributeRule.name=Attribute

View File

@ -19,12 +19,16 @@
package org.sleuthkit.autopsy.logicalimager.dsp;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.apache.commons.io.FileUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.AddLocalFilesTask;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
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
* 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 USERS_TXT = "users.txt"; //NON-NLS
private final String deviceId;
private final String timeZone;
private final File src;
private final File dest;
private final DataSourceProcessorCallback callback;
private final DataSourceProcessorProgressMonitor progressMonitor;
private volatile boolean cancelled;
AddLogicalImageTask(String deviceId,
List<String> imagePaths,
String timeZone,
File src, File dest,
DataSourceProcessorProgressMonitor progressMonitor,
DataSourceProcessorCallback callback
) throws NoCurrentCaseException {
super(deviceId, imagePaths, timeZone, progressMonitor, callback);
this.deviceId = deviceId;
this.timeZone = timeZone;
this.src = src;
this.dest = dest;
this.progressMonitor = progressMonitor;
@ -71,14 +79,34 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
"AddLogicalImageTask.doneCopying=Done copying",
"# {0} - src", "# {1} - dest", "AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1}",
"# {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
public void run() {
List<String> errorList = 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));
String status = addReport(Paths.get(dest.toString(), ALERT_TXT), ALERT_TXT + " " + src.getName());
if (status != null) {
@ -97,7 +125,50 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
}
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;
} catch (TskCoreException ex) {
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;
}
}
/**
* 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
# {1} - dest
AddLogicalImageTask.copyingImageFromTo=Copying image from {0} to {1}
# {0} - sparseImageDirectory
AddLogicalImageTask.directoryDoesNotContainSparseImage=Directory {0} does not contain any images
# {0} - file
AddLogicalImageTask.doneAddingToReport=Done adding {0} to report
AddLogicalImageTask.doneCopying=Done copying
@ -16,6 +18,10 @@ AddLogicalImageTask.failedToAddReport=Failed to add report {0}. Reason= {1}
# {0} - src
# {1} - dest
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
AddMultipleImageTask.adding=Adding: {0}
# {0} - file
@ -39,12 +45,8 @@ AddMultipleImageTask.nonCriticalErrorAdding=Non-critical error adding {0} for de
LogicalImagerDSProcessor.dataSourceType=Autopsy Logical Imager Results
# {0} - directory
LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists
# {0} - sparseImageDirectory
LogicalImagerDSProcessor.directoryDoesNotContainSparseImage=Directory {0} does not contain any images
# {0} - directory
LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0}
# {0} - file
LogicalImagerDSProcessor.failToGetCanonicalPath=Fail to get canonical path for {0}
# {0} - imageDirPath
LogicalImagerDSProcessor.imageDirPathNotFound={0} not found.\nUSB drive has been ejected.
LogicalImagerDSProcessor.noCurrentCase=No current case

View File

@ -19,8 +19,6 @@
package org.sleuthkit.autopsy.logicalimager.dsp;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@ -28,11 +26,9 @@ import java.util.Calendar;
import java.util.List;
import java.util.UUID;
import javax.swing.JPanel;
import org.apache.commons.io.FileUtils;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.casemodule.AddLocalFilesTask;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
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} - directory", "LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0}",
"# {0} - directory", "LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists",
"# {0} - file", "LogicalImagerDSProcessor.failToGetCanonicalPath=Fail to get canonical path for {0}",
"LogicalImagerDSProcessor.noCurrentCase=No current case",
"# {0} - sparseImageDirectory", "LogicalImagerDSProcessor.directoryDoesNotContainSparseImage=Directory {0} does not contain any images",
})
@Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
@ -177,64 +170,14 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
File src = imageDirPath.toFile();
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());
String deviceId = UUID.randomUUID().toString();
String timeZone = Calendar.getInstance().getTimeZone().getID();
run(deviceId, timeZone, src, dest,
progressMonitor, callback);
} catch (NoCurrentCaseException ex) {
String msg = Bundle.LogicalImagerDSProcessor_noCurrentCase();
errorList.add(msg);
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
* associated with the data source that is intended
* 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
* times for the image, obtained from
* java.util.TimeZone.getID.
@ -258,11 +200,11 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
* processing.
* @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,
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback
) throws NoCurrentCaseException {
addLogicalImageTask = new AddLogicalImageTask(deviceId, imagePaths, timeZone, src, dest,
addLogicalImageTask = new AddLogicalImageTask(deviceId, timeZone, src, dest,
progressMonitor, callback);
new Thread(addLogicalImageTask).start();
}