don't overwrite on conflict

This commit is contained in:
Greg DiCristofaro 2022-02-08 09:05:44 -05:00
parent c69c058c18
commit 3af245e411
2 changed files with 108 additions and 66 deletions

View File

@ -393,84 +393,68 @@ public final class ContentUtils {
cntnt.accept(new ExtractFscContentVisitor<>(dest, progress, worker, true)); cntnt.accept(new ExtractFscContentVisitor<>(dest, progress, worker, true));
} }
@Override /**
public Void visit(File file) { * Base method writing a file to disk.
try { *
* @param file The TSK content file.
* @param dest The disk location where the content will be written.
* @param progress progress bar handle to update, if available. null
* otherwise
* @param worker the swing worker background thread the process runs
* within, or null, if in the main thread, used to
* handle task cancellation
* @param source true if source file
*
* @throws IOException
*/
protected void writeFile(Content file, java.io.File dest, ProgressHandle progress, SwingWorker<T, V> worker, boolean source) throws IOException {
ContentUtils.writeToFile(file, dest, progress, worker, source); ContentUtils.writeToFile(file, dest, progress, worker, source);
}
/**
* Visits a TSK content file and writes that file to disk.
* @param file The file to be written.
* @param fileType The file type (i.e. "derived file") for error logging.
* @return null.
*/
protected Void visitFile(Content file, String fileType) {
try {
writeFile(file, dest, progress, worker, source);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, logger.log(Level.WARNING,
String.format("Error reading file '%s' (id=%d).", String.format("Error reading file '%s' (id=%d).",
file.getName(), file.getId()), ex); //NON-NLS file.getName(), file.getId()), ex); //NON-NLS
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, logger.log(Level.SEVERE,
String.format("Error extracting file '%s' (id=%d) to '%s'.", String.format("Error extracting %s '%s' (id=%d) to '%s'.",
file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS fileType, file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
} }
return null; return null;
} }
@Override
public Void visit(File file) {
return visitFile(file, "file");
}
@Override @Override
public Void visit(LayoutFile file) { public Void visit(LayoutFile file) {
try { return visitFile(file, "unallocated content file");
ContentUtils.writeToFile(file, dest, progress, worker, source);
} catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING,
String.format("Error reading file '%s' (id=%d).",
file.getName(), file.getId()), ex); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE,
String.format("Error extracting unallocated content file '%s' (id=%d) to '%s'.",
file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
}
return null;
} }
@Override @Override
public Void visit(DerivedFile file) { public Void visit(DerivedFile file) {
try { return visitFile(file, "derived file");
ContentUtils.writeToFile(file, dest, progress, worker, source);
} catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING,
String.format("Error reading file '%s' (id=%d).",
file.getName(), file.getId()), ex); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE,
String.format("Error extracting derived file '%s' (id=%d) to '%s'.",
file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
}
return null;
} }
@Override @Override
public Void visit(LocalFile file) { public Void visit(LocalFile file) {
try { return visitFile(file, "local file");
ContentUtils.writeToFile(file, dest, progress, worker, source);
} catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING,
String.format("Error reading file '%s' (id=%d).",
file.getName(), file.getId()), ex); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE,
String.format("Error extracting local file '%s' (id=%d) to '%s'.",
file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
}
return null;
} }
@Override @Override
public Void visit(SlackFile file) { public Void visit(SlackFile file) {
try { return visitFile(file, "slack file");
ContentUtils.writeToFile(file, dest, progress, worker, source);
} catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING,
String.format("Error reading file '%s' (id=%d).",
file.getName(), file.getId()), ex); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE,
String.format("Error extracting slack file '%s' (id=%d) to '%s'.",
file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
}
return null;
} }
@Override @Override

View File

