19 package org.sleuthkit.autopsy.casemodule;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.logging.Level;
24 import javax.annotation.concurrent.GuardedBy;
25 import org.apache.commons.lang3.StringUtils;
26 import org.openide.util.NbBundle;
44 class AddImageTask
implements Runnable {
46 private final Logger logger = Logger.getLogger(AddImageTask.class.getName());
47 private final ImageDetails imageDetails;
48 private final DataSourceProcessorProgressMonitor progressMonitor;
49 private final AddDataSourceCallbacks addDataSourceCallbacks;
50 private final AddImageTaskCallback addImageTaskCallback;
51 private boolean criticalErrorOccurred;
64 private final Object tskAddImageProcessLock;
65 @GuardedBy(
"tskAddImageProcessLock")
66 private
boolean tskAddImageProcessStopped;
67 private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess;
78 AddImageTask(ImageDetails imageDetails, DataSourceProcessorProgressMonitor progressMonitor, AddDataSourceCallbacks addDataSourceCallbacks,
79 AddImageTaskCallback addImageTaskCallback) {
80 this.imageDetails = imageDetails;
81 this.addDataSourceCallbacks = addDataSourceCallbacks;
82 this.addImageTaskCallback = addImageTaskCallback;
83 this.progressMonitor = progressMonitor;
84 tskAddImageProcessLock =
new Object();
94 currentCase = Case.getCurrentCaseThrows();
95 }
catch (NoCurrentCaseException ex) {
96 logger.log(Level.SEVERE, String.format(
"Failed to start AddImageTask for %s, no current case", imageDetails.getImagePath()), ex);
99 progressMonitor.setIndeterminate(
true);
100 progressMonitor.setProgress(0);
101 String imageWriterPath =
"";
102 if (imageDetails.imageWriterSettings != null) {
103 imageWriterPath = imageDetails.imageWriterSettings.getPath();
105 List<String> errorMessages =
new ArrayList<>();
106 List<Content> newDataSources =
new ArrayList<>();
108 synchronized (tskAddImageProcessLock) {
109 if (!tskAddImageProcessStopped) {
110 tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(imageDetails.timeZone,
true, imageDetails.ignoreFatOrphanFiles, imageWriterPath);
115 Thread progressUpdateThread =
new Thread(
new ProgressUpdater(progressMonitor, tskAddImageProcess));
116 progressUpdateThread.start();
117 runAddImageProcess(errorMessages);
118 progressUpdateThread.interrupt();
119 finishAddImageProcess(errorMessages, newDataSources);
120 progressMonitor.setProgress(100);
122 DataSourceProcessorCallback.DataSourceProcessorResult result;
123 if (criticalErrorOccurred) {
124 result = DataSourceProcessorResult.CRITICAL_ERRORS;
125 }
else if (!errorMessages.isEmpty()) {
126 result = DataSourceProcessorResult.NONCRITICAL_ERRORS;
128 result = DataSourceProcessorResult.NO_ERRORS;
130 addImageTaskCallback.onCompleted(result, errorMessages, newDataSources);
137 public void cancelTask() {
138 synchronized (tskAddImageProcessLock) {
139 tskAddImageProcessStopped =
true;
140 if (null != tskAddImageProcess) {
150 tskAddImageProcess.stop();
152 }
catch (TskCoreException ex) {
153 logger.log(Level.SEVERE, String.format(
"Error cancelling adding image %s to the case database", imageDetails.getImagePath()), ex);
165 private void runAddImageProcess(List<String> errorMessages) {
167 tskAddImageProcess.run(imageDetails.deviceId, imageDetails.image, imageDetails.sectorSize,
this.addDataSourceCallbacks);
168 }
catch (TskCoreException ex) {
169 logger.log(Level.SEVERE, String.format(
"Critical error occurred adding image %s", imageDetails.getImagePath()), ex);
170 criticalErrorOccurred =
true;
171 errorMessages.add(ex.getMessage());
172 }
catch (TskDataException ex) {
173 logger.log(Level.WARNING, String.format(
"Non-critical error occurred adding image %s", imageDetails.getImagePath()), ex);
174 errorMessages.add(ex.getMessage());
191 private void finishAddImageProcess(List<String> errorMessages, List<Content> newDataSources) {
192 synchronized (tskAddImageProcessLock) {
193 Image newImage = imageDetails.image;
194 String verificationError = newImage.verifyImageSize();
195 if (!verificationError.isEmpty()) {
196 errorMessages.add(verificationError);
198 if (imageDetails.imageWriterSettings != null) {
199 ImageWriterService.createImageWriter(newImage.getId(), imageDetails.imageWriterSettings);
201 newDataSources.add(newImage);
204 if (tskAddImageProcessStopped) {
208 if (!StringUtils.isBlank(imageDetails.md5)) {
210 newImage.setMD5(imageDetails.md5);
211 }
catch (TskCoreException ex) {
212 logger.log(Level.SEVERE, String.format(
"Failed to add MD5 hash for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
213 errorMessages.add(ex.getMessage());
214 criticalErrorOccurred =
true;
215 }
catch (TskDataException ignored) {
223 if (!StringUtils.isBlank(imageDetails.sha1)) {
225 newImage.setSha1(imageDetails.sha1);
226 }
catch (TskCoreException ex) {
227 logger.log(Level.SEVERE, String.format(
"Failed to add SHA1 hash for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
228 errorMessages.add(ex.getMessage());
229 criticalErrorOccurred =
true;
230 }
catch (TskDataException ignored) {
238 if (!StringUtils.isBlank(imageDetails.sha256)) {
240 newImage.setSha256(imageDetails.sha256);
241 }
catch (TskCoreException ex) {
242 logger.log(Level.SEVERE, String.format(
"Failed to add SHA256 for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
243 errorMessages.add(ex.getMessage());
244 criticalErrorOccurred =
true;
245 }
catch (TskDataException ignored) {
284 while (!Thread.currentThread().isInterrupted()) {
286 if (currDir != null) {
287 if (!currDir.isEmpty()) {
289 NbBundle.getMessage(
this.getClass(),
"AddImageTask.run.progress.adding",
304 }
catch (InterruptedException expected) {
312 static class ImageDetails {
317 boolean ignoreFatOrphanFiles;
323 ImageDetails(String deviceId, Image image,
int sectorSize, String timeZone,
boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256,
ImageWriterSettings imageWriterSettings) {
324 this.deviceId = deviceId;
326 this.sectorSize = sectorSize;
327 this.timeZone = timeZone;
328 this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
331 this.sha256 = sha256;
332 this.imageWriterSettings = imageWriterSettings;
335 String getImagePath() {
336 if (image.getPaths().length > 0) {
337 return image.getPaths()[0];
339 return "Unknown data source path";
void setProgressText(String text)
final SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess
final DataSourceProcessorProgressMonitor progressMonitor