diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/blue-tag-icon-16.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/blue-tag-icon-16.png new file mode 100644 index 0000000000..9f9eb9ef25 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/blue-tag-icon-16.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/green-tag-icon-16.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/green-tag-icon-16.png new file mode 100644 index 0000000000..22ce12ad2a Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/green-tag-icon-16.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/star-bookmark-icon-16.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/star-bookmark-icon-16.png new file mode 100644 index 0000000000..a06c596ada Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/star-bookmark-icon-16.png differ diff --git a/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png new file mode 100644 index 0000000000..1d1987fee6 Binary files /dev/null and b/CoreComponentInterfaces/src/org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png differ diff --git a/DataModel/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/DataModel/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index f4bfbbacf3..0898d8b35e 100644 --- a/DataModel/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/DataModel/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -103,7 +103,7 @@ abstract class AbstractContentChildren extends Keys { } /** - * Creates appropriate Node for each sub-class of Content + * Creates appropriate Node for each supported artifact category / grouping */ static class CreateAutopsyNodeVisitor extends AutopsyItemVisitor.Default { diff --git a/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 00eb22b558..b96dbedd49 100644 --- a/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -44,7 +44,26 @@ public class BlackboardArtifactNode extends DisplayableItemNode { Content associated; static final Logger logger = Logger.getLogger(BlackboardArtifactNode.class.getName()); - public BlackboardArtifactNode(BlackboardArtifact artifact) { + /** + * Construct blackboard artifact node from an artifact and using provided icon + * @param artifact artifact to encapsulate + * @param iconPath icon to use for the artifact + */ + public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) { + super(Children.LEAF, getLookups(artifact)); + + this.artifact = artifact; + this.associated = getAssociatedContent(artifact); + this.setName(Long.toString(artifact.getArtifactID())); + this.setDisplayName(associated.getName()); + this.setIconBaseWithExtension(iconPath); + } + + /** + * Construct blackboard artifact node from an artifact and using default icon for artifact type + * @param artifact artifact to encapsulate + */ + public BlackboardArtifactNode(BlackboardArtifact artifact) { super(Children.LEAF, getLookups(artifact)); this.artifact = artifact; @@ -209,6 +228,10 @@ public class BlackboardArtifactNode extends DisplayableItemNode { return "programs.png"; case TSK_RECENT_OBJECT: return "recent_docs.png"; + case TSK_TAG_FILE: + return "blue-tag-icon-16.png"; + case TSK_TAG_ARTIFACT: + return "green-tag-icon-16.png"; } return "artifact-icon.png"; } diff --git a/DataModel/src/org/sleuthkit/autopsy/datamodel/Bookmarks.java b/DataModel/src/org/sleuthkit/autopsy/datamodel/Bookmarks.java index 3c138f8419..46ffcbb4db 100644 --- a/DataModel/src/org/sleuthkit/autopsy/datamodel/Bookmarks.java +++ b/DataModel/src/org/sleuthkit/autopsy/datamodel/Bookmarks.java @@ -23,26 +23,35 @@ import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import org.openide.nodes.AbstractNode; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.lookup.Lookups; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskException; /** * Support for bookmark (file and result/artifact) nodes and displaying * bookmarks in the directory tree Bookmarks are divided into file and result * children bookmarks. + * + * Bookmarks are specialized tags - TSK_TAG_NAME starts with Bookmark + * + * TODO bookmark hierarchy support (TSK_TAG_NAME with slashes) */ public class Bookmarks implements AutopsyVisitableItem { private static final String LABEL_NAME = "Bookmarks"; private static final String DISPLAY_NAME = LABEL_NAME; + private static final String FILE_BOOKMARKS_LABEL_NAME = "File Bookmarks"; + private static final String RESULT_BOOKMARKS_LABEL_NAME = "Result Bookmarks"; + + private static final String BOOKMARK_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png"; + private static final Logger logger = Logger.getLogger(Bookmarks.class.getName()); private SleuthkitCase skCase; private final Map> data = @@ -67,13 +76,13 @@ public class Bookmarks implements AutopsyVisitableItem { super(Children.create(new BookmarksRootChildren(), true), Lookups.singleton(DISPLAY_NAME)); super.setName(LABEL_NAME); super.setDisplayName(DISPLAY_NAME); - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/mail-icon-16.png"); + this.setIconBaseWithExtension(BOOKMARK_ICON_PATH); initData(); } private void initData() { - data.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_BOOKMARK_FILE, null); - data.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_BOOKMARK_ARTIFACT, null); + data.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE, null); + data.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT, null); try { for (BlackboardArtifact.ARTIFACT_TYPE artType : data.keySet()) { @@ -141,10 +150,19 @@ public class Bookmarks implements AutopsyVisitableItem { public BookmarksNodeRoot(BlackboardArtifact.ARTIFACT_TYPE bookType, List bookmarks) { super(Children.create(new BookmarksChildrenNode(bookmarks), true), Lookups.singleton(bookType.getDisplayName())); - final String name = bookType.getDisplayName(); + + String name = null; + if (bookType.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE)) { + name = FILE_BOOKMARKS_LABEL_NAME; + } + else if (bookType.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT)) { + name = RESULT_BOOKMARKS_LABEL_NAME; + } + super.setName(name); super.setDisplayName(name + " (" + bookmarks.size() + ")"); - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/account-icon-16.png"); + + this.setIconBaseWithExtension(BOOKMARK_ICON_PATH); } @Override @@ -200,7 +218,31 @@ public class Bookmarks implements AutopsyVisitableItem { @Override protected Node createNodeForKey(BlackboardArtifact artifact) { - return new BlackboardArtifactNode(artifact); + return new BlackboardArtifactNode(artifact, BOOKMARK_ICON_PATH); } } + + /** + * Links existing blackboard artifact (a tag) to this artifact. + * Linkage is made using TSK_TAGGED_ARTIFACT attribute. + */ + void addArtifactTag(BlackboardArtifact art, BlackboardArtifact tag) throws TskCoreException { + if (art.equals(tag)) { + throw new TskCoreException("Cannot tag the same artifact: id" + art.getArtifactID() ); + } + BlackboardAttribute attrLink = new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID(), + "", art.getArtifactID()); + tag.addAttribute(attrLink); + } + + /** + * Get tag artifacts linked to the artifact + * @param art artifact to get tags for + * @return list of children artifacts or an empty list + * @throws TskCoreException exception thrown if a critical error occurs + * within tsk core and child artifact could not be queried + */ + List getTagArtifacts(BlackboardArtifact art) throws TskCoreException { + return skCase.getBlackboardArtifacts(ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT, art.getArtifactID()); + } } \ No newline at end of file diff --git a/DataModel/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java b/DataModel/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java index cba45b4b0f..2a7c4c9849 100644 --- a/DataModel/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java +++ b/DataModel/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java @@ -68,13 +68,13 @@ public class RootContentChildren extends AbstractContentChildren { break; //TODO check - case TSK_BOOKMARK_FILE: + case TSK_TAG_FILE: if (o instanceof Bookmarks) this.refreshKey(o); break; //TODO check - case TSK_BOOKMARK_ARTIFACT: + case TSK_TAG_ARTIFACT: if (o instanceof Bookmarks) this.refreshKey(o); break; diff --git a/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/FileBookmarkAction.java b/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/FileBookmarkAction.java index cd0fd77df5..fa0d0c7dc4 100644 --- a/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/FileBookmarkAction.java +++ b/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/FileBookmarkAction.java @@ -37,11 +37,13 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Action on a file that bookmarks a file and reloads the bookmark view. * Supports bookmarking of a fs file, directory and layout file and layout - * directory (virtual files/dirs for unalloc content) + * directory (virtual files/dirs for unalloc content) TODO add use enters + * description and hierarchy (TSK_TAG_NAME with slashes) */ public class FileBookmarkAction extends AbstractAction { private static final Logger logger = Logger.getLogger(FileBookmarkAction.class.getName()); + private static final String BOOKMARKS_ROOT_NAME = "Bookmarks"; //content to bookmark (AbstractFile) private AbstractFile bookmarkFile; private final InitializeBookmarkFileV initializer = new InitializeBookmarkFileV(); @@ -52,7 +54,6 @@ public class FileBookmarkAction extends AbstractAction { bookmarkFile = content.accept(initializer); this.setEnabled(bookmarkFile != null); - } /** @@ -95,20 +96,23 @@ public class FileBookmarkAction extends AbstractAction { private void refreshView() { DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance(); - viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_BOOKMARK_FILE); + viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE); + viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT); } private boolean doBookmarkFile(AbstractFile file) { try { - //TODO popup a dialog and allow user to enter category and description - //with the currently present categories and descrptions pre-populated (pull-downs) - - final BlackboardArtifact bookArt = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_BOOKMARK_FILE); + //TODO popup a dialog and allow user to enter description + //and optional bookmark name (TSK_TAG_NAME) with slashes representating hierarchy + //should always start with "Bookmarks" + final BlackboardArtifact bookArt = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE); List attrs = new ArrayList(); - BlackboardAttribute attr1 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), - "", "", "category1"); + + + BlackboardAttribute attr1 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID(), + "", BOOKMARKS_ROOT_NAME); BlackboardAttribute attr2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID(), - "", "", "description2"); + "", "No Description"); attrs.add(attr1); attrs.add(attr2); bookArt.addAttributes(attrs);