Autopsy  3.1
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.concurrent.CancellationException;
28 import java.util.concurrent.ExecutionException;
29 import java.util.logging.Level;
30 
31 import org.openide.util.NbBundle;
33 import javax.swing.AbstractAction;
34 import javax.swing.JFileChooser;
35 import javax.swing.JOptionPane;
36 import javax.swing.SwingWorker;
37 import org.netbeans.api.progress.ProgressHandle;
38 import org.netbeans.api.progress.ProgressHandleFactory;
39 import org.openide.util.Cancellable;
40 import org.openide.util.Utilities;
49 
53 public final class ExtractAction extends AbstractAction {
54  private Logger logger = Logger.getLogger(ExtractAction.class.getName());
55 
56  // This class is a singleton to support multi-selection of nodes, since
57  // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
58  // node in the array returns a reference to the same action object from Node.getActions(boolean).
59  private static ExtractAction instance;
60 
61  public static synchronized ExtractAction getInstance() {
62  if (null == instance) {
63  instance = new ExtractAction();
64  }
65  return instance;
66  }
67 
68  private ExtractAction() {
69  super(NbBundle.getMessage(ExtractAction.class, "ExtractAction.title.extractFiles.text"));
70  }
71 
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  }
83  else if (selectedFiles.size() == 1) {
84  AbstractFile source = selectedFiles.iterator().next();
85  if (source.isDir()) {
86  extractFiles(e, selectedFiles);
87  }
88  else {
89  extractFile(e, selectedFiles.iterator().next());
90  }
91  }
92  }
93 
99  private void extractFile(ActionEvent e, AbstractFile selectedFile) {
100  JFileChooser fileChooser = new JFileChooser();
101  fileChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory()));
102  // If there is an attribute name, change the ":". Otherwise the extracted file will be hidden
103  fileChooser.setSelectedFile(new File(selectedFile.getName().replace(':', '_')));
104  if (fileChooser.showSaveDialog((Component)e.getSource()) == JFileChooser.APPROVE_OPTION) {
105  ArrayList<FileExtractionTask> fileExtractionTasks = new ArrayList<>();
106  fileExtractionTasks.add(new FileExtractionTask(selectedFile, fileChooser.getSelectedFile()));
107  runExtractionTasks(e, fileExtractionTasks);
108  }
109  }
110 
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  }
126  catch (Exception ex) {
127  JOptionPane.showMessageDialog((Component) e.getSource(), NbBundle.getMessage(this.getClass(),
128  "ExtractAction.extractFiles.cantCreateFolderErr.msg"));
129  logger.log(Level.INFO, "Unable to create folder(s) for user " + destinationFolder.getAbsolutePath(), ex); //NON-NLS
130  return;
131  }
132  }
133 
134  // make a task for each file
135  ArrayList<FileExtractionTask> fileExtractionTasks = new ArrayList<>();
136  for (AbstractFile source : selectedFiles) {
137  // If there is an attribute name, change the ":". Otherwise the extracted file will be hidden
138  fileExtractionTasks.add(new FileExtractionTask(source, new File(destinationFolder, source.getId() + "-" + source.getName().replace(':', '_'))));
139  }
140  runExtractionTasks(e, fileExtractionTasks);
141  }
142  }
143 
144  private void runExtractionTasks(ActionEvent e, ArrayList<FileExtractionTask> fileExtractionTasks) {
145 
146  // verify all of the sources and destinations are OK
147  for (Iterator<FileExtractionTask> it = fileExtractionTasks.iterator(); it.hasNext(); ) {
148  FileExtractionTask task = it.next();
149 
150  if (ContentUtils.isDotDirectory(task.source)) {
151  //JOptionPane.showMessageDialog((Component) e.getSource(), "Cannot extract virtual " + task.source.getName() + " directory.", "File is Virtual Directory", JOptionPane.WARNING_MESSAGE);
152  it.remove();
153  continue;
154  }
155 
156  /*
157  * @@@ Problems with this code:
158  * - does not prevent us from having multiple files with the same target name in the task list (in which case, the first ones are overwritten)
159  * Unique Id was added 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  }
172  else {
173  it.remove();
174  }
175  }
176  }
177 
178  // launch a thread to do the work
179  if (!fileExtractionTasks.isEmpty()) {
180  try {
181  FileExtracter extracter = new FileExtracter(fileExtractionTasks);
182  extracter.execute();
183  }
184  catch (Exception ex) {
185  logger.log(Level.WARNING, "Unable to start background file extraction thread", ex); //NON-NLS
186  }
187  }
188  else {
190  NbBundle.getMessage(this.getClass(), "ExtractAction.notifyDlg.noFileToExtr.msg"));
191  }
192  }
193 
194  private class FileExtractionTask {
195  AbstractFile source;
196  File destination;
197 
198  FileExtractionTask(AbstractFile source, File destination) {
199  this.source = source;
200  this.destination = destination;
201  }
202  }
203 
207  private class FileExtracter extends SwingWorker<Object,Void> {
208  private Logger logger = Logger.getLogger(FileExtracter.class.getName());
209  private ProgressHandle progress;
210  private ArrayList<FileExtractionTask> extractionTasks;
211 
212  FileExtracter(ArrayList<FileExtractionTask> extractionTasks) {
213  this.extractionTasks = extractionTasks;
214  }
215 
216  @Override
217  protected Object doInBackground() throws Exception {
218  if (extractionTasks.isEmpty()) {
219  return null;
220  }
221 
222  // Setup progress bar.
223  final String displayName = NbBundle.getMessage(this.getClass(), "ExtractAction.progress.extracting");
224  progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
225  @Override
226  public boolean cancel() {
227  if (progress != null)
228  progress.setDisplayName(
229  NbBundle.getMessage(this.getClass(), "ExtractAction.progress.cancellingExtraction", displayName));
230  return ExtractAction.FileExtracter.this.cancel(true);
231  }
232  });
233  progress.start();
234  progress.switchToIndeterminate();
235 
236  /* @@@ Add back in -> Causes exceptions
237  int workUnits = 0;
238  for (FileExtractionTask task : extractionTasks) {
239  workUnits += calculateProgressBarWorkUnits(task.source);
240  }
241  progress.switchToDeterminate(workUnits);
242  */
243 
244  // Do the extraction tasks.
245  for (FileExtractionTask task : this.extractionTasks) {
246  // @@@ Note, we are no longer passing in progress
247  ExtractFscContentVisitor.extract(task.source, task.destination, null, this);
248  }
249 
250  return null;
251  }
252 
253  @Override
254  protected void done() {
255  boolean msgDisplayed = false;
256  try {
257  super.get();
258  }
259  catch (Exception ex) {
260  logger.log(Level.SEVERE, "Fatal error during file extraction", ex); //NON-NLS
262  NbBundle.getMessage(this.getClass(), "ExtractAction.done.notifyMsg.extractErr", ex.getMessage()));
263  msgDisplayed = true;
264  }
265  finally {
266  progress.finish();
267  if (!this.isCancelled() && !msgDisplayed) {
269  NbBundle.getMessage(this.getClass(), "ExtractAction.done.notifyMsg.fileExtr.text"));
270  }
271  }
272  }
273 
275  int workUnits = 0;
276  if (file.isFile()) {
277  workUnits += file.getSize();
278  }
279  else {
280  try {
281  for (Content child : file.getChildren()) {
282  if (child instanceof AbstractFile) {
283  workUnits += calculateProgressBarWorkUnits((AbstractFile)child);
284  }
285  }
286  }
287  catch (TskCoreException ex) {
288  logger.log(Level.SEVERE, "Could not get children of content", ex); //NON-NLS
289  }
290  }
291  return workUnits;
292  }
293  }
294 }
static boolean deleteFileDir(File path)
Definition: FileUtil.java:78
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)
void runExtractionTasks(ActionEvent e, ArrayList< FileExtractionTask > fileExtractionTasks)
void extractFiles(ActionEvent e, Collection<?extends AbstractFile > selectedFiles)
static boolean isDotDirectory(AbstractFile dir)
static Logger getLogger(String name)
Definition: Logger.java:131

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.