diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index 811be0ab35..b91ebbde9f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -25,7 +25,8 @@ package org.sleuthkit.autopsy.casemodule.services; import java.io.Closeable; import java.io.IOException; import java.util.List; -import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.FsContent; @@ -33,6 +34,7 @@ import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.VirtualDirectory; /** * Abstraction to facilitate access to files and directories. @@ -40,6 +42,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class FileManager implements Closeable { private SleuthkitCase tskCase; + private static final Logger logger = Logger.getLogger(FileManager.class.getName()); public FileManager(SleuthkitCase tskCase) { this.tskCase = tskCase; @@ -138,6 +141,90 @@ public class FileManager implements Closeable { isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails); } + /** + * Helper (internal) to add child of local dir recursively + * @param parentVd + * @param childLocalFile + * @throws TskCoreException + */ + private void addLocalDirectoryRecInt(VirtualDirectory parentVd, + java.io.File childLocalFile) throws TskCoreException { + + final boolean isDir = childLocalFile.isDirectory(); + + if (isDir) { + //create virtual folder + final VirtualDirectory childVd = tskCase.addVirtualDirectory(parentVd.getId(), childLocalFile.getName()); + //add children recursively + for (java.io.File childChild : childLocalFile.listFiles()) { + addLocalDirectoryRecInt(childVd, childChild); + } + } else { + //add leaf file, base case + this.addLocalFileSingle(childLocalFile.getAbsolutePath(), parentVd); + } + + } + + /** + * Add a local directory and its children recursively. + * + * + * @param localAbsPath local absolute path of root folder whose children are + * to be added recursively + * @return parent virtual directory folder created representing the + * localAbsPath node + * @throws TskCoreException exception thrown if the object creation failed + * due to a critical system error or of the file manager has already been + * closed, or if the localAbsPath could not be accessed + */ + public synchronized VirtualDirectory addLocalDir(String localAbsPath) throws TskCoreException { + if (tskCase == null) { + throw new TskCoreException("Attempted to use FileManager after it was closed."); + } + + java.io.File localDir = new java.io.File(localAbsPath); + if (!localDir.exists()) { + throw new TskCoreException("Attempted to add a local dir that does not exist: " + localAbsPath); + } + if (!localDir.canRead()) { + throw new TskCoreException("Attempted to add a local dir that is not readable: " + localAbsPath); + } + + if (!localDir.isDirectory()) { + throw new TskCoreException("Attempted to add a local dir that is not a directory: " + localAbsPath); + } + + final String rootVdName = localDir.getName(); + + VirtualDirectory rootVd = null; + try { + final long localFilesRootId = tskCase.getLocalFilesRootDirectoryId(); + rootVd = tskCase.addVirtualDirectory(localFilesRootId, rootVdName); + } catch (TskCoreException e) { + //log and rethrow + final String msg = "Error creating root dir for local dir to be added, can't addLocalDir: " + localDir; + logger.log(Level.SEVERE, msg, e); + throw new TskCoreException(msg); + } + + try { + java.io.File[] localChildren = localDir.listFiles(); + for (java.io.File localChild : localChildren) { + //add childrnen recursively, at a time in separate transaction + //consider a single transaction for everything + addLocalDirectoryRecInt(rootVd, localChild); + } + } catch (TskCoreException e) { + final String msg = "Error creating local children for local dir to be added, can't fully add addLocalDir: " + localDir; + logger.log(Level.SEVERE, msg, e); + throw new TskCoreException(msg); + } + + + return rootVd; + } + /** * Creates a single local file under $LocalFiles for the case, adds it to * the database and returns it. @@ -147,7 +234,7 @@ public class FileManager implements Closeable { * @return newly created local file object added to the database * @throws TskCoreException exception thrown if the object creation failed * due to a critical system error or of the file manager has already been - * closed + * closed, or if the localAbsPath could not be accessed * */ public synchronized LocalFile addLocalFileSingle(String localAbsPath) throws TskCoreException { @@ -201,11 +288,11 @@ public class FileManager implements Closeable { LocalFile lf = tskCase.addLocalFile(fileName, localAbsPath, size, ctime, crtime, atime, mtime, isFile, parentFile); - + //refresh the content tree - //TODO decouple, use Node autorefresh once implemented - DirectoryTreeTopComponent.getDefault().refreshContentTreeSafe(); - + //TODO decouple at least using events, and later use Node autorefresh once implemented + //DirectoryTreeTopComponent.getDefault().refreshContentTreeSafe(); + return lf; } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java index 4fbe2b18a0..808e8798fb 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java @@ -25,11 +25,13 @@ import org.openide.nodes.Children; import org.sleuthkit.autopsy.datamodel.DirectoryNode; import org.openide.nodes.FilterNode; import org.openide.nodes.Node; -import org.sleuthkit.autopsy.datamodel.LocalFileNode; +import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; +import org.sleuthkit.autopsy.datamodel.LocalFileNode; +import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VolumeNode; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; @@ -37,6 +39,7 @@ import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskException; +import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.Volume; /** @@ -123,7 +126,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { try { for (Content c : vol.getChildren()) { - if (!(c instanceof LayoutFile)) { + if (!(c instanceof LayoutFile + || c instanceof VirtualDirectory + ) + + ) { ret = false; break; } @@ -173,14 +180,13 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { return isLeafDirectory(dn); } - @Override - public Boolean visit(FileNode fn) { + private Boolean visitDeep(AbstractAbstractFileNode node) { //is a leaf if has no children, or children are files not dirs - boolean hasChildren = fn.hasContentChildren(); + boolean hasChildren = node.hasContentChildren(); if (!hasChildren) { return true; } - List derivedChildren = fn.getContentChildren(); + List derivedChildren = node.getContentChildren(); //child of a file, must be a (derived) file too for (Content childContent : derivedChildren) { if (((AbstractFile) childContent).isDir()) { @@ -198,36 +204,34 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { } return true; } - + @Override - public Boolean visit(LocalFileNode dfn) { - //is a leaf if has no children, or children are files not dirs - boolean hasChildren = dfn.hasContentChildren(); - if (!hasChildren) { - return true; - } - List derivedChildren = dfn.getContentChildren(); - //child of a file, must be a (derived) file too - for (Content childContent : derivedChildren) { - if (((AbstractFile) childContent).isDir()) { - return false; - } else { - try { - if (childContent.hasChildren()) { - return false; - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error checking if derived file node is leaf.", e); - } - } - } - return true; + public Boolean visit(FileNode fn) { + return visitDeep(fn); } + + + @Override + public Boolean visit(LocalFileNode lfn) { + return visitDeep(lfn); + } + + @Override + public Boolean visit(LayoutFileNode fn) { + return visitDeep(fn); + } + @Override public Boolean visit(VolumeNode vn) { return isLeafVolume(vn); } + + @Override + public Boolean visit(VirtualDirectoryNode vdn) { + //return visitDeep(vdn); + return ! vdn.hasContentChildren(); + } } private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default { @@ -251,13 +255,18 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { } @Override - public Boolean visit(LocalFileNode dfn) { - return dfn.hasContentChildren(); + public Boolean visit(LocalFileNode lfn) { + return lfn.hasContentChildren(); } @Override public Boolean visit(LayoutFileNode ln) { - return false; + return ln.hasContentChildren(); + } + + @Override + public Boolean visit(VirtualDirectoryNode vdn) { + return vdn.hasContentChildren(); } } }