add tag actions to user created events.

cleanup related files
This commit is contained in:
millmanorama 2019-03-12 14:31:04 +01:00
parent f8134a3d82
commit 671f95c0e7
5 changed files with 76 additions and 97 deletions

View File

@ -51,7 +51,7 @@ public abstract class DisplayableItemNode extends AbstractNode {
*
* @throws TskCoreException
*/
static AbstractFile findLinked(BlackboardArtifact artifact) throws TskCoreException {
protected static AbstractFile findLinked(BlackboardArtifact artifact) throws TskCoreException {
BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID));
if (pathIDAttribute != null) {
long contentID = pathIDAttribute.getValueLong();

View File

@ -59,7 +59,6 @@ import org.openide.windows.RetainLocation;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.actions.AddBookmarkTagAction;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
import org.sleuthkit.autopsy.corecomponents.DataContentPanel;
import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
@ -198,9 +197,6 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
contentViewerPanel.setNode(null);
}
});
} catch (NoCurrentCaseException ex) {
//Since the case is closed, the user probably doesn't care about this, just log it as a precaution.
logger.log(Level.SEVERE, "There was no case open to lookup the Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
Platform.runLater(() -> {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2018 Basis Technology Corp.
* Copyright 2011-2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,9 +21,12 @@ package org.sleuthkit.autopsy.timeline.explorernodes;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.swing.Action;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
@ -31,9 +34,11 @@ import org.openide.nodes.Children;
import org.openide.nodes.PropertySupport;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory;
@ -46,7 +51,6 @@ import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.autopsy.timeline.ui.EventTypeUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
@ -59,17 +63,32 @@ public class EventNode extends DisplayableItemNode {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(EventNode.class.getName());
private static final Logger logger = Logger.getLogger(EventNode.class.getName());
private final TimelineEvent event;
EventNode(TimelineEvent event, Content file, BlackboardArtifact artifact) {
/**
* Construct an EvetNode for an event with a Content and a
* BlackboardArtifact in its lookup.
*
* @param event The event this node is for.
* @param file The Content the artifact for this event is derived form.
* Not Null.
* @param artifact The artifact this event is derived from. Not Null.
*/
EventNode(@Nonnull TimelineEvent event, @Nonnull Content file, @Nonnull BlackboardArtifact artifact) {
super(Children.LEAF, Lookups.fixed(event, file, artifact));
this.event = event;
this.setIconBaseWithExtension(EventTypeUtils.getImagePath(event.getEventType())); // NON-NLS
}
EventNode(TimelineEvent event, Content file) {
/**
* Construct an EvetNode for an event with a Content in its lookup.
*
* @param event The event this node is for.
* @param file The Content this event is derived directly from. Not Null.
*/
EventNode(@Nonnull TimelineEvent event, @Nonnull Content file) {
super(Children.LEAF, Lookups.fixed(event, file));
this.event = event;
this.setIconBaseWithExtension(EventTypeUtils.getImagePath(event.getEventType())); // NON-NLS
@ -117,40 +136,43 @@ public class EventNode extends DisplayableItemNode {
"EventNode.getAction.linkedFileMessage=There was a problem getting actions for the selected result. "
+ " The 'View File in Timeline' action will not be available."})
public Action[] getActions(boolean context) {
Action[] superActions = super.getActions(context);
List<Action> actionsList = new ArrayList<>();
actionsList.addAll(Arrays.asList(superActions));
final Content sourceFile = getLookup().lookup(Content.class);
Collections.addAll(actionsList, super.getActions(context));
/*
* if this event is derived from an artifact, add actions to view the
* If this event is derived from an artifact, add actions to view the
* source file and a "linked" file, if present.
*/
final BlackboardArtifact artifact = getLookup().lookup(BlackboardArtifact.class);
final Content sourceFile = getLookup().lookup(Content.class);
if (artifact != null) {
try {
//find a linked file such as a downloaded file.
AbstractFile linkedfile = findLinked(artifact);
if (linkedfile != null) {
actionsList.add(ViewFileInTimelineAction.createViewFileAction(linkedfile));
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
logger.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
MessageNotifyUtil.Notify.error(Bundle.EventNode_getAction_errorTitle(), Bundle.EventNode_getAction_linkedFileMessage());
}
//if this event has associated content, add the action to view the content in the timeline
if (null != sourceFile) {
//add the action to view the content in the timeline, only for abstract files ( ie with times)
if (sourceFile instanceof AbstractFile) {
actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction((AbstractFile) sourceFile));
}
}
}
//get default actions for the source file
final List<Action> factoryActions = DataModelActionsFactory.getActions(sourceFile, artifact != null);
List<Action> factoryActions = DataModelActionsFactory.getActions(sourceFile, artifact != null);
actionsList.addAll(factoryActions);
if (factoryActions.isEmpty()) { // if there were no factory supplied actions, at least add the tagging actions.
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
if (isExactlyOneArtifactSelected()) {
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
}
actionsList.addAll(ContextMenuExtensionPoint.getActions());
}
return actionsList.toArray(new Action[actionsList.size()]);
}
@ -190,7 +212,7 @@ public class EventNode extends DisplayableItemNode {
try {
setValue(getDateTimeString());
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
LOGGER.log(Level.SEVERE, "Unexpected error setting date/time property on EventNode explorer node", ex); //NON-NLS
logger.log(Level.SEVERE, "Unexpected error setting date/time property on EventNode explorer node", ex); //NON-NLS
}
});
@ -202,10 +224,10 @@ public class EventNode extends DisplayableItemNode {
}
@Override
public void setValue(String t) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
public void setValue(String newValue) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String oldValue = getValue();
value = t;
firePropertyChange("time", oldValue, t); // NON-NLS
value = newValue;
firePropertyChange("time", oldValue, newValue); // NON-NLS
}
}
@ -216,19 +238,18 @@ public class EventNode extends DisplayableItemNode {
* @param eventID The ID of the event this node is for.
* @param eventsModel The model that provides access to the events DB.
*
* @return An EventNode with the file (and artifact) backing this event in
* its lookup.
* @return An EventNode with the content (and possible artifact) backing
* this event in its lookup.
*/
public static EventNode createEventNode(final Long eventID, FilteredEventsModel eventsModel) throws TskCoreException, NoCurrentCaseException {
public static EventNode createEventNode(final Long eventID, FilteredEventsModel eventsModel) throws TskCoreException {
SleuthkitCase sleuthkitCase = eventsModel.getSleuthkitCase();
SleuthkitCase sleuthkitCase = Case.getCurrentCaseThrows().getSleuthkitCase();
try {
/*
* Look up the event by id and creata an EventNode with the
* appropriate data in the lookup.
* Look up the event by id and creata an EventNode with the appropriate
* data in the lookup.
*/
final TimelineEvent eventById = eventsModel.getEventById(eventID);
Content file = sleuthkitCase.getContentById(eventById.getFileObjID());
if (eventById.getArtifactID().isPresent()) {
@ -237,34 +258,11 @@ public class EventNode extends DisplayableItemNode {
} else {
return new EventNode(eventById, file);
}
} catch (TskCoreException ex) {
throw new TskCoreException("Error getting event by id.", ex);
}
}
/**
* this code started as a cut and past of
* DataResultFilterNode.GetPopupActionsDisplayableItemNodeVisitor.findLinked(BlackboardArtifactNode
* ba)
*
* It is now in DisplayableItemNode too, but is not accesible across
* packages
*
* @param artifact
*
* @return
*/
static AbstractFile findLinked(BlackboardArtifact artifact) throws TskCoreException {
BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID));
if (pathIDAttribute != null) {
long contentID = pathIDAttribute.getValueLong();
if (contentID != -1) {
return artifact.getSleuthkitCase().getAbstractFileById(contentID);
}
}
return null;
private static boolean isExactlyOneArtifactSelected() {
final Collection<BlackboardArtifact> selectedArtifactsList
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
return selectedArtifactsList.size() == 1;
}
}

View File

@ -29,7 +29,6 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
@ -85,8 +84,7 @@ public class EventRootNode extends DisplayableItemNode {
* filteredEvents is used to lookup the events from their IDs
*/
private final FilteredEventsModel filteredEvents;
private Map<Long, Node > nodesMap = new HashMap<>();
private final Map<Long, Node> nodesMap = new HashMap<>();
EventNodeChildFactory(Collection<Long> eventIds, FilteredEventsModel filteredEvents) {
this.eventIDs = eventIds;
@ -101,15 +99,11 @@ public class EventRootNode extends DisplayableItemNode {
*/
if (eventIDs.size() < MAX_EVENTS_TO_DISPLAY) {
for (Long eventId : eventIDs) {
if (!nodesMap.containsKey(eventId)) {
nodesMap.put(eventId, createNode(eventId));
}
nodesMap.computeIfAbsent(eventId, this::createNode);
toPopulate.add(eventId);
}
} else {
if (!nodesMap.containsKey(-1L)) {
nodesMap.put(-1L, createNode(-1L));
}
nodesMap.computeIfAbsent(-1L, this::createNode);
toPopulate.add(-1L);
}
return true;
@ -121,7 +115,6 @@ public class EventRootNode extends DisplayableItemNode {
}
private Node createNode(Long eventID) {
if (eventID < 0) {
/*
* If the eventId is a the special value ( -1 ), return a node
@ -131,17 +124,13 @@ public class EventRootNode extends DisplayableItemNode {
} else {
try {
return EventNode.createEventNode(eventID, filteredEvents);
} catch (NoCurrentCaseException ex) {
//Since the case is closed, the user probably doesn't care about this, just log it as a precaution.
LOGGER.log(Level.SEVERE, "There was no case open to lookup the Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
return null;
} catch (TskCoreException ex) {
/*
* Just log it: There might be lots of these errors, and we
* don't want to flood the user with notifications. It will
* be obvious the UI is broken anyways
*/
LOGGER.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Error creating explorer node for event id " + eventID + ".", ex); // NON-NLS
return null;
}
}

View File

@ -78,7 +78,6 @@ import org.controlsfx.control.action.ActionUtils;
import org.openide.awt.Actions;
import org.openide.util.NbBundle;
import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
@ -676,14 +675,11 @@ class ListTimeline extends BorderPane {
}
}
}
};
}
//show new context menu.
new ContextMenu(menuItems.toArray(new MenuItem[menuItems.size()]))
.show(this, contextMenuEvent.getScreenX(), contextMenuEvent.getScreenY());
} catch (NoCurrentCaseException ex) {
//Since the case is closed, the user probably doesn't care about this, just log it as a precaution.
logger.log(Level.SEVERE, "There was no case open to lookup the Sleuthkit object backing a TimelineEvent.", ex); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a TimelineEvent.", ex); //NON-NLS
Platform.runLater(() -> {