Cleanup ExtractAction

- extract File/Folder export to ExtractFscContentVisitor in ContentUtils
This commit is contained in:
Peter J. Martel 2011-12-15 18:01:37 -05:00
parent 8f9b2941e3
commit c903011f7a
3 changed files with 230 additions and 257 deletions

View File

@ -24,11 +24,14 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.ContentVisitor;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.Volume; import org.sleuthkit.datamodel.Volume;
@ -39,6 +42,8 @@ import org.sleuthkit.datamodel.VolumeSystem;
*/ */
public final class ContentUtils { public final class ContentUtils {
private final static Logger logger = Logger.getLogger(ContentUtils.class.getName());
// don't instantiate // don't instantiate
private ContentUtils() { private ContentUtils() {
throw new AssertionError(); throw new AssertionError();
@ -201,4 +206,118 @@ public final class ContentUtils {
out.close(); out.close();
} }
} }
/**
* Helper to ignore the '.' and '..' directories
*/
public static boolean isDotDirectory(Directory dir) {
String name = dir.getName();
return name.equals(".") || name.equals("..");
}
/**
* Extracts file/folder as given destination file, recursing into folders.
* Assumes there will be no collisions with existing directories/files, and
* that the directory to contain the destination file already exists.
*/
public static class ExtractFscContentVisitor extends ContentVisitor.Default<Void> {
java.io.File dest;
/**
* Make new extractor for a specific destination
* @param dest The file/folder visited will be extracted as this file
*/
public ExtractFscContentVisitor(java.io.File dest) {
this.dest = dest;
}
/**
* Convenience method to make a new instance for given destination
* and extract given content
*/
public static void extract(Content cntnt, java.io.File dest) {
cntnt.accept(new ExtractFscContentVisitor(dest));
}
public Void visit(File f) {
try {
ContentUtils.writeToFile(f, dest);
} catch (IOException ex) {
logger.log(Level.SEVERE,
"Trouble extracting file to " + dest.getAbsolutePath(),
ex);
}
return null;
}
@Override
public Void visit(Directory dir) {
// don't extract . and .. directories
if (isDotDirectory(dir)) {
return null;
}
dest.mkdir();
// member visitor to generate destination files for children
DestFileContentVisitor destFileCV = new DestFileContentVisitor();
try {
// recurse on children
for (Content child : dir.getChildren()) {
java.io.File childFile = child.accept(destFileCV);
ExtractFscContentVisitor childVisitor =
new ExtractFscContentVisitor(childFile);
child.accept(childVisitor);
}
} catch (TskException ex) {
logger.log(Level.SEVERE,
"Trouble fetching children to extract.", ex);
}
return null;
}
@Override
protected Void defaultVisit(Content cntnt) {
throw new UnsupportedOperationException("Can't extract a "
+ cntnt.getClass().getSimpleName());
}
/**
* Helper visitor to get the destination file for a child Content object
*/
private class DestFileContentVisitor extends
ContentVisitor.Default<java.io.File> {
/**
* Get destination file by adding File/Directory name to the path
* of parent
*/
private java.io.File getFsContentDest(FsContent fsc) {
String path = dest.getAbsolutePath() + java.io.File.separator
+ fsc.getName();
return new java.io.File(path);
}
@Override
public java.io.File visit(File f) {
return getFsContentDest(f);
}
@Override
public java.io.File visit(Directory dir) {
return getFsContentDest(dir);
}
@Override
protected java.io.File defaultVisit(Content cntnt) {
throw new UnsupportedOperationException("Can't get destination file for a "
+ cntnt.getClass().getSimpleName());
}
}
}
} }

View File

