Merge pull request #7551 from gdicristofaro/8299-fileExtraction

8299 file extraction
This commit is contained in:
eugene7646 2022-02-10 11:17:28 -05:00 committed by GitHub
commit d8241caa60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 128 additions and 66 deletions

View File

@ -392,85 +392,69 @@ public final class ContentUtils {
public static <T, V> void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker<T, V> worker) {
cntnt.accept(new ExtractFscContentVisitor<>(dest, progress, worker, true));
}
/**
* Base method writing a file to disk.
*
* @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);
}
@Override
public Void visit(File file) {
/**
* 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 {
ContentUtils.writeToFile(file, dest, progress, worker, source);
writeFile(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 file '%s' (id=%d) to '%s'.",
file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
String.format("Error extracting %s '%s' (id=%d) to '%s'.",
fileType, file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
}
return null;
}
@Override
public Void visit(File file) {
return visitFile(file, "file");
}
@Override
public Void visit(LayoutFile file) {
try {
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;
return visitFile(file, "unallocated content file");
}
@Override
public Void visit(DerivedFile file) {
try {
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;
return visitFile(file, "derived file");
}
@Override
public Void visit(LocalFile file) {
try {
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;
return visitFile(file, "local file");
}
@Override
public Void visit(SlackFile file) {
try {
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;
return visitFile(file, "slack file");
}
@Override
@ -493,6 +477,20 @@ public final class ContentUtils {
+ content.getName();
return new java.io.File(path);
}
/**
* Returns a visitor to visit any child content.
* @param childFile 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
* @return
*/
protected ExtractFscContentVisitor<T, V> getChildVisitor(java.io.File childFile, ProgressHandle progress, SwingWorker<T, V> worker) {
return new ExtractFscContentVisitor<>(childFile, progress, worker, false);
}
public Void visitDir(AbstractFile dir) {
@ -509,8 +507,7 @@ public final class ContentUtils {
for (Content child : dir.getChildren()) {
if (child instanceof AbstractFile) { //ensure the directory's artifact children are ignored
java.io.File childFile = getFsContentDest(child);
ExtractFscContentVisitor<T, V> childVisitor
= new ExtractFscContentVisitor<>(childFile, progress, worker, false);
ExtractFscContentVisitor<T, V> childVisitor = getChildVisitor(childFile, progress, worker);
// If this is the source directory of an extract it
// will have a progress and worker, and will keep track
// of the progress bar's progress

View File

@ -43,6 +43,8 @@ public final class ExtractAction extends AbstractAction {
}
return instance;
}
private final ExtractActionHelper extractor = new ExtractActionHelper();
/**
* Private constructor for the action.
@ -61,7 +63,6 @@ public final class ExtractAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
Lookup lookup = Utilities.actionsGlobalContext();
Collection<? extends AbstractFile> selectedFiles =lookup.lookupAll(AbstractFile.class);
ExtractActionHelper extractor = new ExtractActionHelper();
extractor.extract(e, selectedFiles);
}

View File

@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.directorytree.actionhelpers;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@ -42,8 +44,10 @@ import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
/**
* Helper class for methods needed by actions which extract files.
@ -52,7 +56,7 @@ public class ExtractActionHelper {
private final Logger logger = Logger.getLogger(ExtractActionHelper.class.getName());
private String userDefinedExportPath;
private final JFileChooserFactory extractFileHelper = new JFileChooserFactory();
private final JFileChooserFactory extractFilesHelper = new JFileChooserFactory();
@ -68,12 +72,7 @@ public class ExtractActionHelper {
if (selectedFiles.size() > 1) {
extractFiles(event, selectedFiles);
} else if (selectedFiles.size() == 1) {
AbstractFile source = selectedFiles.iterator().next();
if (source.isDir()) {
extractFiles(event, selectedFiles);
} else {
extractFile(event, selectedFiles.iterator().next());
}
extractFile(event, selectedFiles.iterator().next());
}
}
@ -83,7 +82,11 @@ public class ExtractActionHelper {
* @param event
* @param selectedFile Selected file
*/
@NbBundle.Messages({"ExtractActionHelper.noOpenCase.errMsg=No open case available."})
@NbBundle.Messages({"ExtractActionHelper.noOpenCase.errMsg=No open case available.",
"ExtractActionHelper.extractOverwrite.title=Export to csv file",
"# {0} - fileName",
"ExtractActionHelper.extractOverwrite.msg=A file already exists at {0}. Do you want to overwrite the existing file?"
})
private void extractFile(ActionEvent event, AbstractFile selectedFile) {
Case openCase;
try {
@ -269,6 +272,68 @@ 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);
}
@Override
protected ExtractFscContentVisitor<T, V> getChildVisitor(File childFile, ProgressHandle progress, SwingWorker<T, V> worker) {
return new UIExtractionVisitor(childFile, progress, worker, false);
}
}
/**
* Thread that does the actual extraction work
*/
@ -321,8 +386,7 @@ public class ExtractActionHelper {
// Do the extraction tasks.
for (FileExtractionTask task : this.extractionTasks) {
progress.progress(Bundle.ExtractActionHelper_progress_fileExtracting(task.destination.getName()));
ContentUtils.ExtractFscContentVisitor.extract(task.source, task.destination, null, this);
UIExtractionVisitor.writeContent(task.source, task.destination, null, this);
}
return null;