mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-29 13:59:52 +00:00
Merge remote-tracking branch 'upstream/timeline-event-mgr' into 1216-drop-immutablesets
# Conflicts: # Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java # Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventCluster.java # Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventStripe.java
This commit is contained in:
@@ -237,8 +237,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT));
|
||||
doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT));
|
||||
doNotShow.add(new BlackboardArtifact.Type(TSK_ACCOUNT));
|
||||
doNotShow.add(new BlackboardArtifact.Type(TSK_TL_EVENT));
|
||||
doNotShow.add(new BlackboardArtifact.Type(TSK_DATA_SOURCE_USAGE));
|
||||
doNotShow.add(new BlackboardArtifact.Type(TSK_TL_EVENT));
|
||||
doNotShow.add(new BlackboardArtifact.Type(TSK_DOWNLOAD_SOURCE) );
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import javafx.collections.ObservableList;
|
||||
import javafx.collections.ObservableMap;
|
||||
import javafx.collections.ObservableSet;
|
||||
import static org.apache.commons.collections4.CollectionUtils.emptyIfNull;
|
||||
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.Interval;
|
||||
import org.openide.util.NbBundle;
|
||||
@@ -526,7 +527,7 @@ public final class FilteredEventsModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a List of event IDs for the events that are derived from the given
|
||||
* Get a Set of event IDs for the events that are derived from the given
|
||||
* file.
|
||||
*
|
||||
* @param file The AbstractFile to get derived event IDs
|
||||
@@ -537,12 +538,12 @@ public final class FilteredEventsModel {
|
||||
* directly from this file (file system
|
||||
* timestamps).
|
||||
*
|
||||
* @return A List of event IDs for the events that are derived from the
|
||||
* given file.
|
||||
* @return A Set of event IDs for the events that are derived from the given
|
||||
* file.
|
||||
*
|
||||
* @throws org.sleuthkit.datamodel.TskCoreException
|
||||
*/
|
||||
public List<Long> getEventIDsForFile(AbstractFile file, boolean includeDerivedArtifacts) throws TskCoreException {
|
||||
public Set<Long> getEventIDsForFile(AbstractFile file, boolean includeDerivedArtifacts) throws TskCoreException {
|
||||
return eventManager.getEventIDsForFile(file, includeDerivedArtifacts);
|
||||
}
|
||||
|
||||
@@ -637,7 +638,7 @@ public final class FilteredEventsModel {
|
||||
|
||||
synchronized public Set<Long> addTag(long objID, Long artifactID, Tag tag) throws TskCoreException {
|
||||
Set<Long> updatedEventIDs = eventManager.setEventsTagged(objID, artifactID, true);
|
||||
if (!updatedEventIDs.isEmpty()) {
|
||||
if (isNotEmpty(updatedEventIDs)) {
|
||||
invalidateCaches(updatedEventIDs);
|
||||
}
|
||||
return updatedEventIDs;
|
||||
@@ -645,7 +646,7 @@ public final class FilteredEventsModel {
|
||||
|
||||
synchronized public Set<Long> deleteTag(long objID, Long artifactID, long tagID, boolean tagged) throws TskCoreException {
|
||||
Set<Long> updatedEventIDs = eventManager.setEventsTagged(objID, artifactID, tagged);
|
||||
if (!updatedEventIDs.isEmpty()) {
|
||||
if (isNotEmpty(updatedEventIDs)) {
|
||||
invalidateCaches(updatedEventIDs);
|
||||
}
|
||||
return updatedEventIDs;
|
||||
@@ -656,7 +657,7 @@ public final class FilteredEventsModel {
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
updatedEventIDs.addAll(eventManager.setEventsHashed(artifact.getObjectID(), hasHashHit));
|
||||
}
|
||||
if (!updatedEventIDs.isEmpty()) {
|
||||
if (isNotEmpty(updatedEventIDs)) {
|
||||
invalidateCaches(updatedEventIDs);
|
||||
}
|
||||
return updatedEventIDs;
|
||||
|
||||
@@ -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");
|
||||
@@ -25,6 +25,7 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -114,8 +115,6 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
|
||||
private final VBox contentRoot = new VBox();
|
||||
|
||||
private final TimeLineController controller;
|
||||
|
||||
private final ValidationSupport validationSupport = new ValidationSupport();
|
||||
|
||||
/**
|
||||
@@ -127,8 +126,7 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ShowInTimelineDialog.amountValidator.message=The entered amount must only contain digits."})
|
||||
private ShowInTimelineDialog(TimeLineController controller, List<Long> eventIDS) throws TskCoreException {
|
||||
this.controller = controller;
|
||||
private ShowInTimelineDialog(TimeLineController controller, Collection<Long> eventIDS) throws TskCoreException {
|
||||
|
||||
//load dialog content fxml
|
||||
final String name = "nbres:/" + StringUtils.replace(ShowInTimelineDialog.class.getPackage().getName(), ".", "/") + "/ShowInTimelineDialog.fxml"; // NON-NLS
|
||||
|
||||
@@ -87,6 +87,7 @@ import org.sleuthkit.autopsy.timeline.zooming.TimeUnits;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.ZoomState;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT;
|
||||
import org.sleuthkit.datamodel.DescriptionLoD;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.timeline.EventType;
|
||||
@@ -734,7 +735,7 @@ public class TimeLineController {
|
||||
break;
|
||||
case DATA_ADDED:
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == TSK_HASHSET_HIT.getTypeID()) {
|
||||
logFutureException(executor.submit(() -> filteredEvents.setHashHit(eventData.getArtifacts(), true)),
|
||||
"Error executing task in response to DATA_ADDED event.",
|
||||
"Error executing response to new data.");
|
||||
|
||||
@@ -3,9 +3,8 @@ EventNode.getAction.linkedFileMessage=There was a problem getting actions for th
|
||||
# {0} - maximum number of events to display
|
||||
# {1} - the number of events that is too many
|
||||
EventRoodNode.tooManyNode.displayName=Too many events to display. Maximum = {0}. But there are {1} to display.
|
||||
NodeProperty.displayName.baseType=Base Type
|
||||
NodeProperty.displayName.dateTime=Date/Time
|
||||
NodeProperty.displayName.description=Description
|
||||
NodeProperty.displayName.eventType=Event Type
|
||||
NodeProperty.displayName.icon=Icon
|
||||
NodeProperty.displayName.known=Known
|
||||
NodeProperty.displayName.subType=Sub Type
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.timeline.EventType;
|
||||
import org.sleuthkit.datamodel.timeline.TimelineEvent;
|
||||
|
||||
/**
|
||||
@@ -57,8 +58,6 @@ import org.sleuthkit.datamodel.timeline.TimelineEvent;
|
||||
*/
|
||||
public class EventNode extends DisplayableItemNode {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(EventNode.class.getName());
|
||||
|
||||
private final TimelineEvent event;
|
||||
@@ -66,21 +65,22 @@ public class EventNode extends DisplayableItemNode {
|
||||
EventNode(TimelineEvent event, Content file, BlackboardArtifact artifact) {
|
||||
super(Children.LEAF, Lookups.fixed(event, file, artifact));
|
||||
this.event = event;
|
||||
this.setIconBaseWithExtension(EventTypeUtils.getImagePath(event.getEventType())); // NON-NLS
|
||||
EventType evenType = event.getEventType();
|
||||
this.setIconBaseWithExtension(EventTypeUtils.getImagePath(evenType));
|
||||
}
|
||||
|
||||
EventNode(TimelineEvent event, Content file) {
|
||||
super(Children.LEAF, Lookups.fixed(event, file));
|
||||
this.event = event;
|
||||
this.setIconBaseWithExtension(EventTypeUtils.getImagePath(event.getEventType())); // NON-NLS
|
||||
EventType evenType = event.getEventType();
|
||||
this.setIconBaseWithExtension(EventTypeUtils.getImagePath(evenType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages({
|
||||
"NodeProperty.displayName.icon=Icon",
|
||||
"NodeProperty.displayName.description=Description",
|
||||
"NodeProperty.displayName.baseType=Base Type",
|
||||
"NodeProperty.displayName.subType=Sub Type",
|
||||
"NodeProperty.displayName.eventType=Event Type",
|
||||
"NodeProperty.displayName.known=Known",
|
||||
"NodeProperty.displayName.dateTime=Date/Time"})
|
||||
protected Sheet createSheet() {
|
||||
@@ -94,9 +94,8 @@ public class EventNode extends DisplayableItemNode {
|
||||
properties.put(new NodeProperty<>("icon", Bundle.NodeProperty_displayName_icon(), "icon", true)); // NON-NLS //gets overridden with icon
|
||||
properties.put(new TimeProperty("time", Bundle.NodeProperty_displayName_dateTime(), "time ", getDateTimeString()));// NON-NLS
|
||||
properties.put(new NodeProperty<>("description", Bundle.NodeProperty_displayName_description(), "description", event.getFullDescription())); // NON-NLS
|
||||
properties.put(new NodeProperty<>("eventBaseType", Bundle.NodeProperty_displayName_baseType(), "base type", event.getEventType().getSuperType().getDisplayName())); // NON-NLS
|
||||
properties.put(new NodeProperty<>("eventSubType", Bundle.NodeProperty_displayName_subType(), "sub type", event.getEventType().getDisplayName())); // NON-NLS
|
||||
|
||||
properties.put(new NodeProperty<>("eventType", Bundle.NodeProperty_displayName_eventType(), "event type", event.getEventType().getDisplayName())); // NON-NLS
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
@@ -225,7 +224,7 @@ public class EventNode extends DisplayableItemNode {
|
||||
* Look up the event by id and creata an EventNode with the
|
||||
* appropriate data in the lookup.
|
||||
*/
|
||||
final TimelineEvent eventById = eventsModel.getEventById(eventID);
|
||||
final TimelineEvent eventById = eventsModel.getEventById(eventID);
|
||||
|
||||
Content file = sleuthkitCase.getContentById(eventById.getFileObjID());
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2016-18 Basis Technology Corp.
|
||||
* Copyright 2016-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -58,8 +58,8 @@ import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.EventCluster;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.EventStripe;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.SingleDetailsViewEvent;
|
||||
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilter;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* One "lane" of a the details view, contains all the core logic and layout
|
||||
|
||||
@@ -259,7 +259,7 @@ final class EventClusterNode extends MultiEventNodeBase<EventCluster, EventStrip
|
||||
|
||||
@Override
|
||||
EventNodeBase<?> createChildNode(EventStripe stripe) throws TskCoreException {
|
||||
Set<Long> eventIDs = stripe.getEventIDs();
|
||||
Set<Long> eventIDs = stripe.getEventIDs();
|
||||
if (eventIDs.size() == 1) {
|
||||
//If the stripe is a single event, make a single event node rather than a stripe node.
|
||||
TimelineEvent singleEvent = getController().getEventsModel().getEventById(Iterables.getOnlyElement(eventIDs));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2016-18 Basis Technology Corp.
|
||||
* Copyright 2016-19 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -173,6 +173,7 @@ public abstract class EventNodeBase<Type extends DetailViewEvent> extends StackP
|
||||
showHoverControls(true);
|
||||
toFront();
|
||||
});
|
||||
|
||||
setOnMouseExited(mouseExited -> {
|
||||
showHoverControls(false);
|
||||
if (parentNode != null) {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
+9
-8
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Copyright 2018-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -165,7 +165,7 @@ final public class DetailsViewModel {
|
||||
+ " event_id, " //NON-NLS
|
||||
+ " hash_hit, " //NON-NLS
|
||||
+ " tagged, " //NON-NLS
|
||||
+ " sub_type, base_type, "
|
||||
+ " event_type_id, super_type_id, "
|
||||
+ " full_description, med_description, short_description " // NON-NLS
|
||||
+ " FROM " + TimelineManager.getAugmentedEventsTablesSQL(activeFilter) // NON-NLS
|
||||
+ " WHERE time >= " + start + " AND time < " + end + " AND " + eventManager.getSQLWhere(activeFilter) // NON-NLS
|
||||
@@ -205,7 +205,7 @@ final public class DetailsViewModel {
|
||||
private TimelineEvent eventHelper(ResultSet resultSet) throws SQLException, TskCoreException {
|
||||
|
||||
//the event tyepe to use to get the description.
|
||||
int eventTypeID = resultSet.getInt("sub_type");
|
||||
int eventTypeID = resultSet.getInt("event_type_id");
|
||||
EventType eventType = eventManager.getEventType(eventTypeID).orElseThrow(()
|
||||
-> new TskCoreException("Error mapping event type id " + eventTypeID + "to EventType."));//NON-NLS
|
||||
|
||||
@@ -216,12 +216,12 @@ final public class DetailsViewModel {
|
||||
resultSet.getLong("artifact_id"), // NON-NLS
|
||||
resultSet.getLong("time"), // NON-NLS
|
||||
eventType,
|
||||
eventType.getDescription(
|
||||
resultSet.getString("full_description"), // NON-NLS
|
||||
resultSet.getString("med_description"), // NON-NLS
|
||||
resultSet.getString("short_description")), // NON-NLS
|
||||
resultSet.getString("full_description"), // NON-NLS
|
||||
resultSet.getString("med_description"), // NON-NLS
|
||||
resultSet.getString("short_description"), // NON-NLS
|
||||
resultSet.getInt("hash_hit") != 0, //NON-NLS
|
||||
resultSet.getInt("tagged") != 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,6 +254,8 @@ final public class DetailsViewModel {
|
||||
.sorted(new DetailViewEvent.StartComparator())
|
||||
.iterator();
|
||||
EventCluster current = iterator.next();
|
||||
|
||||
//JM Todo: maybe we can collect all clusters to merge in one go, rather than piece by piece for performance.
|
||||
while (iterator.hasNext()) {
|
||||
EventCluster next = iterator.next();
|
||||
Interval gap = current.getSpan().gap(next.getSpan());
|
||||
@@ -285,5 +287,4 @@ final public class DetailsViewModel {
|
||||
.sorted(new DetailViewEvent.StartComparator())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
||||
* events clusters
|
||||
*/
|
||||
public static EventCluster merge(EventCluster cluster1, EventCluster cluster2) {
|
||||
|
||||
if (cluster1.getEventType() != cluster2.getEventType()) {
|
||||
throw new IllegalArgumentException("event clusters are not compatible: they have different types");
|
||||
}
|
||||
@@ -112,6 +113,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
||||
EventStripe parent) {
|
||||
|
||||
this.span = spanningInterval;
|
||||
|
||||
this.type = type;
|
||||
this.hashHits = hashHits;
|
||||
this.tagged = tagged;
|
||||
@@ -134,6 +136,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
||||
event.isTagged() ? singleton(event.getEventID()) : emptySet(),
|
||||
event.getDescription(lod),
|
||||
lod);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,6 +216,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
||||
* EventBundle as the parent.
|
||||
*/
|
||||
public EventCluster withParent(EventStripe parent) {
|
||||
|
||||
return new EventCluster(span, type, eventIDs, hashHits, tagged, description, lod, parent);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,14 +73,14 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
||||
*/
|
||||
private final Set<Long> hashHits;
|
||||
|
||||
public static EventStripe merge(EventStripe u, EventStripe v) { //NOPMD
|
||||
Preconditions.checkNotNull(u);
|
||||
Preconditions.checkNotNull(v);
|
||||
Preconditions.checkArgument(Objects.equals(u.description, v.description));
|
||||
Preconditions.checkArgument(Objects.equals(u.lod, v.lod));
|
||||
Preconditions.checkArgument(Objects.equals(u.type, v.type));
|
||||
Preconditions.checkArgument(Objects.equals(u.parent, v.parent));
|
||||
return new EventStripe(u, v);
|
||||
public static EventStripe merge(EventStripe stripeA, EventStripe stripeB) {
|
||||
Preconditions.checkNotNull(stripeA);
|
||||
Preconditions.checkNotNull(stripeB);
|
||||
Preconditions.checkArgument(Objects.equals(stripeA.description, stripeB.description));
|
||||
Preconditions.checkArgument(Objects.equals(stripeA.lod, stripeB.lod));
|
||||
Preconditions.checkArgument(Objects.equals(stripeA.type, stripeB.type));
|
||||
Preconditions.checkArgument(Objects.equals(stripeA.parent, stripeB.parent));
|
||||
return new EventStripe(stripeA, stripeB);
|
||||
}
|
||||
|
||||
public EventStripe withParent(EventCluster parent) {
|
||||
@@ -90,7 +90,9 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
||||
return new EventStripe(parent, this.type, this.description, this.lod, clusters, eventIDs, tagged, hashHits);
|
||||
}
|
||||
|
||||
private EventStripe(EventCluster parent, EventType type, String description, DescriptionLoD lod, SortedSet<EventCluster> clusters, Set<Long> eventIDs, Set<Long> tagged, Set<Long> hashHits) {
|
||||
private EventStripe(EventCluster parent, EventType type, String description,
|
||||
DescriptionLoD lod, SortedSet<EventCluster> clusters,
|
||||
Set<Long> eventIDs, Set<Long> tagged, Set<Long> hashHits) {
|
||||
this.parent = parent;
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
@@ -105,6 +107,7 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
||||
public EventStripe(EventCluster cluster) {
|
||||
this.clusters = copyAsSortedSet(singleton(cluster.withParent(this)),
|
||||
comparing(EventCluster::getStartMillis));
|
||||
|
||||
|
||||
type = cluster.getEventType();
|
||||
description = cluster.getDescription();
|
||||
|
||||
+9
-8
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Copyright 2018-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -37,7 +37,8 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
|
||||
|
||||
private final long eventID;
|
||||
/**
|
||||
* The TSK object ID of the file (could be data source) this event is derived from.
|
||||
* The TSK object ID of the file (could be data source) this event is
|
||||
* derived from.
|
||||
*/
|
||||
private final long fileObjId;
|
||||
|
||||
@@ -85,10 +86,11 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
|
||||
private MultiEvent<?> parent = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param eventID
|
||||
* @param dataSourceObjId
|
||||
* @param fileObjId Object Id of file (could be a data source) that event is associated with
|
||||
* @param fileObjId Object Id of file (could be a data source) that
|
||||
* event is associated with
|
||||
* @param artifactID
|
||||
* @param time
|
||||
* @param type
|
||||
@@ -96,7 +98,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
|
||||
* @param medDescription
|
||||
* @param shortDescription
|
||||
* @param hashHit
|
||||
* @param tagged
|
||||
* @param tagged
|
||||
*/
|
||||
public SingleDetailsViewEvent(long eventID, long dataSourceObjId, long fileObjId, Long artifactID, long time, EventType type, String fullDescription, String medDescription, String shortDescription, boolean hashHit, boolean tagged) {
|
||||
this.eventID = eventID;
|
||||
@@ -182,7 +184,8 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the obj id of the file (which could be a data source) this event is derived from.
|
||||
* Get the obj id of the file (which could be a data source) this event is
|
||||
* derived from.
|
||||
*
|
||||
* @return the object id.
|
||||
*/
|
||||
@@ -231,8 +234,6 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
|
||||
return getDescription(DescriptionLoD.SHORT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the description of this event at the give level of detail(LoD).
|
||||
*
|
||||
|
||||
@@ -49,12 +49,12 @@ class BaseTypeTreeItem extends EventTypeTreeItem {
|
||||
BaseTypeTreeItem(DetailViewEvent event, Comparator<TreeItem<DetailViewEvent>> comparator) {
|
||||
super(event.getEventType().getBaseType(), comparator);
|
||||
}
|
||||
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
@Override
|
||||
public void insert(List<DetailViewEvent> path) {
|
||||
DetailViewEvent head = path.get(0);
|
||||
|
||||
|
||||
Supplier< EventsTreeItem> treeItemConstructor;
|
||||
String descriptionKey;
|
||||
/*
|
||||
@@ -69,7 +69,7 @@ class BaseTypeTreeItem extends EventTypeTreeItem {
|
||||
DetailViewEvent stripe = path.remove(0); //remove head of list if we are going straight to description
|
||||
treeItemConstructor = () -> configureNewTreeItem(new DescriptionTreeItem(stripe, getComparator()));
|
||||
}
|
||||
|
||||
|
||||
EventsTreeItem treeItem = childMap.computeIfAbsent(descriptionKey, key -> treeItemConstructor.get());
|
||||
|
||||
//insert (rest of) path in to new treeItem
|
||||
@@ -77,11 +77,11 @@ class BaseTypeTreeItem extends EventTypeTreeItem {
|
||||
treeItem.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void remove(List<DetailViewEvent> path) {
|
||||
DetailViewEvent head = path.get(0);
|
||||
|
||||
|
||||
EventsTreeItem descTreeItem;
|
||||
/*
|
||||
* if the stripe and this tree item have the same type, get the child
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014-18 Basis Technology Corp.
|
||||
* Copyright 2014-19 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -103,7 +103,7 @@ class DescriptionTreeItem extends EventsTreeItem {
|
||||
@Override
|
||||
public EventsTreeItem findTreeItemForEvent(DetailViewEvent event) {
|
||||
if (getValue().getEventType() == event.getEventType()
|
||||
&& getValue().getDescription().equals(event.getDescription())) {
|
||||
&& getValue().getDescription().equals(event.getDescription())) {
|
||||
//if this tree item match the given event, return this.
|
||||
return this;
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-16 Basis Technology Corp.
|
||||
* Copyright 2013-19 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -572,7 +572,7 @@ class ListTimeline extends BorderPane {
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for TableCells that represent a MergedEvent by way of a
|
||||
* Base class for TableCells that represent a CombinedEvent by way of a
|
||||
* representative TimeLineEvent.
|
||||
*/
|
||||
private abstract class EventTableCell extends TableCell<CombinedEvent, CombinedEvent> {
|
||||
|
||||
@@ -105,8 +105,8 @@ public class CombinedEvent {
|
||||
|
||||
/**
|
||||
* Get the event ID of one event that is representative of all the combined
|
||||
* events. It can be used to look up a SingleEvent with more details, for
|
||||
* example.
|
||||
* events. It can be used to look up a TimelineEvent with more details, for
|
||||
* example. wwhether the file is tagged or a hash hit.
|
||||
*
|
||||
* @return An arbitrary representative event ID for the combined events.
|
||||
*/
|
||||
|
||||
@@ -92,7 +92,7 @@ public class ListViewModel {
|
||||
TimelineDBUtils dbUtils = new TimelineDBUtils(sleuthkitCase);
|
||||
final String querySql = "SELECT full_description, time, file_obj_id, "
|
||||
+ dbUtils.csvAggFunction("CAST(tsk_events.event_id AS VARCHAR)") + " AS eventIDs, "
|
||||
+ dbUtils.csvAggFunction("CAST(sub_type AS VARCHAR)") + " AS eventTypes"
|
||||
+ dbUtils.csvAggFunction("CAST(event_type_id AS VARCHAR)") + " AS eventTypes"
|
||||
+ " FROM " + TimelineManager.getAugmentedEventsTablesSQL(filterState.getActiveFilter())
|
||||
+ " WHERE time >= " + startTime + " AND time <" + endTime + " AND " + eventManager.getSQLWhere(filterState.getActiveFilter())
|
||||
+ " GROUP BY time, full_description, file_obj_id ORDER BY time ASC, full_description";
|
||||
|
||||
@@ -21,7 +21,8 @@ ExtractIE.getBookmark.errMsg.errPostingBookmarks=Error posting Internet Explorer
|
||||
ExtractIE.getCookie.errMsg.errPostingCookies=Error posting Internet Explorer Cookie artifacts.
|
||||
ExtractIE.getCookie.errMsg.errPostingCookiess=Error posting Internet Explorer Cookie artifacts.
|
||||
ExtractIE.getHistory.errMsg.errPostingHistory=Error posting Internet Explorer History artifacts.
|
||||
#{0} - the module name
|
||||
|
||||
# {0} - the module name
|
||||
Extractor.errPostingArtifacts=Error posting {0} artifacts to the blackboard.
|
||||
ExtractOs.androidOs.label=Android
|
||||
ExtractOs.androidVolume.label=OS Drive (Android)
|
||||
|
||||
@@ -28,8 +28,6 @@ import com.google.gson.JsonIOException;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import java.util.logging.Level;
|
||||
import java.util.*;
|
||||
@@ -41,12 +39,11 @@ import org.apache.commons.io.FilenameUtils;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@@ -80,7 +77,6 @@ class Chrome extends Extract {
|
||||
private static final String WEBFORM_ADDRESS_QUERY_V8X = "SELECT first_name, middle_name, last_name, full_name, street_address, city, state, zipcode, country_code, number, email, date_modified, use_date, use_count"
|
||||
+ " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones"
|
||||
+ " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
|
||||
private final Logger logger = Logger.getLogger(this.getClass().getName());
|
||||
private Content dataSource;
|
||||
private IngestJobContext context;
|
||||
|
||||
|
||||
@@ -57,11 +57,11 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@Messages({"Extract.indexError.message=Failed to index artifact for keyword search.",
|
||||
"Extract.noOpenCase.errMsg=No open case available.",
|
||||
"#{0} - the module name",
|
||||
"# {0} - the module name",
|
||||
"Extractor.errPostingArtifacts=Error posting {0} artifacts to the blackboard."})
|
||||
abstract class Extract {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Extract.class.getName());
|
||||
protected static final Logger logger = Logger.getLogger(Extract.class.getName());
|
||||
|
||||
protected Case currentCase;
|
||||
protected SleuthkitCase tskCase;
|
||||
@@ -192,21 +192,22 @@ abstract class Extract {
|
||||
/**
|
||||
* Returns a List of AbstractFile objects from TSK based on sql query.
|
||||
*
|
||||
* @param rs is the resultset that needs to be converted to an arraylist
|
||||
* @param results is the resultset that needs to be converted to an
|
||||
* arraylist
|
||||
*
|
||||
* @return list returns the arraylist built from the converted resultset
|
||||
*/
|
||||
private List<HashMap<String, Object>> resultSetToArrayList(ResultSet rs) throws SQLException {
|
||||
ResultSetMetaData md = rs.getMetaData();
|
||||
int columns = md.getColumnCount();
|
||||
private List<HashMap<String, Object>> resultSetToArrayList(ResultSet results) throws SQLException {
|
||||
ResultSetMetaData metaData = results.getMetaData();
|
||||
int columns = metaData.getColumnCount();
|
||||
List<HashMap<String, Object>> list = new ArrayList<>(50);
|
||||
while (rs.next()) {
|
||||
while (results.next()) {
|
||||
HashMap<String, Object> row = new HashMap<>(columns);
|
||||
for (int i = 1; i <= columns; ++i) {
|
||||
if (rs.getObject(i) == null) {
|
||||
row.put(md.getColumnName(i), "");
|
||||
if (results.getObject(i) == null) {
|
||||
row.put(metaData.getColumnName(i), "");
|
||||
} else {
|
||||
row.put(md.getColumnName(i), rs.getObject(i));
|
||||
row.put(metaData.getColumnName(i), results.getObject(i));
|
||||
}
|
||||
}
|
||||
list.add(row);
|
||||
|
||||
@@ -24,14 +24,17 @@ package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import static java.util.TimeZone.getTimeZone;
|
||||
import java.util.logging.Level;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.openide.modules.InstalledFileLocator;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.ExecUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@@ -39,25 +42,20 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
|
||||
import org.sleuthkit.autopsy.recentactivity.UsbDeviceIdMapper.USBInfo;
|
||||
import org.sleuthkit.datamodel.*;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import java.nio.file.Path;
|
||||
import static java.util.TimeZone.getTimeZone;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
|
||||
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
|
||||
|
||||
/**
|
||||
* Extract windows registry data using regripper. Runs two versions of
|
||||
@@ -72,9 +70,8 @@ import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamExce
|
||||
})
|
||||
class ExtractRegistry extends Extract {
|
||||
|
||||
private final Logger logger = Logger.getLogger(this.getClass().getName());
|
||||
private String RR_PATH;
|
||||
private String RR_FULL_PATH;
|
||||
private final static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
|
||||
|
||||
private Path rrHome; // Path to the Autopsy version of RegRipper
|
||||
private Path rrFullHome; // Path to the full version of RegRipper
|
||||
private Content dataSource;
|
||||
@@ -106,19 +103,19 @@ class ExtractRegistry extends Extract {
|
||||
executableToRun = RIP_PL;
|
||||
}
|
||||
rrHome = rrRoot.toPath();
|
||||
RR_PATH = rrHome.resolve(executableToRun).toString();
|
||||
String rrPath = rrHome.resolve(executableToRun).toString();
|
||||
rrFullHome = rrFullRoot.toPath();
|
||||
RR_FULL_PATH = rrFullHome.resolve(executableToRun).toString();
|
||||
String rrFullPath = rrFullHome.resolve(executableToRun).toString();
|
||||
|
||||
if (!(new File(RR_PATH).exists())) {
|
||||
if (!(new File(rrPath).exists())) {
|
||||
throw new IngestModuleException(Bundle.RegRipperNotFound());
|
||||
}
|
||||
if (!(new File(RR_FULL_PATH).exists())) {
|
||||
if (!(new File(rrFullPath).exists())) {
|
||||
throw new IngestModuleException(Bundle.RegRipperFullNotFound());
|
||||
}
|
||||
if (PlatformUtil.isWindowsOS()) {
|
||||
rrCmd.add(RR_PATH);
|
||||
rrFullCmd.add(RR_FULL_PATH);
|
||||
rrCmd.add(rrPath);
|
||||
rrFullCmd.add(rrFullPath);
|
||||
} else {
|
||||
String perl;
|
||||
File usrBin = new File("/usr/bin/perl");
|
||||
@@ -131,9 +128,9 @@ class ExtractRegistry extends Extract {
|
||||
throw new IngestModuleException("perl not found in your system");
|
||||
}
|
||||
rrCmd.add(perl);
|
||||
rrCmd.add(RR_PATH);
|
||||
rrCmd.add(rrPath);
|
||||
rrFullCmd.add(perl);
|
||||
rrFullCmd.add(RR_FULL_PATH);
|
||||
rrFullCmd.add(rrFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +415,6 @@ class ExtractRegistry extends Extract {
|
||||
Element artroot = (Element) artroots.item(0);
|
||||
NodeList myartlist = artroot.getChildNodes();
|
||||
String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
|
||||
String winver = "";
|
||||
|
||||
// If all artifact nodes should really go under one Blackboard artifact, need to process it differently
|
||||
switch (dataType) {
|
||||
@@ -732,7 +728,7 @@ class ExtractRegistry extends Extract {
|
||||
} else {
|
||||
//add attributes to existing artifact
|
||||
BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
|
||||
|
||||
|
||||
if (bbattr == null) {
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
|
||||
parentModuleName, username));
|
||||
@@ -799,7 +795,7 @@ class ExtractRegistry extends Extract {
|
||||
break;
|
||||
}
|
||||
} // for
|
||||
|
||||
|
||||
return true;
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS
|
||||
@@ -844,7 +840,7 @@ class ExtractRegistry extends Extract {
|
||||
if (line.contains(SECTION_DIVIDER) && previousLine != null) {
|
||||
if (previousLine.contains(userInfoSection)) {
|
||||
readUsers(bufferedReader, userSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
previousLine = line;
|
||||
line = bufferedReader.readLine();
|
||||
@@ -912,7 +908,7 @@ class ExtractRegistry extends Extract {
|
||||
} catch (ParseException ex) {
|
||||
logger.log(Level.SEVERE, "Error parsing the the date from the registry file", ex); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -942,8 +938,7 @@ class ExtractRegistry extends Extract {
|
||||
if (line.contains(userNameLabel)) {
|
||||
String userNameAndIdString = line.replace(userNameLabel, "");
|
||||
userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim();
|
||||
}
|
||||
else if (line.contains(sidLabel) && !userName.isEmpty()){
|
||||
} else if (line.contains(sidLabel) && !userName.isEmpty()) {
|
||||
String sid = line.replace(sidLabel, "").trim();
|
||||
UserInfo userInfo = new UserInfo(userName, sid);
|
||||
//continue reading this users information until end of file or a blank line between users
|
||||
@@ -990,7 +985,7 @@ class ExtractRegistry extends Extract {
|
||||
/**
|
||||
* Create a UserInfo object
|
||||
*
|
||||
* @param name - the os user account name
|
||||
* @param name - the os user account name
|
||||
* @param userSidString - the SID for the user account
|
||||
*/
|
||||
private UserInfo(String name, String userSidString) {
|
||||
|
||||
@@ -101,7 +101,6 @@ class Firefox extends Extract {
|
||||
private final IngestServices services = IngestServices.getInstance();
|
||||
private Content dataSource;
|
||||
private IngestJobContext context;
|
||||
private final String moduleName;
|
||||
|
||||
Firefox() {
|
||||
moduleName = NbBundle.getMessage(Firefox.class, "Firefox.moduleName");
|
||||
|
||||
@@ -33,12 +33,12 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
|
||||
/**
|
||||
* Recent activity image ingest module
|
||||
@@ -48,9 +48,9 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
private static final Logger logger = Logger.getLogger(RAImageIngestModule.class.getName());
|
||||
private final List<Extract> extractors = new ArrayList<>();
|
||||
private final List<Extract> browserExtractors = new ArrayList<>();
|
||||
private IngestServices services = IngestServices.getInstance();
|
||||
private final IngestServices services = IngestServices.getInstance();
|
||||
private IngestJobContext context;
|
||||
private StringBuilder subCompleted = new StringBuilder();
|
||||
private final StringBuilder subCompleted = new StringBuilder();
|
||||
|
||||
RAImageIngestModule() {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user