From f98cf3e6007ff383ee76e7211e0fbece49fa657e Mon Sep 17 00:00:00 2001 From: jmillman Date: Mon, 19 Oct 2015 16:36:12 -0400 Subject: [PATCH] WIP towards view artifacts in timeline action --- .../datamodel/ViewInTimeLineAction.java | 39 ++++++++++++++----- .../directorytree/DataResultFilterNode.java | 18 +++++++++ .../eventtype/ArtifactEventType.java | 12 +++++- .../datamodel/eventtype/EventType.java | 6 ++- .../autopsy/timeline/db/EventsRepository.java | 2 +- 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ViewInTimeLineAction.java b/Core/src/org/sleuthkit/autopsy/datamodel/ViewInTimeLineAction.java index 4bbaad7f3b..64faf03508 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ViewInTimeLineAction.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ViewInTimeLineAction.java @@ -6,20 +6,26 @@ package org.sleuthkit.autopsy.datamodel; import java.awt.event.ActionEvent; -import java.util.Collection; -import java.util.LongSummaryStatistics; -import java.util.stream.LongStream; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.swing.AbstractAction; import org.joda.time.Interval; +import org.openide.util.Exceptions; import org.openide.util.Utilities; import org.openide.util.actions.SystemAction; import org.sleuthkit.autopsy.timeline.OpenTimelineAction; +import org.sleuthkit.autopsy.timeline.datamodel.eventtype.ArtifactEventType; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.TskCoreException; /** * */ -class ViewInTimeLineAction extends AbstractAction { +public class ViewInTimeLineAction extends AbstractAction { // This class is a singleton to support multi-selection of nodes, since // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every @@ -39,13 +45,28 @@ class ViewInTimeLineAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { - Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); + TreeSet timestamps = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class).stream() + .flatMap(file -> Stream.of(file.getAtime(), file.getCrtime(), file.getCtime(), file.getMtime())) + .collect(Collectors.toCollection(TreeSet::new)); - LongSummaryStatistics summaryStatistics = selectedFiles.stream() - .flatMapToLong(file -> LongStream.of(file.getAtime(), file.getCrtime(), file.getCtime(), file.getMtime())) - .summaryStatistics(); + //for each artifact, get all datetime attributes for that artifact type + for (BlackboardArtifact bbart : Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)) { + Set attributeTypes = ArtifactEventType.getAllArtifactEventTypes().stream() + .filter(artEventType -> bbart.getArtifactTypeID() == artEventType.getArtifactType().getTypeID()) + .map(ArtifactEventType::getDateTimeAttrubuteType) + .collect(Collectors.toSet()); - Interval interval = new Interval(summaryStatistics.getMin() * 1000, 1 + summaryStatistics.getMax() * 1000); + for (BlackboardAttribute.ATTRIBUTE_TYPE type : attributeTypes) { + try { + Set collect1 = bbart.getAttributes(type).stream().map(BlackboardAttribute::getValueLong).collect(Collectors.toSet()); + timestamps.addAll(collect1); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } + } + } + + Interval interval = new Interval(timestamps.first() * 1000, 1 + timestamps.last() * 1000); SystemAction.get(OpenTimelineAction.class).showTimeline(interval); } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index e4c34ebce9..be49934e5d 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -66,8 +66,10 @@ import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode; import org.sleuthkit.autopsy.datamodel.RecentFilesNode; import org.sleuthkit.autopsy.datamodel.Reports; import org.sleuthkit.autopsy.datamodel.Tags; +import org.sleuthkit.autopsy.datamodel.ViewInTimeLineAction; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VolumeNode; +import org.sleuthkit.autopsy.timeline.datamodel.eventtype.ArtifactEventType; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -77,6 +79,7 @@ import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.VirtualDirectory; @@ -245,6 +248,21 @@ public class DataResultFilterNode extends FilterNode { actions.add(null); actions.add(AddBlackboardArtifactTagAction.getInstance()); } + + boolean hasTimeStamp = ArtifactEventType.getAllArtifactEventTypes().stream() + .filter(artEventType -> artEventType.getArtifactType().getTypeID() == ba.getArtifactTypeID()) + .filter(artEventType -> { + try { + return ba.getAttributes(artEventType.getDateTimeAttrubuteType()).isEmpty() == false; + } catch (TskCoreException ex) { + Logger.getLogger(DataResultFilterNode.class.getName()).log(Level.WARNING, "Error retreiving blackboard arttributes from blackboard artifact.", ex); + return false; + } + }).findAny().isPresent(); + if (hasTimeStamp){ + actions.add(ViewInTimeLineAction.getInstance()); + } + return actions; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/ArtifactEventType.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/ArtifactEventType.java index fa17ab64e6..c11d3629f0 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/ArtifactEventType.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/ArtifactEventType.java @@ -21,8 +21,10 @@ package org.sleuthkit.autopsy.timeline.datamodel.eventtype; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; import java.util.logging.Level; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -34,6 +36,13 @@ import org.sleuthkit.datamodel.TskCoreException; */ public interface ArtifactEventType extends EventType { + public static Set getAllArtifactEventTypes() { + return allTypes.stream() + .filter((EventType t) -> t instanceof ArtifactEventType) + .map(ArtifactEventType.class::cast) + .collect(Collectors.toSet()); + } + /** * @return the Artifact type this event type is derived form, or null if * there is no artifact type (eg file system events) @@ -87,7 +96,8 @@ public interface ArtifactEventType extends EventType { /** * bundles the per event information derived from a BlackBoard Artifact into - * one object. Primarily used to have a single return value for {@link SubType#buildEventDescription(org.sleuthkit.datamodel.BlackboardArtifact). + * one object. Primarily used to have a single return value for null null + * null null {@link SubType#buildEventDescription(org.sleuthkit.datamodel.BlackboardArtifact). */ static class AttributeEventDescription { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/EventType.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/EventType.java index 0758d804ec..54bd488d8f 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/EventType.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/EventType.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel; */ public interface EventType { - final static List allTypes = RootEventType.getInstance().getSubTypesRecusive(); + final static List allTypes = RootEventType.getInstance().getSubTypesRecusive(); static Comparator getComparator() { return Comparator.comparing(EventType.allTypes::indexOf); @@ -47,7 +47,7 @@ public interface EventType { } } - default List getSubTypesRecusive() { + default List getSubTypesRecusive() { ArrayList flatList = new ArrayList<>(); for (EventType et : getSubTypes()) { @@ -56,6 +56,8 @@ public interface EventType { } return flatList; } + + /** * @return the color used to represent this event type visually diff --git a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java index 73800b9b89..8450260cb3 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java @@ -443,7 +443,7 @@ public class EventsRepository { private final SleuthkitCase skCase; private final TagsManager tagsManager; - public DBPopulationWorker(Runnable postPopulationOperation) { + DBPopulationWorker(Runnable postPopulationOperation) { progressDialog = new ProgressWindow(null, true, this); progressDialog.setVisible(true);