mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
First draft of implementation of multi-select tagging and export
This commit is contained in:
parent
655e7e5787
commit
a5a69b8036
@ -62,7 +62,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
ov.setAllowedDropActions(DnDConstants.ACTION_NONE);
|
||||
|
||||
// only allow one item to be selected at a time
|
||||
ov.getOutline().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
|
||||
// don't show the root node
|
||||
ov.getOutline().setRootVisible(false);
|
||||
|
@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -33,6 +35,14 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
|
||||
private static Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName());
|
||||
|
||||
/**
|
||||
* These Actions are class instances to support multi-selection of nodes corresponding to AbstractFiles.
|
||||
* They must be a class instances because org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick
|
||||
* up an Action if every selected node returns a reference to it from Node.getActions(boolean).
|
||||
*/
|
||||
private static TagAbstractFileAction tagAction = new TagAbstractFileAction();
|
||||
private static ExtractAction extractAction = new ExtractAction();
|
||||
|
||||
/**
|
||||
* @param <T> type of the AbstractFile data to encapsulate
|
||||
* @param abstractFile file to encapsulate
|
||||
@ -153,8 +163,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fill map with AbstractFile properties
|
||||
*
|
||||
@ -191,8 +200,15 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
map.put(AbstractFilePropertyType.MD5HASH.toString(), content.getMd5Hash() == null ? "" : content.getMd5Hash());
|
||||
}
|
||||
|
||||
|
||||
static String getContentDisplayName(AbstractFile file) {
|
||||
protected static TagAbstractFileAction getTagAbstractFileActionInstance() {
|
||||
return tagAction;
|
||||
}
|
||||
|
||||
protected static ExtractAction getExtractActionInstance() {
|
||||
return extractAction;
|
||||
}
|
||||
|
||||
protected static String getContentDisplayName(AbstractFile file) {
|
||||
String name = file.getName();
|
||||
if (name.equals("..")) {
|
||||
name = DirectoryNode.DOTDOTDIR;
|
||||
@ -201,4 +217,4 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children.Keys;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
|
@ -23,7 +23,6 @@ import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
@ -34,7 +33,7 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
||||
* are more directories.
|
||||
*/
|
||||
public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
|
||||
|
||||
|
||||
public static final String DOTDOTDIR = "[parent folder]";
|
||||
public static final String DOTDIR = "[current folder]";
|
||||
|
||||
@ -67,16 +66,16 @@ public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
|
||||
*/
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
List<Action> actions = new ArrayList<>();
|
||||
if (!getDirectoryBrowseMode()) {
|
||||
actions.add(new ViewContextAction("View File in Directory", this));
|
||||
actions.add(null); // creates a menu separator
|
||||
}
|
||||
actions.add(new NewWindowViewAction("View in New Window", this));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new ExtractAction("Extract Directory", this));
|
||||
actions.add(getExtractActionInstance());
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new TagAction(this));
|
||||
actions.add(getTagAbstractFileActionInstance());
|
||||
return actions.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
|
@ -21,14 +21,13 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.getExtractActionInstance;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.FsContent;
|
||||
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
||||
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
||||
|
||||
@ -37,7 +36,7 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
||||
* files children.
|
||||
*/
|
||||
public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
|
||||
|
||||
/**
|
||||
* @param file underlying Content
|
||||
*/
|
||||
@ -74,7 +73,7 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
*/
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
List<Action> actionsList = new ArrayList<Action>();
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
if (!this.getDirectoryBrowseMode()) {
|
||||
actionsList.add(new ViewContextAction("View File in Directory", this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
@ -82,10 +81,10 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
||||
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new ExtractAction("Extract File", this));
|
||||
actionsList.add(getExtractActionInstance());
|
||||
actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new TagAction(this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(getTagAbstractFileActionInstance());
|
||||
return actionsList.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
@ -166,7 +165,6 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
}
|
||||
// Else return the default
|
||||
return "org/sleuthkit/autopsy/images/file-icon.png";
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,11 +24,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.getExtractActionInstance;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.getTagAbstractFileActionInstance;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
||||
import org.sleuthkit.datamodel.LayoutFile;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
@ -104,14 +104,12 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
|
||||
@Override
|
||||
public Action[] getActions(boolean context) {
|
||||
List<Action> actionsList = new ArrayList<Action>();
|
||||
|
||||
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
||||
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new ExtractAction("Extract File", content));
|
||||
actionsList.add(getExtractActionInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new TagAction(content));
|
||||
|
||||
actionsList.add(getTagAbstractFileActionInstance());
|
||||
return actionsList.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
|
@ -25,14 +25,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.Sheet;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.getExtractActionInstance;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.getTagAbstractFileActionInstance;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode.TYPE;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.LocalFile;
|
||||
|
||||
/**
|
||||
* A Node for a LocalFile or DerivedFile content object.
|
||||
@ -86,16 +86,14 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
||||
|
||||
@Override
|
||||
public Action[] getActions(boolean context) {
|
||||
List<Action> actionsList = new ArrayList<Action>();
|
||||
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
||||
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new ExtractAction("Extract", content)); //might not need this actions - already local file
|
||||
actionsList.add(getExtractActionInstance());
|
||||
actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new TagAction(content));
|
||||
|
||||
actionsList.add(getTagAbstractFileActionInstance());
|
||||
return actionsList.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ import java.awt.event.ActionEvent;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -656,36 +655,4 @@ public class Tags implements AutopsyVisitableItem {
|
||||
|
||||
return tagNames;
|
||||
}
|
||||
|
||||
public interface Taggable {
|
||||
void createTag(String name, String comment);
|
||||
}
|
||||
|
||||
public static class TaggableFile implements Taggable {
|
||||
|
||||
private AbstractFile file;
|
||||
|
||||
public TaggableFile(AbstractFile file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTag(String name, String comment) {
|
||||
Tags.createTag(file, name, comment);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TaggableBlackboardArtifact implements Taggable {
|
||||
|
||||
private BlackboardArtifact bba;
|
||||
|
||||
public TaggableBlackboardArtifact(BlackboardArtifact bba) {
|
||||
this.bba = bba;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTag(String name, String comment) {
|
||||
Tags.createTag(bba, name, comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ import java.util.Map;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.getExtractActionInstance;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
@ -76,16 +76,15 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
|
||||
*/
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
|
||||
List<Action> actions = new ArrayList<>();
|
||||
actions.add(new NewWindowViewAction("View in New Window", this));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new ExtractAction("Extract Directory", this));
|
||||
actions.add(getExtractActionInstance());
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new TagAction(this));
|
||||
actions.add(getTagAbstractFileActionInstance());
|
||||
return actions.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet s = super.createSheet();
|
||||
|
@ -81,6 +81,15 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
*/
|
||||
public class DataResultFilterNode extends FilterNode {
|
||||
|
||||
/**
|
||||
* These are class instances to support multi-selection of nodes corresponding to AbstractFiles and BlackboardArtifacts.
|
||||
* They are required because org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every selected
|
||||
* node returns a reference to it from Node.getActions(boolean).
|
||||
*/
|
||||
private final static Action extractAction = new ExtractAction();
|
||||
private final static Action fileTagAction = new TagAbstractFileAction();
|
||||
private final static Action resultTagAction = new TagBlackboardArtifactAction();
|
||||
|
||||
private ExplorerManager sourceEm;
|
||||
private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV;
|
||||
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV;
|
||||
@ -105,7 +114,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal();
|
||||
actions.addAll(originalNode.accept(getActionsDIV));
|
||||
@ -167,7 +176,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
//TODO all actions need to be consolidated in single place!
|
||||
//they should be set in individual Node subclass and using a utility to get Actions per Content sub-type
|
||||
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
//merge predefined specific node actions if bban subclasses have their own
|
||||
for (Action a : ban.getActions(true)) {
|
||||
@ -197,15 +206,15 @@ public class DataResultFilterNode extends FilterNode {
|
||||
actions.add(new NewWindowViewAction("View in New Window", fn));
|
||||
actions.add(new ExternalViewerAction("Open in External Viewer", fn));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new ExtractAction("Extract File", new FileNode(f)));
|
||||
actions.add(extractAction);
|
||||
actions.add(new HashSearchAction("Search for files with the same MD5 hash", fn));
|
||||
|
||||
//add file/result tag if itself is not a tag
|
||||
if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
|
||||
&& artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new TagAction(f));
|
||||
actions.add(new TagAction(ba));
|
||||
actions.add(fileTagAction);
|
||||
actions.add(resultTagAction);
|
||||
}
|
||||
}
|
||||
if ((d = ban.getLookup().lookup(Directory.class)) != null) {
|
||||
@ -214,14 +223,14 @@ public class DataResultFilterNode extends FilterNode {
|
||||
actions.add(new NewWindowViewAction("View in New Window", dn));
|
||||
actions.add(new ExternalViewerAction("Open in External Viewer", dn));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new ExtractAction("Extract Directory", dn));
|
||||
actions.add(extractAction);
|
||||
|
||||
//add file/result tag if itself is not a tag
|
||||
if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
|
||||
&& artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new TagAction(d));
|
||||
actions.add(new TagAction(ba));
|
||||
actions.add(fileTagAction);
|
||||
actions.add(resultTagAction);
|
||||
}
|
||||
}
|
||||
if ((vd = ban.getLookup().lookup(VirtualDirectory.class)) != null) {
|
||||
@ -230,14 +239,14 @@ public class DataResultFilterNode extends FilterNode {
|
||||
actions.add(new NewWindowViewAction("View in New Window", dn));
|
||||
actions.add(new ExternalViewerAction("Open in External Viewer", dn));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new ExtractAction("Extract Directory", dn));
|
||||
actions.add(extractAction);
|
||||
|
||||
//add file/result tag if itself is not a tag
|
||||
if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
|
||||
&& artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new TagAction(d));
|
||||
actions.add(new TagAction(ba));
|
||||
actions.add(fileTagAction);
|
||||
actions.add(resultTagAction);
|
||||
}
|
||||
} else if ((lf = ban.getLookup().lookup(LayoutFile.class)) != null) {
|
||||
LayoutFileNode lfn = new LayoutFileNode(lf);
|
||||
@ -245,14 +254,14 @@ public class DataResultFilterNode extends FilterNode {
|
||||
actions.add(new NewWindowViewAction("View in New Window", lfn));
|
||||
actions.add(new ExternalViewerAction("Open in External Viewer", lfn));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new ExtractAction("Extract File", lfn));
|
||||
actions.add(extractAction);
|
||||
|
||||
//add tag if itself is not a tag
|
||||
if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
|
||||
&& artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new TagAction(lf));
|
||||
actions.add(new TagAction(ba));
|
||||
actions.add(fileTagAction);
|
||||
actions.add(resultTagAction);
|
||||
}
|
||||
} else if ((locF = ban.getLookup().lookup(LocalFile.class)) != null
|
||||
|| (locF = ban.getLookup().lookup(DerivedFile.class)) != null) {
|
||||
@ -261,14 +270,14 @@ public class DataResultFilterNode extends FilterNode {
|
||||
actions.add(new NewWindowViewAction("View in New Window", locfn));
|
||||
actions.add(new ExternalViewerAction("Open in External Viewer", locfn));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new ExtractAction("Extract File", locfn));
|
||||
actions.add(extractAction);
|
||||
|
||||
//add tag if itself is not a tag
|
||||
if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
|
||||
&& artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new TagAction(lf));
|
||||
actions.add(new TagAction(ba));
|
||||
actions.add(fileTagAction);
|
||||
actions.add(resultTagAction);
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +287,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
@Override
|
||||
protected List<Action> defaultVisit(DisplayableItemNode ditem) {
|
||||
//preserve the default node's actions
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
for (Action action : ditem.getActions(true)) {
|
||||
actions.add(action);
|
||||
|
@ -47,6 +47,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
class DirectoryTreeFilterNode extends FilterNode {
|
||||
|
||||
private static final Action collapseAll = new CollapseAction("Collapse All");
|
||||
private static final Action extractAction = new ExtractAction();
|
||||
private static final Logger logger = Logger.getLogger(DirectoryTreeFilterNode.class.getName());
|
||||
|
||||
/**
|
||||
@ -99,8 +100,7 @@ class DirectoryTreeFilterNode extends FilterNode {
|
||||
//extract dir action
|
||||
Directory dir = this.getLookup().lookup(Directory.class);
|
||||
if (dir != null) {
|
||||
actions.add(new ExtractAction("Extract Directory",
|
||||
getOriginal()));
|
||||
actions.add(extractAction);
|
||||
}
|
||||
|
||||
// file search action
|
||||
|
@ -47,6 +47,13 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
|
||||
public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? extends Action>> {
|
||||
/**
|
||||
* These are class instances to support multi-selection of nodes corresponding to AbstractFiles and BlackboardArtifacts.
|
||||
* They are required because org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every selected
|
||||
* node returns a reference to it from Node.getActions(boolean).
|
||||
*/
|
||||
private static Action extractAction = new ExtractAction();
|
||||
private static Action tagAction = new TagAbstractFileAction();
|
||||
|
||||
private static ExplorerNodeActionVisitor instance = new ExplorerNodeActionVisitor();
|
||||
|
||||
@ -101,39 +108,39 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
|
||||
@Override
|
||||
public List<? extends Action> visit(final Directory d) {
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
actions.add(new TagAction(d));
|
||||
actions.add(tagAction);
|
||||
return actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Action> visit(final VirtualDirectory d) {
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
actions.add(new TagAction(d));
|
||||
actions.add(new ExtractAction("Extract Directory", d));
|
||||
actions.add(extractAction);
|
||||
actions.add(tagAction);
|
||||
return actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Action> visit(final DerivedFile d) {
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
actions.add(new ExtractAction("Extract File", d));
|
||||
actions.add(new TagAction(d));
|
||||
actions.add(extractAction);
|
||||
actions.add(tagAction);
|
||||
return actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Action> visit(final LocalFile d) {
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
actions.add(new ExtractAction("Extract File", d));
|
||||
actions.add(new TagAction(d));
|
||||
actions.add(extractAction);
|
||||
actions.add(tagAction);
|
||||
return actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Action> visit(final org.sleuthkit.datamodel.File d) {
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
actions.add(new ExtractAction("Extract File", d));
|
||||
actions.add(new TagAction(d));
|
||||
actions.add(extractAction);
|
||||
actions.add(tagAction);
|
||||
return actions;
|
||||
}
|
||||
|
||||
|
@ -32,11 +32,15 @@ import org.netbeans.api.progress.ProgressHandle;
|
||||
import org.netbeans.api.progress.ProgressHandleFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.Cancellable;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentVisitor;
|
||||
@ -47,66 +51,12 @@ import org.sleuthkit.datamodel.Directory;
|
||||
*/
|
||||
public final class ExtractAction extends AbstractAction {
|
||||
|
||||
private static final InitializeContentVisitor initializeCV = new InitializeContentVisitor();
|
||||
private AbstractFile content;
|
||||
private Logger logger = Logger.getLogger(ExtractAction.class.getName());
|
||||
|
||||
public ExtractAction(String title, Node contentNode) {
|
||||
super(title);
|
||||
Content tempContent = contentNode.getLookup().lookup(Content.class);
|
||||
|
||||
this.content = tempContent.accept(initializeCV);
|
||||
this.setEnabled(content != null);
|
||||
public ExtractAction() {
|
||||
super("Export");
|
||||
}
|
||||
|
||||
public ExtractAction(String title, Content content) {
|
||||
super(title);
|
||||
|
||||
this.content = content.accept(initializeCV);
|
||||
this.setEnabled(this.content != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FsContent if it is supported, otherwise null
|
||||
*/
|
||||
private static class InitializeContentVisitor extends ContentVisitor.Default<AbstractFile> {
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.File f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.LayoutFile lf) {
|
||||
return lf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.DerivedFile df) {
|
||||
return df;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.LocalFile lf) {
|
||||
return lf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.VirtualDirectory vd) {
|
||||
return vd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(Directory dir) {
|
||||
return ContentUtils.isDotDirectory(dir) ? null : dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFile defaultVisit(Content cntnt) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks user to choose destination, then extracts content/directory to
|
||||
* destination (recursing on directories)
|
||||
@ -114,10 +64,35 @@ public final class ExtractAction extends AbstractAction {
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
DataResultViewerTable resultViewer = (DataResultViewerTable)Lookup.getDefault().lookup(DataResultViewer.class);
|
||||
if (null == resultViewer) {
|
||||
Logger.getLogger(TagAction.class.getName()).log(Level.SEVERE, "Could not get DataResultViewerTable from Lookup");
|
||||
return;
|
||||
}
|
||||
|
||||
Node[] selectedNodes = resultViewer.getExplorerManager().getSelectedNodes();
|
||||
if (selectedNodes.length <= 0) {
|
||||
Logger.getLogger(TagAction.class.getName()).log(Level.SEVERE, "Tried to perform tagging of Nodes with no Nodes selected");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Node node : selectedNodes) {
|
||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||
if (null != file) {
|
||||
extractFile(e, file);
|
||||
}
|
||||
else {
|
||||
// RJCTODO
|
||||
// Logger.getLogger(org.sleuthkit.autopsy.directorytree.TagAbstractFileAction.TagAbstractFileMenu.class.getName()).log(Level.SEVERE, "Node not associated with an AbstractFile object");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractFile(ActionEvent e, AbstractFile file) {
|
||||
// Get content and check that it's okay to overwrite existing content
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory()));
|
||||
fc.setSelectedFile(new File(this.content.getName()));
|
||||
fc.setSelectedFile(new File(file.getName()));
|
||||
int returnValue = fc.showSaveDialog((Component) e.getSource());
|
||||
|
||||
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
||||
@ -144,12 +119,12 @@ public final class ExtractAction extends AbstractAction {
|
||||
|
||||
try {
|
||||
ExtractFileThread extract = new ExtractFileThread();
|
||||
extract.init(this.content, e, destination);
|
||||
extract.init(file, e, destination);
|
||||
extract.execute();
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.WARNING, "Unable to start background thread.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ExtractFileThread extends SwingWorker<Object,Void> {
|
||||
@ -230,6 +205,5 @@ public final class ExtractAction extends AbstractAction {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
51
Core/src/org/sleuthkit/autopsy/directorytree/TagAbstractFileAction.java
Executable file
51
Core/src/org/sleuthkit/autopsy/directorytree/TagAbstractFileAction.java
Executable file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.util.logging.Level;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
public class TagAbstractFileAction extends TagAction {
|
||||
@Override
|
||||
protected TagMenu getTagMenu(Node[] selectedNodes) {
|
||||
return new TagAbstractFileMenu(selectedNodes);
|
||||
}
|
||||
|
||||
private static class TagAbstractFileMenu extends TagMenu {
|
||||
public TagAbstractFileMenu(Node[] nodes) {
|
||||
super((nodes.length > 1 ? "Tag Files" : "Tag File"), nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tagNodes(String tagName, String comment) {
|
||||
for (Node node : getNodes()) {
|
||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||
if (null != file) {
|
||||
Tags.createTag(file, tagName, comment);
|
||||
}
|
||||
else {
|
||||
Logger.getLogger(org.sleuthkit.autopsy.directorytree.TagAbstractFileAction.TagAbstractFileMenu.class.getName()).log(Level.SEVERE, "Node not associated with an AbstractFile object");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -21,102 +21,38 @@ package org.sleuthkit.autopsy.directorytree;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.actions.Presenter;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentVisitor;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
|
||||
/**
|
||||
* Action on a file or artifact that adds a tag and
|
||||
* reloads the directory tree. Supports tagging of AbstractFiles and
|
||||
* BlackboardArtifacts.
|
||||
*
|
||||
* TODO add use enters description and hierarchy (TSK_TAG_NAME with slashes)
|
||||
* Action on a file or artifact that adds a tag and reloads the directory tree.
|
||||
* Supports tagging of AbstractFiles and BlackboardArtifacts.
|
||||
*/
|
||||
public class TagAction extends AbstractAction implements Presenter.Popup {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TagAction.class.getName());
|
||||
private JMenu tagMenu;
|
||||
private final InitializeBookmarkFileV initializer = new InitializeBookmarkFileV();
|
||||
|
||||
public TagAction(Node contentNode) {
|
||||
AbstractFile file = contentNode.getLookup().lookup(AbstractFile.class);
|
||||
if (file != null) {
|
||||
tagMenu = new TagMenu(file);
|
||||
return;
|
||||
}
|
||||
|
||||
BlackboardArtifact bba = contentNode.getLookup().lookup(BlackboardArtifact.class);
|
||||
if (bba != null) {
|
||||
tagMenu = new TagMenu(bba);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log(Level.SEVERE, "Tried to create a " + TagAction.class.getName()
|
||||
+ " using a Node whose lookup did not contain an AbstractFile or a BlackboardArtifact.");
|
||||
}
|
||||
|
||||
public TagAction(AbstractFile file) {
|
||||
tagMenu = new TagMenu(file);
|
||||
}
|
||||
|
||||
public TagAction(BlackboardArtifact bba) {
|
||||
tagMenu = new TagMenu(bba);
|
||||
}
|
||||
|
||||
public abstract class TagAction extends AbstractAction implements Presenter.Popup {
|
||||
@Override
|
||||
public JMenuItem getPopupPresenter() {
|
||||
return tagMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FsContent if it is supported, otherwise null
|
||||
*/
|
||||
private static class InitializeBookmarkFileV extends ContentVisitor.Default<AbstractFile> {
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.File f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.LayoutFile lf) {
|
||||
return lf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.DerivedFile lf) {
|
||||
return lf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.LocalFile lf) {
|
||||
return lf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(org.sleuthkit.datamodel.VirtualDirectory ld) {
|
||||
return ld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFile visit(Directory dir) {
|
||||
return ContentUtils.isDotDirectory(dir) ? null : dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFile defaultVisit(Content cntnt) {
|
||||
DataResultViewerTable resultViewer = (DataResultViewerTable)Lookup.getDefault().lookup(DataResultViewer.class);
|
||||
if (null == resultViewer) {
|
||||
Logger.getLogger(TagAction.class.getName()).log(Level.SEVERE, "Could not get DataResultViewerTable from Lookup");
|
||||
return null;
|
||||
}
|
||||
|
||||
Node[] selectedNodes = resultViewer.getExplorerManager().getSelectedNodes();
|
||||
if (selectedNodes.length <= 0) {
|
||||
Logger.getLogger(TagAction.class.getName()).log(Level.SEVERE, "Tried to perform tagging of Nodes with no Nodes selected");
|
||||
return null;
|
||||
}
|
||||
|
||||
return getTagMenu(selectedNodes);
|
||||
}
|
||||
|
||||
protected abstract TagMenu getTagMenu(Node[] selectedNodes);
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// Do nothing - this action should never be performed
|
||||
|
@ -30,28 +30,50 @@ import javax.swing.JFrame;
|
||||
import javax.swing.KeyStroke;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags.Taggable;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* Tag dialog for tagging files and results. User enters an optional comment.
|
||||
*/
|
||||
public class TagAndCommentDialog extends JDialog {
|
||||
|
||||
private static final String TAG_ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png";
|
||||
private static final String BOOKMARK_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png";
|
||||
private static final String NO_TAG_MESSAGE = "No Tags";
|
||||
|
||||
private Taggable taggable;
|
||||
private static final String NO_TAG_MESSAGE = "No Tags";
|
||||
private String tagName = "";
|
||||
private String comment = "";
|
||||
|
||||
public static class CommentedTag {
|
||||
private String name;
|
||||
private String comment;
|
||||
|
||||
CommentedTag(String name, String comment) {
|
||||
this.name = name;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
|
||||
public static CommentedTag doDialog() {
|
||||
TagAndCommentDialog dialog = new TagAndCommentDialog();
|
||||
if (!dialog.tagName.isEmpty()) {
|
||||
return new CommentedTag(dialog.tagName, dialog.comment);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new form TagDialog
|
||||
*/
|
||||
public TagAndCommentDialog(Taggable taggable) {
|
||||
private TagAndCommentDialog() {
|
||||
super((JFrame)WindowManager.getDefault().getMainWindow(), "Tag and Comment", true);
|
||||
|
||||
this.taggable = taggable;
|
||||
|
||||
initComponents();
|
||||
|
||||
// Close the dialog when Esc is pressed
|
||||
@ -60,8 +82,8 @@ public class TagAndCommentDialog extends JDialog {
|
||||
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
|
||||
ActionMap actionMap = getRootPane().getActionMap();
|
||||
actionMap.put(cancelName, new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//doClose(RET_CANCEL);
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
@ -81,15 +103,10 @@ public class TagAndCommentDialog extends JDialog {
|
||||
|
||||
//center it
|
||||
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
|
||||
customizeComponent();
|
||||
|
||||
setVisible(true); // blocks
|
||||
}
|
||||
|
||||
private void customizeComponent() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
@ -195,22 +212,12 @@ public class TagAndCommentDialog extends JDialog {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
//doClose(RET_OK);
|
||||
|
||||
// get the selected tag and comment
|
||||
String selectedTag = (String)tagCombo.getSelectedItem();
|
||||
String comment = commentText.getText();
|
||||
|
||||
// create the tag
|
||||
taggable.createTag(selectedTag, comment);
|
||||
|
||||
refreshDirectoryTree();
|
||||
|
||||
tagName = (String)tagCombo.getSelectedItem();
|
||||
comment = commentText.getText();
|
||||
dispose();
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
//doClose(RET_CANCEL);
|
||||
dispose();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
@ -218,14 +225,12 @@ public class TagAndCommentDialog extends JDialog {
|
||||
* Closes the dialog
|
||||
*/
|
||||
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
|
||||
//doClose(RET_CANCEL);
|
||||
dispose();
|
||||
}//GEN-LAST:event_closeDialog
|
||||
|
||||
private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed
|
||||
String newTagName = CreateTagDialog.getNewTagNameDialog(null);
|
||||
if (newTagName != null) {
|
||||
//tagsModel.addElement(newTagName);
|
||||
tagCombo.addItem(newTagName);
|
||||
tagCombo.setSelectedItem(newTagName);
|
||||
}
|
||||
@ -240,12 +245,4 @@ public class TagAndCommentDialog extends JDialog {
|
||||
private javax.swing.JComboBox tagCombo;
|
||||
private javax.swing.JLabel tagLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
//private int returnStatus = RET_CANCEL;
|
||||
|
||||
private void refreshDirectoryTree() {
|
||||
//TODO instead should send event to node children, which will call its refresh() / refreshKeys()
|
||||
DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance();
|
||||
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE);
|
||||
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.util.logging.Level;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
public class TagBlackboardArtifactAction extends TagAction {
|
||||
@Override
|
||||
protected TagMenu getTagMenu(Node[] selectedNodes) {
|
||||
return new TagBlackboardArtifactMenu(selectedNodes);
|
||||
}
|
||||
|
||||
private static class TagBlackboardArtifactMenu extends TagMenu {
|
||||
public TagBlackboardArtifactMenu(Node[] nodes) {
|
||||
super((nodes.length > 1 ? "Tag Results" : "Tag Result"), nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tagNodes(String tagName, String comment) {
|
||||
for (Node node : getNodes()) {
|
||||
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
|
||||
if (null != artifact) {
|
||||
Tags.createTag(artifact, tagName, comment);
|
||||
}
|
||||
else {
|
||||
Logger.getLogger(org.sleuthkit.autopsy.directorytree.TagBlackboardArtifactAction.TagBlackboardArtifactMenu.class.getName()).log(Level.SEVERE, "Node not associated with a BlackboardArtifact object");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,39 +23,26 @@ import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags.Taggable;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags.TaggableBlackboardArtifact;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags.TaggableFile;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* The menu that results when one right-clicks on a file or artifact.
|
||||
*/
|
||||
public class TagMenu extends JMenu {
|
||||
public abstract class TagMenu extends JMenu {
|
||||
|
||||
private Taggable tagCreator;
|
||||
|
||||
public TagMenu(AbstractFile file) {
|
||||
super("Tag File");
|
||||
tagCreator = new TaggableFile(file);
|
||||
init();
|
||||
}
|
||||
|
||||
public TagMenu(BlackboardArtifact bba) {
|
||||
super("Tag Result");
|
||||
tagCreator = new TaggableBlackboardArtifact(bba);
|
||||
init();
|
||||
}
|
||||
private Node[] nodes;
|
||||
|
||||
private void init() {
|
||||
|
||||
// create the 'Quick Tag' menu and add it to the 'Tag File' menu
|
||||
public TagMenu(String menuItemText, Node[] selectedNodes) {
|
||||
super(menuItemText);
|
||||
this.nodes = selectedNodes;
|
||||
|
||||
// Create the 'Quick Tag' sub-menu and add it to the tag menu.
|
||||
JMenu quickTagMenu = new JMenu("Quick Tag");
|
||||
add(quickTagMenu);
|
||||
|
||||
// create the 'Quick Tag' sub-menu items and add them to the 'Quick Tag' menu
|
||||
add(quickTagMenu);
|
||||
|
||||
// Get the existing tag names.
|
||||
List<String> tagNames = Tags.getTagNames();
|
||||
if (tagNames.isEmpty()) {
|
||||
JMenuItem empty = new JMenuItem("No tags");
|
||||
@ -63,46 +50,56 @@ public class TagMenu extends JMenu {
|
||||
quickTagMenu.add(empty);
|
||||
}
|
||||
|
||||
// Add a menu item for each existing tag name to the 'Quick Tag' menu.
|
||||
for (final String tagName : tagNames) {
|
||||
JMenuItem tagItem = new JMenuItem(tagName);
|
||||
tagItem.addActionListener(new ActionListener() {
|
||||
JMenuItem tagNameItem = new JMenuItem(tagName);
|
||||
tagNameItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tagCreator.createTag(tagName, "");
|
||||
tagNodes(tagName, "");
|
||||
refreshDirectoryTree();
|
||||
}
|
||||
});
|
||||
quickTagMenu.add(tagItem);
|
||||
quickTagMenu.add(tagNameItem);
|
||||
}
|
||||
|
||||
quickTagMenu.addSeparator();
|
||||
|
||||
// create the 'New Tag' menu item
|
||||
// Create the 'New Tag' menu item and add it to the 'Quick Tag' menu.
|
||||
JMenuItem newTagMenuItem = new JMenuItem("New Tag");
|
||||
newTagMenuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String newTagName = CreateTagDialog.getNewTagNameDialog(null);
|
||||
if (newTagName != null) {
|
||||
tagCreator.createTag(newTagName, "");
|
||||
String tagName = CreateTagDialog.getNewTagNameDialog(null);
|
||||
if (tagName != null) {
|
||||
tagNodes(tagName, "");
|
||||
refreshDirectoryTree();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// add the 'New Tag' menu item to the 'Quick Tag' menu
|
||||
quickTagMenu.add(newTagMenuItem);
|
||||
|
||||
JMenuItem newTagItem = new JMenuItem("Tag and Comment");
|
||||
newTagItem.addActionListener(new ActionListener() {
|
||||
// Create the 'Tag and Comment' menu item and add it to the tag menu.
|
||||
JMenuItem tagAndCommentItem = new JMenuItem("Tag and Comment");
|
||||
tagAndCommentItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new TagAndCommentDialog(tagCreator);
|
||||
TagAndCommentDialog.CommentedTag commentedTag = TagAndCommentDialog.doDialog();
|
||||
if (null != commentedTag) {
|
||||
tagNodes(commentedTag.getName(), commentedTag.getComment());
|
||||
refreshDirectoryTree();
|
||||
}
|
||||
}
|
||||
});
|
||||
add(newTagItem);
|
||||
add(tagAndCommentItem);
|
||||
}
|
||||
|
||||
protected Node[] getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected abstract void tagNodes(String tagName, String comment);
|
||||
|
||||
private void refreshDirectoryTree() {
|
||||
//TODO instead should send event to node children, which will call its refresh() / refreshKeys()
|
||||
DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance();
|
||||
|
Loading…
x
Reference in New Issue
Block a user