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;
42 class AddImageTask
implements Runnable {
44 private final Logger logger = Logger.getLogger(AddImageTask.class.getName());
45 private final String deviceId;
46 private final String imagePath;
47 private final int sectorSize;
48 private final String timeZone;
49 private final ImageWriterSettings imageWriterSettings;
50 private final boolean ignoreFatOrphanFiles;
51 private final String md5;
52 private final String sha1;
53 private final String sha256;
54 private final DataSourceProcessorProgressMonitor progressMonitor;
55 private final DataSourceProcessorCallback callback;
56 private boolean criticalErrorOccurred;
69 private final Object tskAddImageProcessLock;
70 @GuardedBy(
"tskAddImageProcessLock")
71 private
boolean tskAddImageProcessStopped;
72 private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess;
98 AddImageTask(String deviceId, String imagePath,
int sectorSize, String timeZone,
boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, ImageWriterSettings imageWriterSettings,
99 DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
100 this.deviceId = deviceId;
101 this.imagePath = imagePath;
102 this.sectorSize = sectorSize;
103 this.timeZone = timeZone;
104 this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
107 this.sha256 = sha256;
108 this.imageWriterSettings = imageWriterSettings;
109 this.callback = callback;
110 this.progressMonitor = progressMonitor;
111 tskAddImageProcessLock =
new Object();
121 currentCase = Case.getCurrentCaseThrows();
122 }
catch (NoCurrentCaseException ex) {
123 logger.log(Level.SEVERE, String.format(
"Failed to add image data source at %s, no current case", imagePath), ex);
126 progressMonitor.setIndeterminate(
true);
127 progressMonitor.setProgress(0);
128 String imageWriterPath =
"";
129 if (imageWriterSettings != null) {
130 imageWriterPath = imageWriterSettings.getPath();
132 List<String> errorMessages =
new ArrayList<>();
133 List<Content> newDataSources =
new ArrayList<>();
135 synchronized (tskAddImageProcessLock) {
136 if (!tskAddImageProcessStopped) {
137 tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone,
true, ignoreFatOrphanFiles, imageWriterPath);
142 Thread progressUpdateThread =
new Thread(
new ProgressUpdater(progressMonitor, tskAddImageProcess));
143 progressUpdateThread.start();
144 runAddImageProcess(errorMessages);
145 progressUpdateThread.interrupt();
146 commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources);
147 progressMonitor.setProgress(100);
149 DataSourceProcessorCallback.DataSourceProcessorResult result;
150 if (criticalErrorOccurred) {
151 result = DataSourceProcessorResult.CRITICAL_ERRORS;
152 }
else if (!errorMessages.isEmpty()) {
153 result = DataSourceProcessorResult.NONCRITICAL_ERRORS;
155 result = DataSourceProcessorResult.NO_ERRORS;
157 callback.done(result, errorMessages, newDataSources);
164 public void cancelTask() {
165 synchronized (tskAddImageProcessLock) {
166 tskAddImageProcessStopped =
true;
167 if (null != tskAddImageProcess) {
177 tskAddImageProcess.stop();
179 }
catch (TskCoreException ex) {
180 logger.log(Level.SEVERE, String.format(
"Error cancelling adding image %s to the case database", imagePath), ex);
192 private void runAddImageProcess(List<String> errorMessages) {
194 tskAddImageProcess.run(deviceId,
new String[]{imagePath}, sectorSize);
195 }
catch (TskCoreException ex) {
196 logger.log(Level.SEVERE, String.format(
"Critical error occurred adding image %s", imagePath), ex);
197 criticalErrorOccurred =
true;
198 errorMessages.add(ex.getMessage());
199 }
catch (TskDataException ex) {
200 logger.log(Level.WARNING, String.format(
"Non-critical error occurred adding image %s", imagePath), ex);
201 errorMessages.add(ex.getMessage());
219 private void commitOrRevertAddImageProcess(Case currentCase, List<String> errorMessages, List<Content> newDataSources) {
220 synchronized (tskAddImageProcessLock) {
221 if (tskAddImageProcessStopped || criticalErrorOccurred) {
223 tskAddImageProcess.revert();
224 }
catch (TskCoreException ex) {
225 logger.log(Level.SEVERE, String.format(
"Error reverting after adding image %s to the case database", imagePath), ex);
226 errorMessages.add(ex.getMessage());
227 criticalErrorOccurred =
true;
231 long imageId = tskAddImageProcess.commit();
233 Image newImage = currentCase.getSleuthkitCase().getImageById(imageId);
234 String verificationError = newImage.verifyImageSize();
235 if (!verificationError.isEmpty()) {
236 errorMessages.add(verificationError);
238 if (imageWriterSettings != null) {
239 ImageWriterService.createImageWriter(imageId, imageWriterSettings);
241 newDataSources.add(newImage);
242 if (!StringUtils.isBlank(md5)) {
244 newImage.setMD5(md5);
245 }
catch (TskCoreException ex) {
246 logger.log(Level.SEVERE, String.format(
"Failed to add MD5 hash for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
247 errorMessages.add(ex.getMessage());
248 criticalErrorOccurred =
true;
249 }
catch (TskDataException ignored) {
257 if (!StringUtils.isBlank(sha1)) {
259 newImage.setSha1(sha1);
260 }
catch (TskCoreException ex) {
261 logger.log(Level.SEVERE, String.format(
"Failed to add SHA1 hash for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
262 errorMessages.add(ex.getMessage());
263 criticalErrorOccurred =
true;
264 }
catch (TskDataException ignored) {
272 if (!StringUtils.isBlank(sha256)) {
274 newImage.setSha256(sha256);
275 }
catch (TskCoreException ex) {
276 logger.log(Level.SEVERE, String.format(
"Failed to add SHA256 for image data source %s (objId=%d)", newImage.getName(), newImage.getId()), ex);
277 errorMessages.add(ex.getMessage());
278 criticalErrorOccurred =
true;
279 }
catch (TskDataException ignored) {
288 String errorMessage = String.format(
"Error commiting after adding image %s to the case database, no object id returned", imagePath);
289 logger.log(Level.SEVERE, errorMessage);
290 errorMessages.add(errorMessage);
291 criticalErrorOccurred =
true;
293 }
catch (TskCoreException ex) {
294 logger.log(Level.SEVERE, String.format(
"Error committing adding image %s to the case database", imagePath), ex);
295 errorMessages.add(ex.getMessage());
296 criticalErrorOccurred =
true;
330 while (!Thread.currentThread().isInterrupted()) {
332 if (currDir != null) {
333 if (!currDir.isEmpty()) {
335 NbBundle.getMessage(
this.getClass(),
"AddImageTask.run.progress.adding",
350 }
catch (InterruptedException expected) {
void setProgressText(String text)
final SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess
final DataSourceProcessorProgressMonitor progressMonitor