@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.directorytree.actionhelpers;
import java.awt.Component; import java.awt.Component;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -36,15 +38,16 @@ import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.Cancellable; import org.openide.util.Cancellable;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
import org.sleuthkit.autopsy.guiutils.JFileChooserFactory; import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
/** /**
* Helper class for methods needed by actions which extract files. * Helper class for methods needed by actions which extract files.
@ -99,15 +102,15 @@ public class ExtractActionHelper {
fileChooser.setSelectedFile(new File(FileUtil.escapeFileName(selectedFile.getName()))); fileChooser.setSelectedFile(new File(FileUtil.escapeFileName(selectedFile.getName())));
if (fileChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) { if (fileChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) {
File saveLocation = fileChooser.getSelectedFile(); File saveLocation = fileChooser.getSelectedFile();
if (saveLocation.exists()) { // if (saveLocation.exists()) {
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), // if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(),
Bundle.ExtractActionHelper_extractOverwrite_msg(saveLocation.getPath()), // Bundle.ExtractActionHelper_extractOverwrite_msg(saveLocation.getPath()),
Bundle.ExtractActionHelper_extractOverwrite_title(), // Bundle.ExtractActionHelper_extractOverwrite_title(),
JOptionPane.YES_NO_OPTION)) { // JOptionPane.YES_NO_OPTION)) {
} else { // } else {
return; // return;
} // }
} // }
String exportDirectory = saveLocation.getParent(); String exportDirectory = saveLocation.getParent();
updateExportDirectory(exportDirectory, openCase); updateExportDirectory(exportDirectory, openCase);
@ -281,6 +284,62 @@ public class ExtractActionHelper {
} }
} }
/**
* A file content extraction visitor that handles for the UI designed to
* handle file name conflicts by appending the object id to the file name.
*/
private static class UIExtractionVisitor<T, V> extends ExtractFscContentVisitor<T, V> {
/**
* @param file The TSK content file.
* @param dest The disk location where the content will be written.
* @param progress progress bar handle to update, if available. null
* otherwise
* @param worker the swing worker background thread the process runs
* within, or null, if in the main thread, used to
* handle task cancellation
* @param source true if source file
*/
UIExtractionVisitor(File dest, ProgressHandle progress, SwingWorker<T, V> worker, boolean source) {
super(dest, progress, worker, source);
}
/**
* Writes content and children to disk.
*
* @param content The root content.
* @param file The TSK content file.
* @param dest The disk location where the content will be written.
* @param progress progress bar handle to update, if available. null
* otherwise
* @param worker the swing worker background thread the process runs
* within, or null, if in the main thread, used to
* handle task cancellation
* @param source true if source file
*/
static <T,V> void writeContent(Content content, File dest, ProgressHandle progress, SwingWorker<T, V> worker) {
content.accept(new UIExtractionVisitor<>(dest, progress, worker, true));
}
@Override
protected void writeFile(Content file, File dest, ProgressHandle progress, SwingWorker<T, V> worker, boolean source) throws IOException {
File destFile;
if (dest.exists()) {
String parent = dest.getParent();
String fileName = dest.getName();
String objIdFileName = MessageFormat.format("{0}-{1}", file.getId(), fileName);
destFile = new File(parent, objIdFileName);
} else {
destFile = dest;
}
super.writeFile(file, destFile, progress, worker, source);
}
}
/** /**
* Thread that does the actual extraction work * Thread that does the actual extraction work
*/ */
@ -333,8 +392,7 @@ public class ExtractActionHelper {
// Do the extraction tasks. // Do the extraction tasks.
for (FileExtractionTask task : this.extractionTasks) { for (FileExtractionTask task : this.extractionTasks) {
progress.progress(Bundle.ExtractActionHelper_progress_fileExtracting(task.destination.getName())); progress.progress(Bundle.ExtractActionHelper_progress_fileExtracting(task.destination.getName()));
UIExtractionVisitor.writeContent(task.source, task.destination, null, this);
ContentUtils.ExtractFscContentVisitor.extract(task.source, task.destination, null, this);
} }
return null; return null;