19 package org.sleuthkit.datamodel;
21 import com.google.common.annotations.Beta;
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableMap;
24 import java.sql.PreparedStatement;
25 import java.sql.ResultSet;
26 import java.sql.SQLException;
27 import java.sql.Statement;
28 import java.time.Instant;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
36 import java.util.Objects;
37 import static java.util.Objects.isNull;
38 import java.util.Optional;
40 import java.util.logging.Level;
41 import java.util.logging.Logger;
42 import java.util.stream.Collectors;
43 import org.joda.time.DateTimeZone;
44 import org.joda.time.Interval;
57 private static final Logger logger = Logger.getLogger(
TimelineManager.class.getName());
62 private static final ImmutableList<TimelineEventType> ROOT_CATEGORY_AND_FILESYSTEM_TYPES
79 private static final ImmutableList<TimelineEventType> PREDEFINED_EVENT_TYPES
92 private static final Long MAX_TIMESTAMP_TO_ADD = Instant.now().getEpochSecond() + 394200000;
97 private final Map<Long, TimelineEventType> eventTypeIDMap =
new HashMap<>();
109 this.caseDB = caseDB;
112 ROOT_CATEGORY_AND_FILESYSTEM_TYPES.forEach(eventType -> eventTypeIDMap.put(eventType.getTypeID(), eventType));
116 try (
final CaseDbConnection con = caseDB.getConnection();
117 final Statement statement = con.createStatement()) {
119 con.executeUpdate(statement,
120 insertOrIgnore(
" INTO tsk_event_types(event_type_id, display_name, super_type_id) "
121 +
"VALUES( " + type.getTypeID() +
", '"
122 + escapeSingleQuotes(type.getDisplayName()) +
"',"
123 + type.getParent().getTypeID()
125 eventTypeIDMap.put(type.getTypeID(), type);
127 }
catch (SQLException ex) {
128 throw new TskCoreException(
"Failed to initialize timeline event types", ex);
146 if (eventIDs.isEmpty()) {
149 final String query =
"SELECT Min(time) as minTime, Max(time) as maxTime FROM tsk_events WHERE event_id IN (" + buildCSVString(eventIDs) +
")";
151 try (CaseDbConnection con = caseDB.getConnection();
152 Statement stmt = con.createStatement();
153 ResultSet results = stmt.executeQuery(query);) {
154 if (results.next()) {
155 return new Interval(results.getLong(
"minTime") * 1000, (results.getLong(
"maxTime") + 1) * 1000, DateTimeZone.UTC);
157 }
catch (SQLException ex) {
158 throw new TskCoreException(
"Error executing get spanning interval query: " + query, ex);
178 long start = timeRange.getStartMillis() / 1000;
179 long end = timeRange.getEndMillis() / 1000;
180 String sqlWhere = getSQLWhere(filter);
181 String augmentedEventsTablesSQL = getAugmentedEventsTablesSQL(filter);
182 String queryString =
" SELECT (SELECT Max(time) FROM " + augmentedEventsTablesSQL
183 +
" WHERE time <=" + start +
" AND " + sqlWhere +
") AS start,"
184 +
" (SELECT Min(time) FROM " + augmentedEventsTablesSQL
185 +
" WHERE time >= " + end +
" AND " + sqlWhere +
") AS end";
187 try (CaseDbConnection con = caseDB.getConnection();
188 Statement stmt = con.createStatement();
189 ResultSet results = stmt.executeQuery(queryString);) {
191 if (results.next()) {
192 long start2 = results.getLong(
"start");
193 long end2 = results.getLong(
"end");
198 return new Interval(start2 * 1000, (end2 + 1) * 1000, timeZone);
200 }
catch (SQLException ex) {
218 String sql =
"SELECT * FROM " + getAugmentedEventsTablesSQL(
false) +
" WHERE event_id = " + eventID;
220 try (CaseDbConnection con = caseDB.getConnection();
221 Statement stmt = con.createStatement();) {
222 try (ResultSet results = stmt.executeQuery(sql);) {
223 if (results.next()) {
224 int typeID = results.getInt(
"event_type_id");
227 results.getLong(
"data_source_obj_id"),
228 results.getLong(
"content_obj_id"),
229 results.getLong(
"artifact_id"),
230 results.getLong(
"time"),
231 type, results.getString(
"full_description"),
232 results.getString(
"med_description"),
233 results.getString(
"short_description"),
234 intToBoolean(results.getInt(
"hash_hit")),
235 intToBoolean(results.getInt(
"tagged")));
238 }
catch (SQLException sqlEx) {
258 Long startTime = timeRange.getStartMillis() / 1000;
259 Long endTime = timeRange.getEndMillis() / 1000;
261 if (Objects.equals(startTime, endTime)) {
265 ArrayList<Long> resultIDs =
new ArrayList<>();
267 String query =
"SELECT tsk_events.event_id AS event_id FROM " + getAugmentedEventsTablesSQL(filter)
268 +
" WHERE time >= " + startTime +
" AND time <" + endTime +
" AND " + getSQLWhere(filter) +
" ORDER BY time ASC";
270 try (CaseDbConnection con = caseDB.getConnection();
271 Statement stmt = con.createStatement();
272 ResultSet results = stmt.executeQuery(query);) {
273 while (results.next()) {
274 resultIDs.add(results.getLong(
"event_id"));
277 }
catch (SQLException sqlEx) {
278 throw new TskCoreException(
"Error while executing query " + query, sqlEx);
296 try (CaseDbConnection con = caseDB.getConnection();
297 Statement stms = con.createStatement();
298 ResultSet results = stms.executeQuery(STATEMENTS.GET_MAX_TIME.getSQL());) {
299 if (results.next()) {
300 return results.getLong(
"max");
302 }
catch (SQLException ex) {
303 throw new TskCoreException(
"Error while executing query " + STATEMENTS.GET_MAX_TIME.getSQL(), ex);
320 try (CaseDbConnection con = caseDB.getConnection();
321 Statement stms = con.createStatement();
322 ResultSet results = stms.executeQuery(STATEMENTS.GET_MIN_TIME.getSQL());) {
323 if (results.next()) {
324 return results.getLong(
"min");
326 }
catch (SQLException ex) {
327 throw new TskCoreException(
"Error while executing query " + STATEMENTS.GET_MAX_TIME.getSQL(), ex);
343 return Optional.ofNullable(eventTypeIDMap.get(eventTypeID));
352 return ImmutableList.copyOf(eventTypeIDMap.values());
355 private String insertOrIgnore(String query) {
358 return " INSERT " + query +
" ON CONFLICT DO NOTHING ";
360 return " INSERT OR IGNORE " + query;
362 throw new UnsupportedOperationException(
"Unsupported DB type: " + caseDB.
getDatabaseType().name());
369 private enum STATEMENTS {
371 GET_MAX_TIME(
"SELECT Max(time) AS max FROM tsk_events"),
372 GET_MIN_TIME(
"SELECT Min(time) AS min FROM tsk_events");
374 private final String sql;
376 private STATEMENTS(String sql) {
396 ArrayList<Long> eventIDs =
new ArrayList<>();
399 =
"SELECT event_id FROM tsk_events "
400 +
" LEFT JOIN tsk_event_descriptions on ( tsk_events.event_description_id = tsk_event_descriptions.event_description_id ) "
401 +
" WHERE artifact_id = " + artifact.getArtifactID();
403 try (CaseDbConnection con = caseDB.getConnection();
404 Statement stmt = con.createStatement();
405 ResultSet results = stmt.executeQuery(query);) {
406 while (results.next()) {
407 eventIDs.add(results.getLong(
"event_id"));
409 }
catch (SQLException ex) {
410 throw new TskCoreException(
"Error executing getEventIDsForArtifact query.", ex);
432 try (CaseDbConnection conn = caseDB.getConnection()) {
433 return getEventAndDescriptionIDs(conn, content.getId(), includeDerivedArtifacts).keySet();
456 private long addEventDescription(
long dataSourceObjId,
long fileObjId, Long artifactID,
457 String fullDescription, String medDescription, String shortDescription,
458 boolean hasHashHits,
boolean tagged, CaseDbConnection connection)
throws TskCoreException {
459 String insertDescriptionSql
460 =
"INSERT INTO tsk_event_descriptions ( "
461 +
"data_source_obj_id, content_obj_id, artifact_id, "
462 +
" full_description, med_description, short_description, "
463 +
" hash_hit, tagged "
465 + dataSourceObjId +
","
467 + Objects.toString(artifactID,
"NULL") +
","
468 + quotePreservingNull(fullDescription) +
","
469 + quotePreservingNull(medDescription) +
","
470 + quotePreservingNull(shortDescription) +
", "
471 + booleanToInt(hasHashHits) +
","
472 + booleanToInt(tagged)
476 try (Statement insertDescriptionStmt = connection.createStatement()) {
477 connection.executeUpdate(insertDescriptionStmt, insertDescriptionSql, PreparedStatement.RETURN_GENERATED_KEYS);
478 try (ResultSet generatedKeys = insertDescriptionStmt.getGeneratedKeys()) {
479 generatedKeys.next();
480 return generatedKeys.getLong(1);
482 }
catch (SQLException ex) {
483 throw new TskCoreException(
"Failed to insert event description.", ex);
489 Collection<TimelineEvent> addEventsForNewFile(AbstractFile file, CaseDbConnection connection)
throws TskCoreException {
490 Set<TimelineEvent> events = addEventsForNewFileQuiet(file, connection);
492 .map(TimelineEventAddedEvent::new)
493 .forEach(caseDB::fireTSKEvent);
512 Set<TimelineEvent> addEventsForNewFileQuiet(AbstractFile file, CaseDbConnection connection)
throws TskCoreException {
514 Map<TimelineEventType, Long> timeMap = ImmutableMap.of(TimelineEventType.FILE_CREATED, file.getCrtime(),
515 TimelineEventType.FILE_ACCESSED, file.getAtime(),
516 TimelineEventType.FILE_CHANGED, file.getCtime(),
517 TimelineEventType.FILE_MODIFIED, file.getMtime());
523 if (Collections.max(timeMap.values()) <= 0) {
524 return Collections.emptySet();
527 String description = file.getParentPath() + file.getName();
528 long fileObjId = file.getId();
529 Set<TimelineEvent> events =
new HashSet<>();
532 long descriptionID = addEventDescription(file.getDataSourceObjectId(), fileObjId, null,
533 description, null, null,
false,
false, connection);
535 for (Map.Entry<TimelineEventType, Long> timeEntry : timeMap.entrySet()) {
536 Long time = timeEntry.getValue();
537 if (time > 0 && time < MAX_TIMESTAMP_TO_ADD) {
538 TimelineEventType type = timeEntry.getKey();
539 long eventID = addEventWithExistingDescription(time, type, descriptionID, connection);
546 events.add(
new TimelineEvent(eventID, descriptionID, fileObjId, null, time, type,
547 description, null, null,
false,
false));
549 if (time >= MAX_TIMESTAMP_TO_ADD) {
550 logger.log(Level.WARNING, String.format(
"Date/Time discarded from Timeline for %s for file %s with Id %d", timeEntry.getKey().getDisplayName(), file.getParentPath() + file.getName(), file.getId()));
575 Set<TimelineEvent> addArtifactEvents(BlackboardArtifact artifact)
throws TskCoreException {
576 Set<TimelineEvent> newEvents =
new HashSet<>();
583 if (artifact.getArtifactTypeID() == TSK_TL_EVENT.getTypeID()) {
584 TimelineEventType eventType;
585 BlackboardAttribute attribute = artifact.getAttribute(
new BlackboardAttribute.Type(TSK_TL_EVENT_TYPE));
586 if (attribute == null) {
587 eventType = TimelineEventType.OTHER;
589 long eventTypeID = attribute.getValueLong();
590 eventType = eventTypeIDMap.getOrDefault(eventTypeID, TimelineEventType.OTHER);
594 addArtifactEvent(((TimelineEventArtifactTypeImpl) TimelineEventType.OTHER)::makeEventDescription, eventType, artifact)
595 .ifPresent(newEvents::add);
601 Set<TimelineEventArtifactTypeImpl> eventTypesForArtifact = eventTypeIDMap.values().stream()
602 .filter(TimelineEventArtifactTypeImpl.class::isInstance)
603 .map(TimelineEventArtifactTypeImpl.class::cast)
604 .filter(eventType -> eventType.getArtifactTypeID() == artifact.getArtifactTypeID())
605 .collect(Collectors.toSet());
607 for (TimelineEventArtifactTypeImpl eventType : eventTypesForArtifact) {
608 addArtifactEvent(eventType::makeEventDescription, eventType, artifact)
609 .ifPresent(newEvents::add);
613 .map(TimelineEventAddedEvent::new)
614 .forEach(caseDB::fireTSKEvent);
635 private Optional<TimelineEvent> addArtifactEvent(TSKCoreCheckedFunction<BlackboardArtifact, TimelineEventDescriptionWithTime> payloadExtractor,
636 TimelineEventType eventType, BlackboardArtifact artifact)
throws TskCoreException {
637 TimelineEventDescriptionWithTime eventPayload = payloadExtractor.apply(artifact);
638 if (eventPayload == null) {
639 return Optional.empty();
641 long time = eventPayload.getTime();
643 if (time <= 0 || time >= MAX_TIMESTAMP_TO_ADD) {
644 if (time >= MAX_TIMESTAMP_TO_ADD) {
645 logger.log(Level.WARNING, String.format(
"Date/Time discarded from Timeline for %s for artifact %s with id %d", artifact.getDisplayName(), eventPayload.getDescription(TimelineLevelOfDetail.HIGH), artifact.getId()));
647 return Optional.empty();
649 String fullDescription = eventPayload.getDescription(TimelineLevelOfDetail.HIGH);
650 String medDescription = eventPayload.getDescription(TimelineLevelOfDetail.MEDIUM);
651 String shortDescription = eventPayload.getDescription(TimelineLevelOfDetail.LOW);
652 long artifactID = artifact.getArtifactID();
653 long fileObjId = artifact.getObjectID();
654 long dataSourceObjectID = artifact.getDataSourceObjectID();
657 boolean hasHashHits =
false;
660 hasHashHits = isNotEmpty(file.getHashSetNames());
666 try (CaseDbConnection connection = caseDB.getConnection();) {
668 long descriptionID = addEventDescription(dataSourceObjectID, fileObjId, artifactID,
669 fullDescription, medDescription, shortDescription,
670 hasHashHits, tagged, connection);
672 long eventID = addEventWithExistingDescription(time, eventType, descriptionID, connection);
674 event =
new TimelineEvent(eventID, dataSourceObjectID, fileObjId, artifactID,
675 time, eventType, fullDescription, medDescription, shortDescription,
676 hasHashHits, tagged);
681 return Optional.of(event);
684 private long addEventWithExistingDescription(Long time, TimelineEventType type,
long descriptionID, CaseDbConnection connection)
throws TskCoreException {
685 String insertEventSql
686 =
"INSERT INTO tsk_events ( event_type_id, event_description_id , time) "
687 +
" VALUES (" + type.getTypeID() +
", " + descriptionID +
", " + time +
")";
690 try (Statement insertRowStmt = connection.createStatement();) {
691 connection.executeUpdate(insertRowStmt, insertEventSql, PreparedStatement.RETURN_GENERATED_KEYS);
693 try (ResultSet generatedKeys = insertRowStmt.getGeneratedKeys();) {
694 generatedKeys.next();
695 return generatedKeys.getLong(1);
697 }
catch (SQLException ex) {
698 throw new TskCoreException(
"Failed to insert event for existing description.", ex);
704 static private String quotePreservingNull(String value) {
705 return isNull(value) ?
" NULL " :
"'" + escapeSingleQuotes(value) +
"'";
708 private Map<Long, Long> getEventAndDescriptionIDs(CaseDbConnection conn,
long contentObjID,
boolean includeArtifacts)
throws TskCoreException {
709 return getEventAndDescriptionIDsHelper(conn, contentObjID, (includeArtifacts ?
"" :
" AND artifact_id IS NULL"));
712 private Map<Long, Long> getEventAndDescriptionIDs(CaseDbConnection conn,
long contentObjID, Long artifactID)
throws TskCoreException {
713 return getEventAndDescriptionIDsHelper(conn, contentObjID,
" AND artifact_id = " + artifactID);
716 private Map<Long, Long> getEventAndDescriptionIDsHelper(CaseDbConnection con,
long fileObjID, String artifactClause)
throws TskCoreException {
718 Map<Long, Long> eventIDToDescriptionIDs =
new HashMap<>();
719 String sql =
"SELECT event_id, tsk_events.event_description_id"
720 +
" FROM tsk_events "
721 +
" LEFT JOIN tsk_event_descriptions ON ( tsk_events.event_description_id = tsk_event_descriptions.event_description_id )"
722 +
" WHERE content_obj_id = " + fileObjID
724 try (Statement selectStmt = con.createStatement(); ResultSet executeQuery = selectStmt.executeQuery(sql);) {
725 while (executeQuery.next()) {
726 eventIDToDescriptionIDs.put(executeQuery.getLong(
"event_id"), executeQuery.getLong(
"event_description_id"));
728 }
catch (SQLException ex) {
729 throw new TskCoreException(
"Error getting event description ids for object id = " + fileObjID, ex);
731 return eventIDToDescriptionIDs;
753 try (CaseDbConnection conn = caseDB.getConnection()) {
754 Map<Long, Long> eventIDs = getEventAndDescriptionIDs(conn, content.getId(),
false);
755 updateEventSourceTaggedFlag(conn, eventIDs.values(), 1);
756 return eventIDs.keySet();
782 try (CaseDbConnection conn = caseDB.getConnection()) {
784 Map<Long, Long> eventIDs = getEventAndDescriptionIDs(conn, content.getId(),
false);
785 updateEventSourceTaggedFlag(conn, eventIDs.values(), 0);
786 return eventIDs.keySet();
788 return Collections.emptySet();
808 try (CaseDbConnection conn = caseDB.getConnection()) {
809 Map<Long, Long> eventIDs = getEventAndDescriptionIDs(conn, artifact.getObjectID(), artifact.getArtifactID());
810 updateEventSourceTaggedFlag(conn, eventIDs.values(), 1);
811 return eventIDs.keySet();
831 try (CaseDbConnection conn = caseDB.getConnection()) {
833 Map<Long, Long> eventIDs = getEventAndDescriptionIDs(conn, artifact.getObjectID(), artifact.getArtifactID());
834 updateEventSourceTaggedFlag(conn, eventIDs.values(), 0);
835 return eventIDs.keySet();
837 return Collections.emptySet();
844 private void updateEventSourceTaggedFlag(CaseDbConnection conn, Collection<Long> eventDescriptionIDs,
int flagValue)
throws TskCoreException {
845 if (eventDescriptionIDs.isEmpty()) {
849 String sql =
"UPDATE tsk_event_descriptions SET tagged = " + flagValue +
" WHERE event_description_id IN (" + buildCSVString(eventDescriptionIDs) +
")";
850 try (Statement updateStatement = conn.createStatement()) {
851 updateStatement.executeUpdate(sql);
852 }
catch (SQLException ex) {
853 throw new TskCoreException(
"Error marking content events tagged: " + sql, ex);
873 try (CaseDbConnection con = caseDB.getConnection(); Statement updateStatement = con.createStatement();) {
874 Map<Long, Long> eventIDs = getEventAndDescriptionIDs(con, content.getId(),
true);
875 if (! eventIDs.isEmpty()) {
876 String sql =
"UPDATE tsk_event_descriptions SET hash_hit = 1" +
" WHERE event_description_id IN (" + buildCSVString(eventIDs.values()) +
")";
878 updateStatement.executeUpdate(sql);
879 return eventIDs.keySet();
880 }
catch (SQLException ex) {
884 return eventIDs.keySet();
886 }
catch (SQLException ex) {
917 long adjustedEndTime = Objects.equals(startTime, endTime) ? endTime + 1 : endTime;
921 String queryString =
"SELECT count(DISTINCT tsk_events.event_id) AS count, " + typeColumn
922 +
" FROM " + getAugmentedEventsTablesSQL(filter)
923 +
" WHERE time >= " + startTime +
" AND time < " + adjustedEndTime +
" AND " + getSQLWhere(filter)
924 +
" GROUP BY " + typeColumn;
927 try (CaseDbConnection con = caseDB.getConnection();
928 Statement stmt = con.createStatement();
929 ResultSet results = stmt.executeQuery(queryString);) {
930 Map<TimelineEventType, Long> typeMap =
new HashMap<>();
931 while (results.next()) {
932 int eventTypeID = results.getInt(typeColumn);
934 .orElseThrow(() -> newEventTypeMappingException(eventTypeID));
936 typeMap.put(eventType, results.getLong(
"count"));
939 }
catch (SQLException ex) {
940 throw new TskCoreException(
"Error getting count of events from db: " + queryString, ex);
946 private static TskCoreException newEventTypeMappingException(
int eventTypeID) {
947 return new TskCoreException(
"Error mapping event type id " + eventTypeID +
" to EventType.");
963 static private String getAugmentedEventsTablesSQL(TimelineFilter.RootFilter filter) {
964 TimelineFilter.FileTypesFilter fileTypesFitler = filter.getFileTypesFilter();
965 boolean needsMimeTypes = fileTypesFitler != null && fileTypesFitler.hasSubFilters();
967 return getAugmentedEventsTablesSQL(needsMimeTypes);
984 static private String getAugmentedEventsTablesSQL(
boolean needMimeTypes) {
997 return "( SELECT event_id, time, tsk_event_descriptions.data_source_obj_id, content_obj_id, artifact_id, "
998 +
" full_description, med_description, short_description, tsk_events.event_type_id, super_type_id,"
999 +
" hash_hit, tagged "
1000 + (needMimeTypes ?
", mime_type" :
"")
1001 +
" FROM tsk_events "
1002 +
" JOIN tsk_event_descriptions ON ( tsk_event_descriptions.event_description_id = tsk_events.event_description_id)"
1003 +
" JOIN tsk_event_types ON (tsk_events.event_type_id = tsk_event_types.event_type_id ) "
1004 + (needMimeTypes ?
" LEFT OUTER JOIN tsk_files "
1005 +
" ON (tsk_event_descriptions.content_obj_id = tsk_files.obj_id)"
1007 +
") AS tsk_events";
1017 private static int booleanToInt(
boolean value) {
1018 return value ? 1 : 0;
1021 private static boolean intToBoolean(
int value) {
1038 List<TimelineEvent> events =
new ArrayList<>();
1040 Long startTime = timeRange.getStartMillis() / 1000;
1041 Long endTime = timeRange.getEndMillis() / 1000;
1043 if (Objects.equals(startTime, endTime)) {
1047 if (filter == null) {
1051 if (endTime < startTime) {
1056 String querySql =
"SELECT time, content_obj_id, data_source_obj_id, artifact_id, "
1060 +
" event_type_id, super_type_id, "
1061 +
" full_description, med_description, short_description "
1062 +
" FROM " + getAugmentedEventsTablesSQL(filter)
1063 +
" WHERE time >= " + startTime +
" AND time < " + endTime +
" AND " + getSQLWhere(filter)
1067 try (CaseDbConnection con = caseDB.getConnection();
1068 Statement stmt = con.createStatement();
1069 ResultSet resultSet = stmt.executeQuery(querySql);) {
1071 while (resultSet.next()) {
1072 int eventTypeID = resultSet.getInt(
"event_type_id");
1074 ->
new TskCoreException(
"Error mapping event type id " + eventTypeID +
"to EventType."));
1077 resultSet.getLong(
"event_id"),
1078 resultSet.getLong(
"data_source_obj_id"),
1079 resultSet.getLong(
"content_obj_id"),
1080 resultSet.getLong(
"artifact_id"),
1081 resultSet.getLong(
"time"),
1083 resultSet.getString(
"full_description"),
1084 resultSet.getString(
"med_description"),
1085 resultSet.getString(
"short_description"),
1086 resultSet.getInt(
"hash_hit") != 0,
1087 resultSet.getInt(
"tagged") != 0);
1092 }
catch (SQLException ex) {
1093 throw new TskCoreException(
"Error getting events from db: " + querySql, ex);
1108 private static String typeColumnHelper(
final boolean useSubTypes) {
1109 return useSubTypes ?
"event_type_id" :
"super_type_id";
1120 String getSQLWhere(TimelineFilter.RootFilter filter) {
1123 if (filter == null) {
1124 return getTrueLiteral();
1126 result = filter.getSQLWhere(
this);
1132 private String getTrueLiteral() {
1139 throw new UnsupportedOperationException(
"Unsupported DB type: " + caseDB.
getDatabaseType().name());
1157 this.addedEvent = event;
1168 @FunctionalInterface
1169 private interface TSKCoreCheckedFunction<I, O> {
1171 O apply(I input)
throws TskCoreException;
List< Long > getEventIDs(Interval timeRange, TimelineFilter.RootFilter filter)
TimelineEvent getAddedEvent()
TimelineEvent getEventById(long eventID)
ImmutableList< TimelineEventType > getEventTypes()
Interval getSpanningInterval(Interval timeRange, TimelineFilter.RootFilter filter, DateTimeZone timeZone)
Set< Long > getEventIDsForContent(Content content, boolean includeDerivedArtifacts)
TimelineEventType FILE_ACCESSED
Interval getSpanningInterval(Collection< Long > eventIDs)
Set< Long > updateEventsForContentTagAdded(Content content)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)
SortedSet<?extends TimelineEventType > getChildren()
Set< Long > updateEventsForContentTagDeleted(Content content)
Set< Long > updateEventsForHashSetHit(Content content)
TimelineEventType WEB_ACTIVITY
AbstractFile getAbstractFileById(long id)
TimelineEventType FILE_MODIFIED
void releaseSingleUserCaseReadLock()
TimelineEventType MISC_TYPES
static String escapeSingleQuotes(String text)
Set< Long > updateEventsForArtifactTagDeleted(BlackboardArtifact artifact)
void acquireSingleUserCaseWriteLock()
void releaseSingleUserCaseWriteLock()
TimelineEventType FILE_CREATED
TimelineEventType FILE_SYSTEM
Map< TimelineEventType, Long > countEventsByType(Long startTime, Long endTime, TimelineFilter.RootFilter filter, TimelineEventType.HierarchyLevel typeHierachyLevel)
List< Long > getEventIDsForArtifact(BlackboardArtifact artifact)
TimelineEventType ROOT_EVENT_TYPE
List< TimelineEvent > getEvents(Interval timeRange, TimelineFilter.RootFilter filter)
TimelineEventType CUSTOM_TYPES
void acquireSingleUserCaseReadLock()
List< ContentTag > getContentTagsByContent(Content content)
Optional< TimelineEventType > getEventType(long eventTypeID)
TimelineEventType FILE_CHANGED
Set< Long > updateEventsForArtifactTagAdded(BlackboardArtifact artifact)