Autopsy  4.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractAction.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013 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 content 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.directorytree;
20 
21 import java.awt.Component;
22 import java.awt.event.ActionEvent;
23 import java.io.File;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.logging.Level;
28 
29 import org.openide.util.NbBundle;
31 import javax.swing.AbstractAction;
32 import javax.swing.JFileChooser;
33 import javax.swing.JOptionPane;
34 import javax.swing.SwingWorker;
35 import org.netbeans.api.progress.ProgressHandle;
36 import org.netbeans.api.progress.ProgressHandleFactory;
37 import org.openide.util.Cancellable;
38 import org.openide.util.Utilities;
42 import org.sleuthkit.datamodel.AbstractFile;
45 import org.sleuthkit.datamodel.Content;
46 import org.sleuthkit.datamodel.TskCoreException;
47 
51 public final class ExtractAction extends AbstractAction {
52 
53  private Logger logger = Logger.getLogger(ExtractAction.class.getName());
54 
55  // This class is a singleton to support multi-selection of nodes, since
56  // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
57  // node in the array returns a reference to the same action object from Node.getActions(boolean).
58  private static ExtractAction instance;
59 
60  public static synchronized ExtractAction getInstance() {
61  if (null == instance) {
62  instance = new ExtractAction();
63  }
64  return instance;
65  }
66 
67  private ExtractAction() {
68  super(NbBundle.getMessage(ExtractAction.class, "ExtractAction.title.extractFiles.text"));
69  }
70 
77  @Override
78  public void actionPerformed(ActionEvent e) {
79  Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
80  if (selectedFiles.size() > 1) {
81  extractFiles(e, selectedFiles);
82  } else if (selectedFiles.size() == 1) {
83  AbstractFile source = selectedFiles.iterator().next();
84  if (source.isDir()) {
85  extractFiles(e, selectedFiles);
86  } else {
87  extractFile(e, selectedFiles.iterator().next());
88  }
89  }
90  }
91 
98  private void extractFile(ActionEvent e, AbstractFile selectedFile) {
99  JFileChooser fileChooser = new JFileChooser();
100  fileChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory()));
101  // If there is an attribute name, change the ":". Otherwise the extracted file will be hidden
102  fileChooser.setSelectedFile(new File(FileUtil.escapeFileName(selectedFile.getName())));
103  if (fileChooser.showSaveDialog((Component) e.getSource()) == JFileChooser.APPROVE_OPTION) {
104  ArrayList<FileExtractionTask> fileExtractionTasks = new ArrayList<>();
105  fileExtractionTasks.add(new FileExtractionTask(selectedFile, fileChooser.getSelectedFile()));
106  runExtractionTasks(e, fileExtractionTasks);
107  }
108  }
109 
116  private void extractFiles(ActionEvent e, Collection<? extends AbstractFile> selectedFiles) {
117  JFileChooser folderChooser = new JFileChooser();
118  folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
119  folderChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory()));
120  if (folderChooser.showSaveDialog((Component) e.getSource()) == JFileChooser.APPROVE_OPTION) {
121  File destinationFolder = folderChooser.getSelectedFile();
122  if (!destinationFolder.exists()) {
123  try {
124  destinationFolder.mkdirs();
125  } catch (Exception ex) {
126  JOptionPane.showMessageDialog((Component) e.getSource(), NbBundle.getMessage(this.getClass(),
127  "ExtractAction.extractFiles.cantCreateFolderErr.msg"));
128  logger.log(Level.INFO, "Unable to create folder(s) for user " + destinationFolder.getAbsolutePath(), ex); //NON-NLS
129  return;
130  }
131  }
132 
133  // make a task for each file
134  ArrayList<FileExtractionTask> fileExtractionTasks = new ArrayList<>();
135  for (AbstractFile source : selectedFiles) {
136  // If there is an attribute name, change the ":". Otherwise the extracted file will be hidden
137  fileExtractionTasks.add(new FileExtractionTask(source, new File(destinationFolder, source.getId() + "-" + FileUtil.escapeFileName(source.getName()))));
138  }
139  runExtractionTasks(e, fileExtractionTasks);
140  }
141  }
142 
143  private void runExtractionTasks(ActionEvent e, ArrayList<FileExtractionTask> fileExtractionTasks) {
144 
145  // verify all of the sources and destinations are OK
146  for (Iterator<FileExtractionTask> it = fileExtractionTasks.iterator(); it.hasNext();) {
147  FileExtractionTask task = it.next();
148 
149  if (ContentUtils.isDotDirectory(task.source)) {
150  //JOptionPane.showMessageDialog((Component) e.getSource(), "Cannot extract virtual " + task.source.getName() + " directory.", "File is Virtual Directory", JOptionPane.WARNING_MESSAGE);
151  it.remove();
152  continue;
153  }
154 
155  /*
156  * @@@ Problems with this code: - does not prevent us from having
157  * multiple files with the same target name in the task list (in
158  * which case, the first ones are overwritten) Unique Id was added
159  * to set of names before calling this method to deal with that.
160  */
161  if (task.destination.exists()) {
162  if (JOptionPane.showConfirmDialog((Component) e.getSource(),
163  NbBundle.getMessage(this.getClass(), "ExtractAction.confDlg.destFileExist.msg", task.destination.getAbsolutePath()),
164  NbBundle.getMessage(this.getClass(), "ExtractAction.confDlg.destFileExist.title"),
165  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
166  if (!FileUtil.deleteFileDir(task.destination)) {
167  JOptionPane.showMessageDialog((Component) e.getSource(),
168  NbBundle.getMessage(this.getClass(), "ExtractAction.msgDlg.cantOverwriteFile.msg", task.destination.getAbsolutePath()));
169  it.remove();
170  }
171  } else {
172  it.remove();
173  }
174  }
175  }
176 
177  // launch a thread to do the work
178  if (!fileExtractionTasks.isEmpty()) {
179  try {
180  FileExtracter extracter = new FileExtracter(fileExtractionTasks);
181  extracter.execute();
182  } catch (Exception ex) {
183  logger.log(Level.WARNING, "Unable to start background file extraction thread", ex); //NON-NLS
184  }
185  } else {
187  NbBundle.getMessage(this.getClass(), "ExtractAction.notifyDlg.noFileToExtr.msg"));
188  }
189  }
190 
191  private class FileExtractionTask {
192 
193  AbstractFile source;
194  File destination;
195 
196  FileExtractionTask(AbstractFile source, File destination) {
197  this.source = source;
198  this.destination = destination;
199  }
200  }
201 
205  private class FileExtracter extends SwingWorker<Object, Void> {
206 
207  private Logger logger = Logger.getLogger(FileExtracter.class.getName());
208  private ProgressHandle progress;
209  private ArrayList<FileExtractionTask> extractionTasks;
210 
211  FileExtracter(ArrayList<FileExtractionTask> extractionTasks) {
212  this.extractionTasks = extractionTasks;
213  }
214 
215  @Override
216  protected Object doInBackground() throws Exception {
217  if (extractionTasks.isEmpty()) {
218  return null;
219  }
220 
221  // Setup progress bar.
222  final String displayName = NbBundle.getMessage(this.getClass(), "ExtractAction.progress.extracting");
223  progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
224  @Override
225  public boolean cancel() {
226  if (progress != null) {
227  progress.setDisplayName(
228  NbBundle.getMessage(this.getClass(), "ExtractAction.progress.cancellingExtraction", displayName));
229  }
230  return ExtractAction.FileExtracter.this.cancel(true);
231  }
232  });
233  progress.start();
234  progress.switchToIndeterminate();
235 
236  /*
237  * @@@ Add back in -> Causes exceptions int workUnits = 0; for
238  * (FileExtractionTask task : extractionTasks) { workUnits +=
239  * calculateProgressBarWorkUnits(task.source); }
240  * progress.switchToDeterminate(workUnits);
241  */
242  // Do the extraction tasks.
243  for (FileExtractionTask task : this.extractionTasks) {
244  // @@@ Note, we are no longer passing in progress
245  ExtractFscContentVisitor.extract(task.source, task.destination, null, this);
246  }
247 
248  return null;
249  }
250 
251  @Override
252  protected void done() {
253  boolean msgDisplayed = false;
254  try {
255  super.get();
256  } catch (Exception ex) {
257  logger.log(Level.SEVERE, "Fatal error during file extraction", ex); //NON-NLS
259  NbBundle.getMessage(this.getClass(), "ExtractAction.done.notifyMsg.extractErr", ex.getMessage()));
260  msgDisplayed = true;
261  } finally {
262  progress.finish();
263  if (!this.isCancelled() && !msgDisplayed) {
265  NbBundle.getMessage(this.getClass(), "ExtractAction.done.notifyMsg.fileExtr.text"));
266  }
267  }
268  }
269 
270  private int calculateProgressBarWorkUnits(AbstractFile file) {
271  int workUnits = 0;
272  if (file.isFile()) {
273  workUnits += file.getSize();
274  } else {
275  try {
276  for (Content child : file.getChildren()) {
277  if (child instanceof AbstractFile) {
278  workUnits += calculateProgressBarWorkUnits((AbstractFile) child);
279  }
280  }
281  } catch (TskCoreException ex) {
282  logger.log(Level.SEVERE, "Could not get children of content", ex); //NON-NLS
283  }
284  }
285  return workUnits;
286  }
287  }
288 }
static boolean deleteFileDir(File path)
Definition: FileUtil.java:87
static synchronized ExtractAction getInstance()
static< T, V > void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker< T, V > worker)
void extractFile(ActionEvent e, AbstractFile selectedFile)
static String escapeFileName(String fileName)
Definition: FileUtil.java:169
synchronized static Logger getLogger(String name)
Definition: Logger.java:166
void runExtractionTasks(ActionEvent e, ArrayList< FileExtractionTask > fileExtractionTasks)
void extractFiles(ActionEvent e, Collection<?extends AbstractFile > selectedFiles)
static boolean isDotDirectory(AbstractFile dir)

Copyright © 2012-2015 Basis Technology. Generated on: Wed Apr 6 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.