19package org.sleuthkit.autopsy.directorytree.actionhelpers;
21import java.awt.Component;
22import java.awt.event.ActionEvent;
24import java.io.IOException;
25import java.text.MessageFormat;
26import java.util.ArrayList;
27import java.util.Collection;
28import java.util.HashSet;
29import java.util.Iterator;
32import java.util.concurrent.ExecutionException;
33import java.util.logging.Level;
34import javax.swing.JFileChooser;
35import javax.swing.JOptionPane;
36import javax.swing.SwingWorker;
37import org.netbeans.api.progress.ProgressHandle;
38import org.openide.util.Cancellable;
39import org.openide.util.NbBundle;
40import org.openide.util.NbBundle.Messages;
41import org.sleuthkit.autopsy.casemodule.Case;
42import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
43import org.sleuthkit.autopsy.coreutils.FileUtil;
44import org.sleuthkit.autopsy.coreutils.Logger;
45import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
46import org.sleuthkit.autopsy.datamodel.ContentUtils;
47import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
48import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
49import org.sleuthkit.datamodel.AbstractFile;
50import org.sleuthkit.datamodel.Content;
71 public void extract(ActionEvent event, Collection<? extends AbstractFile> selectedFiles) {
72 if (selectedFiles.size() > 1) {
74 }
else if (selectedFiles.size() == 1) {
75 extractFile(event, selectedFiles.iterator().next());
85 @NbBundle.Messages({
"ExtractActionHelper.noOpenCase.errMsg=No open case available.",
86 "ExtractActionHelper.extractOverwrite.title=Export to csv file",
88 "ExtractActionHelper.extractOverwrite.msg=A file already exists at {0}. Do you want to overwrite the existing file?"
90 private void extractFile(ActionEvent event, AbstractFile selectedFile) {
95 JOptionPane.showMessageDialog((Component) event.getSource(), Bundle.ExtractActionHelper_noOpenCase_errMsg());
96 logger.log(Level.INFO,
"Exception while getting open case.", ex);
103 if (fileChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) {
106 ArrayList<FileExtractionTask> fileExtractionTasks =
new ArrayList<>();
107 fileExtractionTasks.add(
new FileExtractionTask(selectedFile, fileChooser.getSelectedFile()));
108 runExtractionTasks(event, fileExtractionTasks, fileChooser.getSelectedFile().getName());
118 private void extractFiles(ActionEvent event, Collection<? extends AbstractFile> selectedFiles) {
123 JOptionPane.showMessageDialog((Component) event.getSource(), Bundle.ExtractActionHelper_noOpenCase_errMsg());
124 logger.log(Level.INFO,
"Exception while getting open case.", ex);
128 folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
130 if (folderChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) {
131 File destinationFolder = folderChooser.getSelectedFile();
132 if (!destinationFolder.exists()) {
134 destinationFolder.mkdirs();
135 }
catch (Exception ex) {
136 JOptionPane.showMessageDialog((Component) event.getSource(), NbBundle.getMessage(
this.getClass(),
137 "ExtractAction.extractFiles.cantCreateFolderErr.msg"));
138 logger.log(Level.INFO,
"Unable to create folder(s) for user " + destinationFolder.getAbsolutePath(), ex);
150 Set<AbstractFile> uniqueFiles =
new HashSet<>(selectedFiles);
153 ArrayList<FileExtractionTask> fileExtractionTasks =
new ArrayList<>();
154 for (AbstractFile source : uniqueFiles) {
173 return caseExportPath;
177 if (file.exists() ==
false || file.isDirectory() ==
false) {
178 return caseExportPath;
210 private void runExtractionTasks(ActionEvent event, List<FileExtractionTask> fileExtractionTasks, String destName) {
213 for (Iterator<FileExtractionTask> it = fileExtractionTasks.iterator(); it.hasNext();) {
225 if (task.destination.exists()) {
226 if (JOptionPane.showConfirmDialog((Component) event.getSource(),
227 NbBundle.getMessage(
this.getClass(),
"ExtractActionHelper.confDlg.destFileExist.msg", task.destination.getAbsolutePath()),
228 NbBundle.getMessage(
this.getClass(),
"ExtractActionHelper.confDlg.destFileExist.title"),
229 JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
231 JOptionPane.showMessageDialog((Component) event.getSource(),
232 NbBundle.getMessage(
this.getClass(),
"ExtractActionHelper.msgDlg.cantOverwriteFile.msg", task.destination.getAbsolutePath()));
242 if (!fileExtractionTasks.isEmpty()) {
246 }
catch (Exception ex) {
247 logger.log(Level.WARNING,
"Unable to start background file extraction thread", ex);
251 NbBundle.getMessage(
this.getClass(),
"ExtractActionHelper.notifyDlg.noFileToExtr.msg"));
258 private class FileExtractionTask {
269 FileExtractionTask(AbstractFile source, File destination) {
270 this.source = source;
271 this.destination = destination;
291 UIExtractionVisitor(File dest, ProgressHandle progress, SwingWorker<T, V> worker,
boolean source) {
292 super(dest, progress, worker, source);
308 static <T,V>
void writeContent(Content content, File dest, ProgressHandle progress, SwingWorker<T, V> worker) {
309 content.accept(
new UIExtractionVisitor<>(dest, progress, worker,
true));
314 protected void writeFile(Content file, File dest, ProgressHandle progress, SwingWorker<T, V> worker,
boolean source)
throws IOException {
317 String parent = dest.getParent();
318 String fileName = dest.getName();
319 String objIdFileName = MessageFormat.format(
"{0}-{1}", file.getId(), fileName);
320 destFile =
new File(parent, objIdFileName);
325 super.writeFile(file, destFile, progress, worker, source);
330 return new UIExtractionVisitor<>(childFile, progress, worker,
false);
340 private class FileExtracter
extends SwingWorker<Object, Void> {
361 "# {0} - outputFolderName",
362 "ExtractActionHelper.progress.extracting=Extracting to {0}",
364 "ExtractActionHelper.progress.fileExtracting=Extracting file: {0}"
372 final String displayName = Bundle.ExtractActionHelper_progress_extracting(
destName);
373 progress = ProgressHandle.createHandle(displayName,
new Cancellable() {
375 public boolean cancel() {
378 NbBundle.getMessage(
this.getClass(),
"ExtractActionHelper.progress.cancellingExtraction", displayName));
388 progress.progress(Bundle.ExtractActionHelper_progress_fileExtracting(task.destination.getName()));
397 boolean msgDisplayed =
false;
400 }
catch (InterruptedException | ExecutionException ex) {
401 logger.log(Level.SEVERE,
"Fatal error during file extraction", ex);
403 NbBundle.getMessage(
this.getClass(),
"ExtractActionHelper.done.notifyMsg.extractErr", ex.getMessage()));
407 if (!this.isCancelled() && !msgDisplayed) {
409 NbBundle.getMessage(
this.getClass(),
"ExtractActionHelper.done.notifyMsg.fileExtr.text"));
static Case getCurrentCaseThrows()
String getExportDirectory()
static String escapeFileName(String fileName)
static boolean deleteFileDir(File path)
synchronized static Logger getLogger(String name)
static void info(String message)
static boolean isDotDirectory(AbstractFile dir)