Autopsy  4.11.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AddMultipleImageTask.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013-2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.logicalimager.dsp;
20 
21 import java.nio.file.Paths;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.logging.Level;
25 import org.openide.util.NbBundle.Messages;
33 import org.sleuthkit.datamodel.AbstractFile;
34 import org.sleuthkit.datamodel.Content;
35 import org.sleuthkit.datamodel.Image;
36 import org.sleuthkit.datamodel.LocalFilesDataSource;
37 import org.sleuthkit.datamodel.SleuthkitCase;
38 import org.sleuthkit.datamodel.SleuthkitJNI;
39 import org.sleuthkit.datamodel.TskCoreException;
40 import org.sleuthkit.datamodel.TskDataException;
41 
47 @Messages({
48  "AddMultipleImageTask.fsTypeUnknownErr=Cannot determine file system type"
49 })
50 class AddMultipleImageTask implements Runnable {
51 
52  private static final Logger LOGGER = Logger.getLogger(AddMultipleImageTask.class.getName());
53  public static final String TSK_FS_TYPE_UNKNOWN_ERR_MSG = Bundle.AddMultipleImageTask_fsTypeUnknownErr();
54  private final String deviceId;
55  private final List<String> imageFilePaths;
56  private final String timeZone;
57  private final DataSourceProcessorProgressMonitor progressMonitor;
58  private final DataSourceProcessorCallback callback;
59  private final Case currentCase;
60  private boolean criticalErrorOccurred;
61  private volatile boolean cancelled;
62 
81  @Messages({
82  "# {0} - file", "AddMultipleImageTask.addingFileAsLogicalFile=Adding: {0} as logical file",
83  "# {0} - deviceId", "# {1} - exceptionMessage",
84  "AddMultipleImageTask.errorAddingImgWithoutFileSystem=Error adding images without file systems for device %s: %s",
85  })
86  AddMultipleImageTask(String deviceId, List<String> imageFilePaths, String timeZone,
87  DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) throws NoCurrentCaseException {
88  this.deviceId = deviceId;
89  this.imageFilePaths = imageFilePaths;
90  this.timeZone = timeZone;
91  this.callback = callback;
92  this.progressMonitor = progressMonitor;
93  currentCase = Case.getCurrentCaseThrows();
94  }
95 
96  @Override
97  public void run() {
98  /*
99  * Try to add the input image files as images.
100  */
101  List<Content> newDataSources = new ArrayList<>();
102  List<String> localFileDataSourcePaths = new ArrayList<>();
103  List<String> errorMessages = new ArrayList<>();
104  currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock();
105  try {
106  progressMonitor.setIndeterminate(true);
107  for (String imageFilePath : imageFilePaths) {
108  if (!cancelled) {
109  addImageToCase(imageFilePath, newDataSources, localFileDataSourcePaths, errorMessages);
110  }
111  }
112  } finally {
113  currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock();
114  }
115 
116  /*
117  * Try to add any input image files that did not have file systems as a
118  * single local/logical files set with the device id as the root virtual
119  * directory name.
120  */
121  if (!cancelled && !localFileDataSourcePaths.isEmpty()) {
122  FileManager fileManager = currentCase.getServices().getFileManager();
123  FileManager.FileAddProgressUpdater progressUpdater = (final AbstractFile newFile) -> {
124  progressMonitor.setProgressText(Bundle.AddMultipleImageTask_addingFileAsLogicalFile(Paths.get(newFile.getParentPath(), newFile.getName())));
125  };
126  try {
127  LocalFilesDataSource localFilesDataSource = fileManager.addLocalFilesDataSource(deviceId, "", timeZone, localFileDataSourcePaths, progressUpdater);
128  newDataSources.add(localFilesDataSource);
129  } catch (TskCoreException | TskDataException ex) {
130  errorMessages.add(Bundle.AddMultipleImageTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage()));
131  criticalErrorOccurred = true;
132  }
133  }
134 
135  /*
136  * This appears to be the best that can be done to indicate completion
137  * with the DataSourceProcessorProgressMonitor in its current form.
138  */
139  progressMonitor.setProgress(0);
140  progressMonitor.setProgress(100);
141 
142  /*
143  * Pass the results back via the callback.
144  */
145  DataSourceProcessorResult result;
146  if (criticalErrorOccurred) {
147  result = DataSourceProcessorResult.CRITICAL_ERRORS;
148  } else if (!errorMessages.isEmpty()) {
149  result = DataSourceProcessorResult.NONCRITICAL_ERRORS;
150  } else {
151  result = DataSourceProcessorResult.NO_ERRORS;
152  }
153  callback.done(result, errorMessages, newDataSources);
154  criticalErrorOccurred = false;
155  }
156 
161  void cancelTask() {
162  LOGGER.log(Level.WARNING, "AddMultipleImageTask cancelled, processing may be incomplete"); // NON-NLS
163  cancelled = true;
164  }
165 
183  @Messages({
184  "# {0} - imageFilePath", "AddMultipleImageTask.adding=Adding: {0}",
185  "# {0} - imageFilePath", "# {1} - deviceId", "# {2} - exceptionMessage", "AddMultipleImageTask.criticalErrorAdding=Critical error adding {0} for device {1}: {2}",
186  "# {0} - imageFilePath", "# {1} - deviceId", "# {2} - exceptionMessage", "AddMultipleImageTask.criticalErrorReverting=Critical error reverting add image process for {0} for device {1}: {2}",
187  "# {0} - imageFilePath", "# {1} - deviceId", "# {2} - exceptionMessage", "AddMultipleImageTask.nonCriticalErrorAdding=Non-critical error adding {0} for device {1}: {2}",
188  })
189  private void addImageToCase(String imageFilePath, List<Content> newDataSources, List<String> localFileDataSourcePaths, List<String> errorMessages) {
190  /*
191  * Try to add the image to the case database as a data source.
192  */
193  progressMonitor.setProgressText(Bundle.AddMultipleImageTask_adding(imageFilePath));
194  SleuthkitCase caseDatabase = currentCase.getSleuthkitCase();
195  SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess = caseDatabase.makeAddImageProcess(timeZone, false, false, "");
196  try {
197  addImageProcess.run(deviceId, new String[]{imageFilePath});
198  } catch (TskCoreException ex) {
199  if (ex.getMessage().contains(TSK_FS_TYPE_UNKNOWN_ERR_MSG)) {
200  /*
201  * If Sleuth Kit failed to add the image because it did not find
202  * a file system, save the image path so it can be added to the
203  * case as part of a local/logical files data source. All other
204  * errors are critical.
205  */
206  localFileDataSourcePaths.add(imageFilePath);
207  } else {
208  errorMessages.add(Bundle.AddMultipleImageTask_criticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
209  criticalErrorOccurred = true;
210  }
211  /*
212  * Either way, the add image process needs to be reverted.
213  */
214  try {
215  addImageProcess.revert();
216  } catch (TskCoreException e) {
217  errorMessages.add(Bundle.AddMultipleImageTask_criticalErrorReverting(imageFilePath, deviceId, e.getLocalizedMessage()));
218  criticalErrorOccurred = true;
219  }
220  return;
221  } catch (TskDataException ex) {
222  errorMessages.add(Bundle.AddMultipleImageTask_nonCriticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
223  }
224 
225  /*
226  * Try to commit the results of the add image process, retrieve the new
227  * image from the case database, and add it to the list of new data
228  * sources to be returned via the callback.
229  */
230  try {
231  long imageId = addImageProcess.commit();
232  Image dataSource = caseDatabase.getImageById(imageId);
233  newDataSources.add(dataSource);
234 
235  /*
236  * Verify the size of the new image. Note that it may not be what is
237  * expected, but at least part of it was added to the case.
238  */
239  String verificationError = dataSource.verifyImageSize();
240  if (!verificationError.isEmpty()) {
241  errorMessages.add(Bundle.AddMultipleImageTask_nonCriticalErrorAdding(imageFilePath, deviceId, verificationError));
242  }
243  } catch (TskCoreException ex) {
244  /*
245  * The add image process commit failed or querying the case database
246  * for the newly added image failed. Either way, this is a critical
247  * error.
248  */
249  errorMessages.add(Bundle.AddMultipleImageTask_criticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
250  criticalErrorOccurred = true;
251  }
252  }
253 
254 }

Copyright © 2012-2018 Basis Technology. Generated on: Fri Jun 21 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.