19 package org.sleuthkit.datamodel;
21 import com.google.common.net.InternetDomainName;
23 import java.net.URISyntaxException;
24 import java.util.stream.Collectors;
25 import java.util.stream.Stream;
26 import org.apache.commons.lang3.StringUtils;
35 class TimelineEventTypes {
37 private TimelineEventTypes() {
45 final static class EmptyExtractor
implements TimelineEventArtifactTypeImpl.TSKCoreCheckedFunction<BlackboardArtifact, String> {
48 public String apply(BlackboardArtifact ignored)
throws TskCoreException {
53 static class URLArtifactEventType
extends TimelineEventArtifactTypeSingleDescription {
55 URLArtifactEventType(
int typeID, String displayName, TimelineEventType superType, BlackboardArtifact.Type artifactType, BlackboardAttribute.Type timeAttribute, BlackboardAttribute.Type descriptionAttribute) {
56 super(typeID, displayName, superType, artifactType, timeAttribute, descriptionAttribute);
60 TimelineEventDescription parseDescription(String fullDescriptionRaw, String medDescriptionRaw, String shortDescriptionRaw) {
68 String fullDescription = fullDescriptionRaw;
70 URI uri =
new URI(fullDescription);
71 String host = uri.getHost();
73 host = StringUtils.strip(fullDescription,
"./");
76 String shortDescription;
77 if (InternetDomainName.isValid(host)) {
78 InternetDomainName domain = InternetDomainName.from(host);
79 shortDescription = (domain.isUnderPublicSuffix())
80 ? domain.topPrivateDomain().toString()
83 shortDescription = host;
86 String mediumDescription =
new URI(uri.getScheme(), uri.getUserInfo(), host, uri.getPort(), uri.getPath(), null, null).toString();
88 return new TimelineEventDescription(fullDescription, mediumDescription, shortDescription);
89 }
catch (URISyntaxException ex) {
91 return new TimelineEventDescription(fullDescription);
96 static class FilePathEventType
extends TimelineEventTypeImpl {
98 FilePathEventType(
long typeID, String displayName, TimelineEventType.HierarchyLevel eventTypeZoomLevel, TimelineEventType superType) {
99 super(typeID, displayName, eventTypeZoomLevel, superType);
103 TimelineEventDescription parseDescription(String fullDescription, String medDescription, String shortDescription) {
104 return parseFilePathDescription(fullDescription);
109 static class FilePathArtifactEventType
extends TimelineEventArtifactTypeSingleDescription {
111 FilePathArtifactEventType(
int typeID, String displayName, TimelineEventType superType, BlackboardArtifact.Type artifactType, BlackboardAttribute.Type timeAttribute, BlackboardAttribute.Type descriptionAttribute) {
112 super(typeID, displayName, superType, artifactType, timeAttribute, descriptionAttribute);
116 TimelineEventDescription parseDescription(String fullDescriptionRaw, String medDescriptionRaw, String shortDescriptionRaw) {
117 return parseFilePathDescription(fullDescriptionRaw);
126 static class GPSTrackArtifactEventType
extends TimelineEventArtifactTypeSingleDescription {
128 GPSTrackArtifactEventType(
int typeID, String displayName, TimelineEventType superType, BlackboardArtifact.Type artifactType, BlackboardAttribute.Type descriptionAttribute) {
130 super(typeID, displayName, superType, artifactType,
new BlackboardAttribute.Type(TSK_GEO_TRACKPOINTS), descriptionAttribute);
134 public TimelineEventDescriptionWithTime makeEventDescription(BlackboardArtifact artifact)
throws TskCoreException {
137 BlackboardAttribute attribute = artifact.getAttribute(
new BlackboardAttribute.Type(TSK_GEO_TRACKPOINTS));
138 if (attribute == null) {
143 GeoTrackPoints pointsList;
145 pointsList = BlackboardJsonAttrUtil.fromAttribute(attribute, GeoTrackPoints.class);
146 }
catch (BlackboardJsonAttrUtil.InvalidJsonException ex) {
147 throw new TskCoreException(
"Unable to parse track points in TSK_GEO_TRACKPOINTS attribute", ex);
149 Long startTime = pointsList.getStartTime();
152 if (startTime == null) {
156 return new TimelineEventDescriptionWithTime(startTime, null, null, extractFullDescription(artifact));
168 static TimelineEventDescription parseFilePathDescription(String fullDescription) {
170 String[] split = fullDescription.split(
"/");
171 String mediumDescription = Stream.of(split)
172 .filter(StringUtils::isNotBlank)
173 .limit(Math.max(1, split.length - 2))
174 .collect(Collectors.joining(
"/",
"/",
""))
175 .replaceAll(
"//",
"/");
177 String shortDescription = Stream.of(split)
178 .filter(StringUtils::isNotBlank)
180 .collect(Collectors.joining(
"/",
"/",
""))
181 .replaceAll(
"//",
"/");
182 return new TimelineEventDescription(fullDescription, mediumDescription, shortDescription);