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;
43 class AddImageTask
implements Runnable {
45 private final Logger logger = Logger.getLogger(AddImageTask.class.getName());
46 private final ImageDetails imageDetails;
47 private final DataSourceProcessorProgressMonitor progressMonitor;
48 private final AddDataSourceCallbacks addDataSourceCallbacks;
49 private final AddImageTaskCallback addImageTaskCallback;
50 private boolean criticalErrorOccurred;
63 private final Object tskAddImageProcessLock;
64 @GuardedBy(
"tskAddImageProcessLock")
65 private
boolean tskAddImageProcessStopped;
66 private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess;
77 AddImageTask(ImageDetails imageDetails, DataSourceProcessorProgressMonitor progressMonitor, AddDataSourceCallbacks addDataSourceCallbacks,
78 AddImageTaskCallback addImageTaskCallback) {
79 this.imageDetails = imageDetails;
80 this.addDataSourceCallbacks = addDataSourceCallbacks;
81 this.addImageTaskCallback = addImageTaskCallback;
82 this.progressMonitor = progressMonitor;
83 tskAddImageProcessLock =
new Object();
93 currentCase = Case.getCurrentCaseThrows();
94 }
catch (NoCurrentCaseException ex) {
95 logger.log(Level.SEVERE, String.format(
"Failed to start AddImageTask for %s, no current case", imageDetails.getImagePath()), ex);
98 progressMonitor.setIndeterminate(
true);
99 progressMonitor.setProgress(0);
100 String imageWriterPath =
"";
101 if (imageDetails.imageWriterSettings != null) {
102 imageWriterPath = imageDetails.imageWriterSettings.getPath();
104 List<String> errorMessages =
new ArrayList<>();
105 List<Content> newDataSources =
new ArrayList<>();
107 synchronized (tskAddImageProcessLock) {
108 if (!tskAddImageProcessStopped) {
109 tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(imageDetails.timeZone,
true, imageDetails.ignoreFatOrphanFiles, imageWriterPath);
114 Thread progressUpdateThread =
new Thread(
new ProgressUpdater(progressMonitor, tskAddImageProcess));
115 progressUpdateThread.start();
116 runAddImageProcess(errorMessages);
117 progressUpdateThread.interrupt();
118 finishAddImageProcess(errorMessages, newDataSources);
119 progressMonitor.setProgress(100);
121 DataSourceProcessorCallback.DataSourceProcessorResult result;
122 if (criticalErrorOccurred) {
123 result = DataSourceProcessorResult.CRITICAL_ERRORS;
124 }
else if (!errorMessages.isEmpty()) {
125 result = DataSourceProcessorResult.NONCRITICAL_ERRORS;
127 result = DataSourceProcessorResult.NO_ERRORS;
129 addImageTaskCallback.onCompleted(result, errorMessages, newDataSources);
136 public void cancelTask() {
137 synchronized (tskAddImageProcessLock) {
138 tskAddImageProcessStopped =
true;
139 if (null != tskAddImageProcess) {
149 tskAddImageProcess.stop();
151 }
catch (TskCoreException ex) {
152 logger.log(Level.SEVERE, String.format(
"Error cancelling adding image %s to the case database", imageDetails.getImagePath()), ex);
164 private void runAddImageProcess(List<String> errorMessages) {
166 tskAddImageProcess.run(imageDetails.deviceId, imageDetails.image, imageDetails.sectorSize,
this.addDataSourceCallbacks);
167 }
catch (TskCoreException ex) {
168 logger.log(Level.SEVERE, String.format(
"Critical error occurred adding image %s", imageDetails.getImagePath()), ex);
169 criticalErrorOccurred =
true;
170 errorMessages.add(ex.getMessage());
171 }
catch (TskDataException ex) {
172 logger.log(Level.WARNING, String.format(
"Non-critical error occurred adding image %s", imageDetails.getImagePath()), ex);
173 errorMessages.add(ex.getMessage());
190 private void finishAddImageProcess(List<String> errorMessages, List<Content> newDataSources) {
191 synchronized (tskAddImageProcessLock) {
192 Image newImage = imageDetails.image;
193 String verificationError = newImage.verifyImageSize();
194 if (!verificationError.isEmpty()) {
195 errorMessages.add(verificationError);
197 if (imageDetails.imageWriterSettings != null) {
198 ImageWriterService.createImageWriter(newImage.getId(), imageDetails.imageWriterSettings);
200 newDataSources.add(newImage);
203 if (tskAddImageProcessStopped) {
207 if (!StringUtils.isBlank(imageDetails.md5)) {
209 newImage.setMD5(imageDetails.md5);
210 }
catch (TskCoreException ex) {
211 logger.log(Level.SEVERE, String.format(
"Failed to add MD5 hash for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
212 errorMessages.add(ex.getMessage());
213 criticalErrorOccurred =
true;
214 }
catch (TskDataException ignored) {
222 if (!StringUtils.isBlank(imageDetails.sha1)) {
224 newImage.setSha1(imageDetails.sha1);
225 }
catch (TskCoreException ex) {
226 logger.log(Level.SEVERE, String.format(
"Failed to add SHA1 hash for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
227 errorMessages.add(ex.getMessage());
228 criticalErrorOccurred =
true;
229 }
catch (TskDataException ignored) {
237 if (!StringUtils.isBlank(imageDetails.sha256)) {
239 newImage.setSha256(imageDetails.sha256);
240 }
catch (TskCoreException ex) {
241 logger.log(Level.SEVERE, String.format(
"Failed to add SHA256 for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
242 errorMessages.add(ex.getMessage());
243 criticalErrorOccurred =
true;
244 }
catch (TskDataException ignored) {
283 while (!Thread.currentThread().isInterrupted()) {
285 if (currDir != null) {
286 if (!currDir.isEmpty()) {
288 NbBundle.getMessage(
this.getClass(),
"AddImageTask.run.progress.adding",
303 }
catch (InterruptedException expected) {
311 static class ImageDetails {
316 boolean ignoreFatOrphanFiles;
322 ImageDetails(String deviceId, Image image,
int sectorSize, String timeZone,
boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256,
ImageWriterSettings imageWriterSettings) {
323 this.deviceId = deviceId;
325 this.sectorSize = sectorSize;
326 this.timeZone = timeZone;
327 this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
330 this.sha256 = sha256;
331 this.imageWriterSettings = imageWriterSettings;
334 String getImagePath() {
335 if (image.getPaths().length > 0) {
336 return image.getPaths()[0];
338 return "Unknown data source path";
void setProgressText(String text)
final SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess
final DataSourceProcessorProgressMonitor progressMonitor