@ -70,40 +70,10 @@ public class DataResultFilterNode extends FilterNode{
List<Action> actions = new ArrayList<Action>(); List<Action> actions = new ArrayList<Action>();
actions.add(new NewWindowViewAction("View in New Window", getOriginal())); actions.add(new NewWindowViewAction("View in New Window", getOriginal()));
// TODO: ContentNode fix - restore right-click actions
// TODO: ContentVisitor instead of instanceof
Content nodeContent = this.getOriginal().getLookup().lookup(Content.class); Content nodeContent = this.getOriginal().getLookup().lookup(Content.class);
actions.addAll(nodeContent.accept(getActionsCV)); actions.addAll(nodeContent.accept(getActionsCV));
// // right click action(s) for image node
// if (originalNode instanceof ImageNode) {
// actions.add(new NewWindowViewAction("View in New Window", (ImageNode) originalNode));
// actions.addAll(ShowDetailActionVisitor.getActions(nodeContent));
// } // right click action(s) for volume node
// else if (originalNode instanceof VolumeNode) {
// actions.add(new NewWindowViewAction("View in New Window", (VolumeNode) originalNode));
// //new ShowDetailActionVisitor("Volume Details", this.currentNode.getName(), (VolumeNode) this.currentNode),
// actions.addAll(ShowDetailActionVisitor.getActions(nodeContent));
// actions.add(new ChangeViewAction("View", 0, this.getOriginal()));
// } // right click action(s) for directory node
// else if (originalNode instanceof DirectoryNode) {
// actions.add(new NewWindowViewAction("View in New Window", (DirectoryNode) originalNode));
// actions.add(new ChangeViewAction("View", 0, originalNode));
// // TODO: ContentNode fix - reimplement ExtractAction
// //actions.add(new ExtractAction("Extract Directory", (DirectoryNode) this.currentNode));
// } // right click action(s) for the file node
// else if (originalNode instanceof FileNode) {
// actions.add(new ExternalViewerAction("Open File in External Viewer", (FileNode) originalNode));
// actions.add(new NewWindowViewAction("View in New Window", (FileNode) originalNode));
// // TODO: ContentNode fix - reimplement ExtractAction
// //actions.add(new ExtractAction("Extract", (FileNode) this.currentNode));
// actions.add(new ChangeViewAction("View", 0, originalNode));
// }
return actions.toArray(new Action[actions.size()]); return actions.toArray(new Action[actions.size()]);
} }
@ -127,8 +97,7 @@ public class DataResultFilterNode extends FilterNode{
public List<Action> visit(Directory dir) { public List<Action> visit(Directory dir) {
List<Action> actions = new ArrayList<Action>(); List<Action> actions = new ArrayList<Action>();
actions.add(new ChangeViewAction("View", 0, getOriginal())); actions.add(new ChangeViewAction("View", 0, getOriginal()));
// TODO: ContentNode fix - reimplement ExtractAction actions.add(new ExtractAction("Extract Directory", getOriginal()));
//actions.add(new ExtractAction("Extract Directory", (DirectoryNode) this.currentNode));
return actions; return actions;
} }
@ -136,8 +105,7 @@ public class DataResultFilterNode extends FilterNode{
public List<Action> visit(File f) { public List<Action> visit(File f) {
List<Action> actions = new ArrayList<Action>(); List<Action> actions = new ArrayList<Action>();
actions.add(new ExternalViewerAction("Open File in External Viewer", getOriginal())); actions.add(new ExternalViewerAction("Open File in External Viewer", getOriginal()));
// TODO: ContentNode fix - reimplement ExtractAction actions.add(new ExtractAction("Extract", getOriginal()));
//actions.add(new ExtractAction("Extract", (FileNode) this.currentNode));
return actions; return actions;
} }

View File

@ -1,225 +1,111 @@
// TODO: ContentNode fix - reimplement ExtractAction /*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.directorytree;
import java.awt.event.ActionEvent;
import javax.swing.JFileChooser;
import java.io.File;
import java.awt.Component;
import javax.swing.AbstractAction;
import javax.swing.JOptionPane;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
import org.sleuthkit.autopsy.logging.Log;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor;
import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.FsContent;
///* /**
// * Autopsy Forensic Browser * Exports files and folders
// * */
// * Copyright 2011 Basis Technology Corp. public final class ExtractAction extends AbstractAction {
// * Contact: carrier <at> sleuthkit <dot> org
// * private static final InitializeContentVisitor initializeCV = new InitializeContentVisitor();
// * Licensed under the Apache License, Version 2.0 (the "License"); private FsContent fsContent;
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at public ExtractAction(String title, Node contentNode) {
// * super(title);
// * http://www.apache.org/licenses/LICENSE-2.0 Content tempContent = contentNode.getLookup().lookup(Content.class);
// *
// * Unless required by applicable law or agreed to in writing, software this.fsContent = tempContent.accept(initializeCV);
// * distributed under the License is distributed on an "AS IS" BASIS, this.setEnabled(fsContent != null);
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }
// * See the License for the specific language governing permissions and
// * limitations under the License. /**
// */ * Returns the FsContent if it is supported, otherwise null
//package org.sleuthkit.autopsy.directorytree; */
// private static class InitializeContentVisitor extends ContentVisitor.Default<FsContent> {
//import org.sleuthkit.autopsy.datamodel.FileNode;
//import java.io.*; @Override
//import java.awt.event.ActionEvent; public FsContent visit(org.sleuthkit.datamodel.File f) {
//import javax.swing.JFileChooser; return f;
//import java.io.File; }
//import java.awt.Component;
//import java.util.logging.Level; @Override
//import java.util.logging.Logger; public FsContent visit(Directory dir) {
//import javax.swing.AbstractAction; return ContentUtils.isDotDirectory(dir) ? null : dir;
//import javax.swing.JPanel; }
//import javax.swing.filechooser.FileFilter;
//import org.openide.nodes.Node; @Override
//import org.sleuthkit.autopsy.casemodule.GeneralFilter; protected FsContent defaultVisit(Content cntnt) {
//import org.sleuthkit.autopsy.datamodel.DirectoryNode; return null;
//import org.sleuthkit.autopsy.logging.Log; }
//import org.sleuthkit.datamodel.Content; }
//import org.sleuthkit.datamodel.TskException;
// /**
///** * Asks user to choose destination, then extracts file/directory to
// * This is an action class to extract and save the bytes given as a file. * destination (recursing on directories)
// * * @param e the action event
// * @author jantonius */
// */ @Override
//public final class ExtractAction extends AbstractAction { public void actionPerformed(ActionEvent e) {
// Log.noteAction(this.getClass());
// private JFileChooser fc = new JFileChooser();
// private byte[] source; JFileChooser fc = new JFileChooser();
// private Content content; fc.setSelectedFile(new File(this.fsContent.getName()));
// private String fileName; int returnValue = fc.showSaveDialog((Component) e.getSource());
// private String extension;
// // for error handling if (returnValue == JFileChooser.APPROVE_OPTION) {
// private JPanel caller; File destination = fc.getSelectedFile();
// private String className = this.getClass().toString();
// // check that it's okay to overwrite existing file
// /** the constructor */ if (destination.exists()) {
// public ExtractAction(String title, Node contentNode) { int choice = JOptionPane.showConfirmDialog(
// super(title); (Component) e.getSource(),
// "Destination file already exists, it will be overwritten.",
// String fullFileName = contentNode.getDisplayName(); "Destination already exists!",
// JOptionPane.OK_CANCEL_OPTION);
//
// if (fullFileName.equals(".")) { if (choice != JOptionPane.OK_OPTION) {
// // . folders are not associated with their children in the database, return;
// // so get original }
// Node parentNode = contentNode.getParentNode();
// contentNode = parentNode; if (!destination.delete()) {
// fullFileName = parentNode.getDisplayName(); JOptionPane.showMessageDialog(
// } (Component) e.getSource(),
// "Couldn't delete existing file.");
// }
// this.content = contentNode.getLookup().lookup(Content.class); }
//
// long size = content.getSize(); ExtractFscContentVisitor.extract(fsContent, destination);
// }
// }
// }
// /**
// * Checks first if the the selected it file or directory. If it's a file,
// * check if the file size is bigger than 0. If it's a directory, check
// * if it's not referring to the parent directory. Disables the menu otherwise.
// */
// if ((contentNode instanceof FileNode && size > 0) || (contentNode instanceof DirectoryNode && !fullFileName.equals(".."))) {
// if (contentNode instanceof FileNode && fullFileName.contains(".")) {
// String tempFileName = fullFileName.substring(0, fullFileName.indexOf("."));
// String tempExtension = fullFileName.substring(fullFileName.indexOf("."));
// this.fileName = tempFileName;
// this.extension = tempExtension;
// } else {
// this.fileName = fullFileName;
// this.extension = "";
// }
// } else {
// this.fileName = fullFileName;
// this.extension = "";
// this.setEnabled(false); // can't extract zero-sized file or ".." directory
// }
//
// }
//
// /**
// * Converts and saves the bytes into the file.
// *
// * @param e the action event
// */
// @Override
// public void actionPerformed(ActionEvent e) {
// Log.noteAction(this.getClass());
//
// // set the filter for File
// if (content instanceof org.sleuthkit.datamodel.File && !extension.equals("")) {
// //FileFilter filter = new ExtensionFileFilter(extension.substring(1).toUpperCase() + " File (*" + extension + ")", new String[]{extension.substring(1)});
// String[] fileExt = {extension};
// FileFilter filter = new GeneralFilter(fileExt, extension.substring(1).toUpperCase() + " File (*" + extension + ")", false);
// fc.setFileFilter(filter);
// }
//
// fc.setSelectedFile(new File(this.fileName));
//
// int returnValue = fc.showSaveDialog((Component) e.getSource());
// if (returnValue == JFileChooser.APPROVE_OPTION) {
// String path = fc.getSelectedFile().getPath() + extension;
//
//
// // TODO: convert this to a Content Visitor
// try {
// // file extraction
// if (content instanceof org.sleuthkit.datamodel.File) {
// extractFile(path, (org.sleuthkit.datamodel.File) content);
// }
//
// // directory extraction
// if (content instanceof org.sleuthkit.datamodel.File) {
// extractDirectory(path, (org.sleuthkit.datamodel.Directory) content);
// }
// } catch (Exception ex) {
// Logger.getLogger(this.className).log(Level.WARNING, "Error: Couldn't extract file/directory.", ex);
// }
//
// }
//
// }
//
// /**
// * Extracts the content of the given fileNode into the given path.
// *
// * @param givenPath the path to extract the file
// * @param file the file node that contain the file
// */
// private void extractFile(String givenPath, org.sleuthkit.datamodel.File file) throws Exception {
// try {
// if (file.getSize() > 0) {
// try {
// this.source = file.read(0, file.getSize());
// } catch (TskException ex) {
// throw new Exception("Error: can't read the content of the file.", ex);
// }
// } else {
// this.source = new byte[0];
// }
//
// String path = givenPath;
//
// File outputFile = new File(path);
// if (outputFile.exists()) {
// outputFile.delete();
// }
// outputFile.createNewFile();
// // convert char to byte
// byte[] dataSource = new byte[source.length];
// for (int i = 0; i < source.length; i++) {
// dataSource[i] = (byte) source[i];
// }
// FileOutputStream fos = new FileOutputStream(outputFile);
// //fos.write(dataSource);
// fos.write(dataSource);
// fos.close();
// } catch (IOException ex) {
// throw new Exception("Error while trying to extract the file.", ex);
// }
// }
//
// /**
// * Extracts the content of the given directoryNode into the given path.
// *
// * @param givenPath the path to extract the directory
// * @param dirNode the directory node that contain the directory
// */
// private void extractDirectory(String givenPath, DirectoryNode dirNode) throws Exception {
// String path = givenPath;
// File dir = new File(path);
// if (!dir.exists()) {
// dir.mkdir();
// }
//
// int totalChildren = dirNode.getChildren().getNodesCount();
// for (int i = 0; i < totalChildren; i++) {
// Node childNode = dirNode.getChildren().getNodeAt(i);
//
// if (childNode instanceof FileNode) {
// FileNode fileNode = (FileNode) childNode;
// String tempPath = path + File.separator + ((Node)fileNode).getDisplayName();
// try {
// extractFile(tempPath, fileNode);
// } catch (Exception ex) {
// throw ex;
// }
// }
//
// if (childNode instanceof DirectoryNode) {
// DirectoryNode dirNode2 = (DirectoryNode) childNode;
// String dirNode2Name = ((Node)dirNode2).getDisplayName();
//
// if (!dirNode2Name.trim().equals(".") && !dirNode2Name.trim().equals("..")) {
// String tempPath = path + File.separator + dirNode2Name;
// extractDirectory(tempPath, dirNode2);
// }
// }
// }
//
//
// }
//}