diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java index f448236346dcd6466fdadf4b59d6c98b73687473..58c85b7ec844400ec87cac021a2fc4a3c71b11dd 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java +++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java @@ -1373,17 +1373,13 @@ public enum ATTRIBUTE_TYPE { bundle.getString("BlackboardAttribute.tskattachments.text"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON), - TSK_GEO_DISTANCE_FROM_HOME_POINT(142, "TSK_GEO_DISTANCE_FROM_HOME_POINT", //NON-NLS - bundle.getString("BlackboardAttribute.tskdronehpdistance.text"), - TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE), - - TSK_GEO_DISTANCE_TRAVELED(143, "TSK_GEO_DISTANCE_TRAVELED", //NON-NLS - bundle.getString("BlackboardAttribute.tskdronedistancetraveled.text"), - TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE), - - TSK_GEO_TRACKPOINTS(144, "TSK_GEO_TRACKPOINTS", + TSK_GEO_TRACKPOINTS(142, "TSK_GEO_TRACKPOINTS", bundle.getString("BlackboardAttribute.tskgeopath.text"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON), + + TSK_GEO_WAYPOINTS(143, "TSK_GEO_WAYPOINTS", + bundle.getString("BlackboardAttribute.tskgeowaypoints.text"), + TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON), ; diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties index 3908626177bb626ce7028f5880bd815a01897b84..96584aa91e722ee42eeaae568c339dc7c13f736c 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties +++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties @@ -191,9 +191,8 @@ BlackboardAttribute.tskaccountsettings.text=Account Settings BlackboardAttribute.tskpasswordhint.text=Password Hint BlackboardAttribute.tskgroups.text=Groups BlackboardAttribute.tskattachments.text=Message Attachments -BlackboardAttribute.tskdronehpdistance.text=Distance From Home Point -BlackboardAttribute.tskdronedistancetraveled.text=Total Distance Traveled -BlackboardAttribute.tskgeopath.text=Waypoint List +BlackboardAttribute.tskgeopath.text=List of Track Points +BlackboardAttribute.tskgeowaypoints.text=List of Waypoints AbstractFile.readLocal.exception.msg4.text=Error reading local file\: {0} AbstractFile.readLocal.exception.msg1.text=Error reading local file, local path is not set AbstractFile.readLocal.exception.msg2.text=Error reading local file, it does not exist at local path\: {0} diff --git a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventTypes.java b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventTypes.java index 2d062e02b5d5172652f64e8403222d50613d652a..1fb7cd76292126b94ace0eb621e79f904a04ded4 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventTypes.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventTypes.java @@ -21,13 +21,12 @@ import com.google.common.net.InternetDomainName; import java.net.URI; import java.net.URISyntaxException; -import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint.GeoTrackPoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList; /** * Container class for various types of timeline events @@ -57,6 +56,7 @@ static class URLArtifactEventType extends TimelineEventArtifactTypeSingleDescrip super(typeID, displayName, superType, artifactType, timeAttribute, descriptionAttribute); } + @Override TimelineEventDescription parseDescription(String fullDescriptionRaw, String medDescriptionRaw, String shortDescriptionRaw) { /** * Parses the full description from db, which is the full URL, to a @@ -99,6 +99,7 @@ static class FilePathEventType extends TimelineEventTypeImpl { super(typeID, displayName, eventTypeZoomLevel, superType); } + @Override TimelineEventDescription parseDescription(String fullDescription, String medDescription, String shortDescription) { return parseFilePathDescription(fullDescription); } @@ -111,6 +112,7 @@ static class FilePathArtifactEventType extends TimelineEventArtifactTypeSingleDe super(typeID, displayName, superType, artifactType, timeAttribute, descriptionAttribute); } + @Override TimelineEventDescription parseDescription(String fullDescriptionRaw, String medDescriptionRaw, String shortDescriptionRaw) { return parseFilePathDescription(fullDescriptionRaw); } @@ -123,6 +125,8 @@ TimelineEventDescription parseDescription(String fullDescriptionRaw, String medD */ static class GPSTrackArtifactEventType extends TimelineEventArtifactTypeSingleDescription { + private final TskGeoTrackpointsUtil trackpointUtil = new TskGeoTrackpointsUtil(); + GPSTrackArtifactEventType(int typeID, String displayName, TimelineEventType superType, BlackboardArtifact.Type artifactType, BlackboardAttribute.Type descriptionAttribute) { // Passing TSK_GEO_TRACKPOINTS as the "time attribute" as more of a place filler, to avoid any null issues super(typeID, displayName, superType, artifactType, new BlackboardAttribute.Type(TSK_GEO_TRACKPOINTS), descriptionAttribute); @@ -138,15 +142,8 @@ public TimelineEventDescriptionWithTime makeEventDescription(BlackboardArtifact } // Get the waypoint list "start time" - List<GeoTrackPoint> points = GeoTrackPoints.deserializePoints(attribute.getValueString()); - Long startTime = null; - for (GeoTrackPoint point : points) { - // Points are in time order so return the first non-null time stamp - startTime = point.getTimeStamp(); - if (startTime != null) { - break; - } - } + GeoTrackPointList pointsList = trackpointUtil.fromAttribute(attribute); + Long startTime = pointsList.getStartTime(); // If we didn't find a startime do not create an event. if (startTime == null) { diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/GeoArtifactsHelper.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/GeoArtifactsHelper.java index 89af4887ff33a91ae54818b7bdef802c2aac6b2a..0e3f99f5a072d33678e470d91dfb72af8b68e6fe 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/GeoArtifactsHelper.java +++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/GeoArtifactsHelper.java @@ -18,7 +18,8 @@ */ package org.sleuthkit.datamodel.blackboardutils; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; +import java.util.ArrayList; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList; import java.util.List; import org.sleuthkit.datamodel.Blackboard.BlackboardException; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -26,7 +27,9 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint.GeoTrackPoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil; /** * Class to help ingest modules create Geolocation artifacts. @@ -34,44 +37,112 @@ */ public final class GeoArtifactsHelper extends ArtifactHelperBase { + private final String programName; + private final TskGeoTrackpointsUtil trackPointAttributeUtil; + private final TskGeoWaypointsUtil waypointsAttributeUtil; + /** * Constructs a geolocation artifact helper for the given source file. * - * @param caseDb Sleuthkit case db. + * @param caseDb Sleuthkit case db. * @param moduleName Name of module using the helper. - * @param srcFile Source file being processed by the module. + * @param programName Optional program name for TSK_PROG_NAME attribute, + * nulls and empty string will be ignored. + * @param srcFile Source file being processed by the module. */ - public GeoArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcFile) { + public GeoArtifactsHelper(SleuthkitCase caseDb, String moduleName, String programName, Content srcFile) { super(caseDb, moduleName, srcFile); + this.programName = programName; + trackPointAttributeUtil = new TskGeoTrackpointsUtil(); + waypointsAttributeUtil = new TskGeoWaypointsUtil(); } /** - * Add a Track from a GPS device to the database. A Track represents a series of points that the device - * has traveled on. This will create a TSK_GPS_TRACK artifact and add it to the case. + * Add a Track from a GPS device to the database. A Track represents a + * series of points that the device has traveled on. This will create a + * TSK_GPS_TRACK artifact and add it to the case. * - * @param trackName Name of GPS track, not required. Pass in null if unknown. - * @param points Set of GeoTrackPoints that the track traversed. Required. + * @param trackName Name of GPS track, not required. + * @param points List of GeoTrackPoints that the track traversed. + * Required. + * @param moreAttributes Optional list of other artifact attributes * * @return TSK_GPS_TRACK artifact * - * @throws TskCoreException If there is an error creating the artifact. + * @throws TskCoreException If there is an error creating the artifact. * @throws BlackboardException If there is a problem posting the artifact */ - public BlackboardArtifact addTrack(String trackName, List<GeoTrackPoint> points) throws TskCoreException, BlackboardException { - if (points == null) { - throw new IllegalArgumentException("GeoTrackPoint instance must be valid"); + public BlackboardArtifact addTrack(String trackName, GeoTrackPointList points, List<BlackboardAttribute> moreAttributes) throws TskCoreException, BlackboardException { + + if(points == null) { + throw new IllegalArgumentException(String.format("addTrack was passed a null list of track points")); } - + BlackboardArtifact artifact = getContent().newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK); + List<BlackboardAttribute> attributes = new ArrayList<>(); if (trackName != null) { - artifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, getModuleName(), trackName)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, getModuleName(), trackName)); + } + + attributes.add(trackPointAttributeUtil.toAttribute(getModuleName(), points)); + + if (programName != null) { + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getModuleName(), programName)); + } + + if (moreAttributes != null) { + attributes.addAll(moreAttributes); + } + + artifact.addAttributes(attributes); + + getSleuthkitCase().getBlackboard().postArtifact(artifact, getModuleName()); + + return artifact; + } + + /** + * Add a Route from a GPS device to the database. This will create a + * TSK_GPS_ROUTE artifact and add it to the case. + * + * @param routeName Optional route name + * @param creationTime Time the route was created, optional. + * @param points List of GeoWaypointList belonging to the route, required + * @param moreAttributes Optional list of other artifact attributes. + * + * @return TSK_GPS_ROUTE artifact + * + * @throws TskCoreException If there is an error creating the artifact. + * @throws BlackboardException If there is a problem posting the artifact. + */ + public BlackboardArtifact addRoute(String routeName, Long creationTime, GeoWaypointList points, List<BlackboardAttribute> moreAttributes) throws TskCoreException, BlackboardException { + + if (points == null) { + throw new IllegalArgumentException(String.format("addRoute was passed a null list of waypoints")); + } + + BlackboardArtifact artifact = getContent().newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE); + List<BlackboardAttribute> attributes = new ArrayList<>(); + + attributes.add(waypointsAttributeUtil.toAttribute(getModuleName(), points)); + + if (routeName != null) { + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, getModuleName(), routeName)); + } + + if (creationTime != null) { + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getModuleName(), creationTime)); + } + + if (programName != null) { + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getModuleName(), programName)); + } + + if (moreAttributes != null) { + attributes.addAll(moreAttributes); } - artifact.addAttribute( - new BlackboardAttribute( - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS, - getModuleName(), - GeoTrackPoints.serializePoints(points))); + artifact.addAttributes(attributes); getSleuthkitCase().getBlackboard().postArtifact(artifact, getModuleName()); diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/BlackboardAttributeUtil.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/BlackboardAttributeUtil.java new file mode 100755 index 0000000000000000000000000000000000000000..d32b264a56a6309498990d944c4125089b9bb48a --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/BlackboardAttributeUtil.java @@ -0,0 +1,48 @@ +/* + * Sleuth Kit Data Model + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier <at> sleuthkit <dot> org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.datamodel.blackboardutils.attributes; + +import org.sleuthkit.datamodel.BlackboardAttribute; + +/** + * An interface for Utility classes to implement for translating + * BlackboardAttributes to and from a particular format. Initial use case is for + * BlackboardAttributes of type TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON. + */ +public interface BlackboardAttributeUtil<T> { + + /** + * Translates the value of type T to a attribute. + * + * @param moduleName Name of module creating the artifact + * @param value Object to Translate to attribute + * + * @return BlackboardAttribute created from value + */ + BlackboardAttribute toAttribute(String moduleName, T value); + + /** + * Translates a attribute to an object of type T. + * + * @param attribute The attribute to be translated to T + * + * @return A new instance of T created from the attribute + */ + T fromAttribute(BlackboardAttribute attribute); +} diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoTrackPoints.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoTrackPoints.java deleted file mode 100755 index 21474995e57360bf5102f1283424ec6ec86bcdfc..0000000000000000000000000000000000000000 --- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoTrackPoints.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Sleuth Kit Data Model - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier <at> sleuthkit <dot> org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.datamodel.blackboardutils.attributes; - -import com.google.gson.Gson; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint.GeoTrackPoint; - -/** - * Helper class to make it easier to serialize and deserialize the list of track - * points with Gson. - * - */ -public final class GeoTrackPoints { - - private final List<GeoTrackPoint> points; - - /** - * Deserialize the given list of GeoTrackPoints. - * - * @param jsonString JSon string of track points. - * - * @return Timestamp ordered list of GeoTrackPoints, empty list will be - * returned if jsonString is null or empty. - */ - public static List<GeoTrackPoint> deserializePoints(String jsonString) { - if (jsonString == null || jsonString.isEmpty()) { - return new ArrayList<>(); - } - - GeoTrackPoints trackPoints = (new Gson()).fromJson(jsonString, GeoTrackPoints.class); - return trackPoints.getTimeOrderedPoints(); - } - - /** - * Serialize the given list of GeoTrackPoints. - * - * @param points List of GeoTrackPoints - * - * @return JSon formatted string is returned or empty string if points was - * null - */ - public static String serializePoints(List<GeoTrackPoint> points) { - if (points == null) { - return ""; - } - - Gson gson = new Gson(); - return gson.toJson(new GeoTrackPoints(points)); - } - - /** - * Constructs a new instance with the give list of GeoTrackPoints. - * - * @param points - */ - private GeoTrackPoints(List<GeoTrackPoint> points) { - if (points == null) { - throw new IllegalArgumentException("Invalid list of track points passed to constructor"); - } - - this.points = points; - } - - /** - * Returns a timestamp ordered copy of the points list. - * - * @return timestamp - */ - private List<GeoTrackPoint> getTimeOrderedPoints() { - return points.stream().sorted().collect(Collectors.toCollection(ArrayList::new)); - } -} diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoWaypoint.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoWaypoint.java deleted file mode 100755 index 14fb0358d991a7a3c495c849a02361337d9d6bde..0000000000000000000000000000000000000000 --- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoWaypoint.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Sleuth Kit Data Model - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier <at> sleuthkit <dot> org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.datamodel.blackboardutils.attributes; - -import com.google.gson.annotations.SerializedName; - -/** - * Class that represents a single waypoint made up of longitude, latitude, and - * altitude. - */ -public class GeoWaypoint { - - @SerializedName("TSK_GEO_LATITUDE") - private final Double latitude; - @SerializedName("TSK_GEO_LONGITUDE") - private final Double longitude; - @SerializedName("TSK_GEO_ALTITUDE") - private final Double altitude; - - /** - * Creates a GeoWaypoint instance. - * - * @param latitude The latitude, required - * @param longitude The longitude, required - * @param altitude The altitude, can be null - */ - public GeoWaypoint(Double latitude, Double longitude, Double altitude) { - if (latitude == null || longitude == null) { - throw new IllegalArgumentException("Null cordinate value passed to waypoint constructor"); - } - - this.latitude = latitude; - this.longitude = longitude; - this.altitude = altitude; - } - - /** - * Returns latitude of the waypoint. - * - * @return Double latitude value - */ - public Double getLatitude() { - return latitude; - } - - /** - * Returns longitude of the waypoint. - * - * @return Double longitude value - */ - public Double getLongitude() { - return longitude; - } - - /** - * Get the altitude if available for this waypoint. - * - * @return Double altitude value, maybe null if not available or applicable - */ - public Double getAltitude() { - return altitude; - } - - /** - * A GeoTrackPoint is a Waypoint with more detailed information about the - * point. - * - */ - public final static class GeoTrackPoint extends GeoWaypoint implements Comparable<GeoTrackPoint> { - - @SerializedName("TSK_GEO_VELOCITY") - private final Double velocity; - @SerializedName("TSK_GEO_DISTANCE_FROM_HOME_POINT") - private final Double distanceFromHP; - @SerializedName("TSK_GEO_DISTANCE_TRAVELED") - private final Double distanceTraveled; - @SerializedName("TSK_DATETIME") - private final Long timestamp; - - /** - * Constructs a GeoTrackPoint with the given attributes. - * - * @param latitude Latitude of the trackpoint, required - * @param longitude Longitude of the trackpoint, required - * @param altitude Altitude of the trackpoint, maybe null - * @param velocity Velocity in meters/sec, maybe null - * @param distanceFromHP Trackpoint distance from an established "home - * point", maybe null if not applicable - * @param distanceTraveled Overall distance traveled in meters at the - * time this trackpoint was created, maybe null - * if not applicable - * @param timestamp Trackpoint creation time, maybe null if not - * applicable - */ - public GeoTrackPoint(Double latitude, - Double longitude, - Double altitude, - Double velocity, - Double distanceFromHP, - Double distanceTraveled, - Long timestamp) { - super(latitude, longitude, altitude); - this.velocity = velocity; - this.distanceFromHP = distanceFromHP; - this.distanceTraveled = distanceTraveled; - this.timestamp = timestamp; - } - - /** - * Returns velocity of the point. - * - * @return Double velocity value, maybe null if not available or - * applicable - */ - public Double getVelocity() { - return velocity; - } - - /** - * Returns distance from home point for the point. - * - * @return Double velocity distance from home point, maybe null if not - * available or applicable - */ - public Double getDistanceFromHP() { - return distanceFromHP; - } - - /** - * Returns distance traveled for the point. - * - * @return Double distance traveled value, maybe null if not available - * or applicable - */ - public Double getDistanceTraveled() { - return distanceTraveled; - } - - /** - * Returns the time stamp (seconds from java/unix epoch) of the track - * point. - * - * @return time stamp of the track point, or null if not available - */ - public Long getTimeStamp() { - return timestamp; - } - - @Override - public int compareTo(GeoTrackPoint otherTP) { - Long otherTimeStamp = otherTP.getTimeStamp(); - - if (timestamp == null && otherTimeStamp != null) { - return -1; - } else if (timestamp != null && otherTimeStamp == null) { - return 1; - } else { - return timestamp.compareTo(otherTP.getTimeStamp()); - } - } - } - -} diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/TskGeoTrackpointsUtil.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/TskGeoTrackpointsUtil.java new file mode 100755 index 0000000000000000000000000000000000000000..ad434f5c7d3e1da86cbf7620629b9fb0a9c9b835 --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/TskGeoTrackpointsUtil.java @@ -0,0 +1,330 @@ +/* + * Sleuth Kit Data Model + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier <at> sleuthkit <dot> org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.datamodel.blackboardutils.attributes; + +import com.google.gson.Gson; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint; + +/** + * Utility class for translating TSK_GEO_TRACKPOINTS attribute values to + * GeoTrackPointList objects and GeoTrackPointList to BlackboardAttributes. + */ +public final class TskGeoTrackpointsUtil implements BlackboardAttributeUtil<GeoTrackPointList> { + + @Override + public BlackboardAttribute toAttribute(String moduleName, GeoTrackPointList value) { + + if (value == null) { + throw new IllegalArgumentException("toAttribute was passed a null list"); + } + + return new BlackboardAttribute( + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS, + moduleName, + toJSON(value)); + } + + @Override + public GeoTrackPointList fromAttribute(BlackboardAttribute attribute) { + if (attribute == null) { + throw new IllegalArgumentException("fromAttribute was passed a null attribute"); + } + + BlackboardAttribute.ATTRIBUTE_TYPE type = BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attribute.getAttributeType().getTypeID()); + if (type != BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS) { + throw new IllegalArgumentException(String.format("Invalid attribute of type %s passed to fromAttribute method. Attribute of type TSK_GEO_TRACKPOINTS is required", type.getDisplayName())); + } + + return fromJSON(attribute.getValueString()); + } + + /** + * Creates a GeoTrackPointList from the given JSON string. + * + * @param jsonString JSon string of track points. + * + * @return Timestamp ordered list of GeoTrackPoints, empty list will be + * returned if jsonString is null or empty. + */ + private static GeoTrackPointList fromJSON(String jsonString) { + if (jsonString == null || jsonString.isEmpty()) { + return null; + } + + return (new Gson()).fromJson(jsonString, GeoTrackPointList.class); + } + + /** + * Returns a JSON string representing the given object. + * + * @return JSON string + */ + private static String toJSON(GeoTrackPointList pointList) { + Gson gson = new Gson(); + return gson.toJson(pointList); + } + + /** + * A list of GeoTrackPoints. + */ + public static class GeoTrackPointList implements Iterable<GeoTrackPointList.GeoTrackPoint> { + + private final List<GeoTrackPoint> pointList; + + /** + * Construct an empty GeoTrackPointList. + */ + public GeoTrackPointList() { + pointList = new ArrayList<>(); + } + + /** + * Construct a new instance with the given list of GeoTrackPoint + * objects. + * + * @param points List of track points, cannot be null. + */ + public GeoTrackPointList(List<GeoTrackPoint> points) { + if (points == null) { + throw new IllegalArgumentException("Constructor was passed a null list"); + } + + pointList = points; + } + + /** + * Add a point to the list of track points. + * + * @param point A point to add to the track point list, cannot be null. + */ + public void addPoint(GeoTrackPoint point) { + if (point == null) { + throw new IllegalArgumentException("addPoint was passed a null list"); + } + + pointList.add(point); + } + + /** + * Adds a new point with the given attributes. + * + * @param latitude Latitude of the trackpoint, required + * @param longitude Longitude of the trackpoint, required + * @param altitude Altitude of the trackpoint, maybe null + * @param name Name of trackpoint, maybe null + * @param velocity Velocity in meters/sec, maybe null + * @param distanceFromHomePoint Track point distance from an established + * "home point", may be null if not + * applicable + * @param distanceTraveled Overall distance traveled in meters at + * the time this trackpoint was created, + * maybe null if not applicable + * @param timestamp Trackpoint creation time, maybe null if + * not applicable + */ + public void addPoint(Double latitude, + Double longitude, + Double altitude, + String name, + Double velocity, + Double distanceFromHomePoint, + Double distanceTraveled, + Long timestamp) { + pointList.add(new GeoTrackPoint( + latitude, + longitude, + altitude, + name, + velocity, + distanceFromHomePoint, + distanceTraveled, + timestamp)); + } + + /** + * Returns an iterator over the points in this GeoTrackPointList. + * + * @return An iterator over the elements of the list. + */ + @Override + public Iterator<GeoTrackPoint> iterator() { + return pointList.iterator(); + } + + /** + * Returns true if this list contains no points. + * + * @return True if this list contains no points. + */ + public boolean isEmpty() { + return pointList.isEmpty(); + } + + /** + * Return the start time for the track. + * + * @return First non-null time stamp or null, if one was not found. + */ + public Long getStartTime() { + List<GeoTrackPoint> orderedPoints = getTimeOrderedPoints(); + if (orderedPoints != null) { + for (GeoTrackPoint point : orderedPoints) { + if (point.getTimeStamp() != null) { + return point.getTimeStamp(); + } + } + } + return null; + } + + /** + * Return the ends time for the track. + * + * @return First non-null time stamp or null, if one was not found. + */ + public Long getEndTime() { + List<GeoTrackPoint> orderedPoints = getTimeOrderedPoints(); + if (orderedPoints != null) { + for (int index = orderedPoints.size() - 1; index >= 0; index--) { + GeoTrackPoint point = orderedPoints.get(index); + if (point.getTimeStamp() != null) { + return point.getTimeStamp(); + } + } + } + return null; + } + + /** + * Returns a timestamp ordered copy of the points list. + * + * @return List of points sorted by timestamps. + */ + private List<GeoTrackPoint> getTimeOrderedPoints() { + return pointList.stream().sorted().collect(Collectors.toCollection(ArrayList::new)); + } + + /** + * A GeoTrackPoint is a Waypoint with more detailed information about + * the point. + * + */ + public final static class GeoTrackPoint extends TskGeoWaypointsUtil.GeoWaypointList.GeoWaypoint implements Comparable<GeoTrackPointList.GeoTrackPoint> { + + private final Double velocity; + private final Double distanceFromHomePoint; + private final Double distanceTraveled; + private final Long timestamp; + + /** + * Constructs a GeoTrackPoint with the given attributes. + * + * @param latitude Latitude of the track point, required + * @param longitude Longitude of the track point, + * required + * @param altitude Altitude of the track point, may be + * null + * @param name Name of track point, may be null + * @param velocity Velocity in meters/sec, may be null + * @param distanceFromHomePoint Track point distance from an + * established "home point", maybe null + * if not applicable + * @param distanceTraveled Overall distance traveled in meters + * at the time this track point was + * created, maybe null if not + * applicable + * @param timestamp Track point creation time, maybe + * null if not applicable + */ + public GeoTrackPoint(Double latitude, + Double longitude, + Double altitude, + String name, + Double velocity, + Double distanceFromHomePoint, + Double distanceTraveled, + Long timestamp) { + super(latitude, longitude, altitude, name); + this.velocity = velocity; + this.distanceFromHomePoint = distanceFromHomePoint; + this.distanceTraveled = distanceTraveled; + this.timestamp = timestamp; + } + + /** + * Returns velocity of the point. + * + * @return Double velocity value, maybe null if not available or + * applicable + */ + public Double getVelocity() { + return velocity; + } + + /** + * Returns distance from home point for the point. + * + * @return Double velocity distance from home point, maybe null if + * not available or applicable + */ + public Double getDistanceFromHomePoint() { + return distanceFromHomePoint; + } + + /** + * Returns distance traveled for the point. + * + * @return Double distance traveled value, maybe null if not + * available or applicable + */ + public Double getDistanceTraveled() { + return distanceTraveled; + } + + /** + * Returns the time stamp (seconds from java/unix epoch) of the + * track point. + * + * @return time stamp of the track point, or null if not available + */ + public Long getTimeStamp() { + return timestamp; + } + + @Override + public int compareTo(GeoTrackPointList.GeoTrackPoint otherTP) { + Long otherTimeStamp = otherTP.getTimeStamp(); + + if (timestamp == null && otherTimeStamp != null) { + return -1; + } else if (timestamp != null && otherTimeStamp == null) { + return 1; + } else { + return timestamp.compareTo(otherTP.getTimeStamp()); + } + } + } + } +} diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/TskGeoWaypointsUtil.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/TskGeoWaypointsUtil.java new file mode 100755 index 0000000000000000000000000000000000000000..08d5a1c6bd6a77ab67bf0992c5a73a2d4e58ebe5 --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/TskGeoWaypointsUtil.java @@ -0,0 +1,197 @@ +/* + * Sleuth Kit Data Model + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier <at> sleuthkit <dot> org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.datamodel.blackboardutils.attributes; + +import com.google.gson.Gson; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList.GeoWaypoint; + +/** + * Utility class for Translating TSK_GEO_WAYPOINTS attribute values to + * GeoWaypointList objects and GeoWaypointList to BlackboardAttributes. + */ +public final class TskGeoWaypointsUtil implements BlackboardAttributeUtil<GeoWaypointList> { + + @Override + public BlackboardAttribute toAttribute(String moduleName, GeoWaypointList value) { + + if (value == null) { + throw new IllegalArgumentException("toAttribute was pass a null list"); + } + + return new BlackboardAttribute( + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS, + moduleName, + toJSON(value)); + } + + @Override + public GeoWaypointList fromAttribute(BlackboardAttribute attribute) { + if (attribute == null) { + throw new IllegalArgumentException("fromAttribute was pass a null list"); + } + + BlackboardAttribute.ATTRIBUTE_TYPE type = BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attribute.getAttributeType().getTypeID()); + if (type != BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS) { + throw new IllegalArgumentException(String.format("Invalid attribute of type %s passed to fromAttribute method. Attribute of type TSK_GEO_WAYPOINTS is required", type.getDisplayName())); + } + + return fromJSON(attribute.getValueString()); + } + + /** + * Deserialize the given list of GeoTrackPoints. + * + * @param jsonString JSon string of track points. + * + * @return Timestamp ordered list of GeoTrackPoints, empty list will be + * returned if jsonString is null or empty. + */ + private static GeoWaypointList fromJSON(String jsonString) { + if (jsonString == null || jsonString.isEmpty()) { + return null; + } + + return (new Gson()).fromJson(jsonString, GeoWaypointList.class); + } + + /** + * Returns a JSON string can than be used as the TSK_GEO_TRACKPOINTS + * attribute of the TSK_GPS_TRACK artifact. + * + * @return JSON string + */ + private static String toJSON(GeoWaypointList pointList) { + Gson gson = new Gson(); + return gson.toJson(pointList); + } + + /** + * Helper class to make it easier to serialize and deserialize the list of + * waypoints points with json. + * + */ + public static final class GeoWaypointList implements Iterable<GeoWaypointList.GeoWaypoint> { + + private final List<GeoWaypoint> points; + + public GeoWaypointList() { + points = new ArrayList<>(); + } + + /** + * Adds a point to the list of waypoints. + * + * @param latitude The latitude, required + * @param longitude The longitude, required + * @param altitude The altitude, can be null + * @param name A name for the point, can be null + */ + public void addPoint(Double latitude, Double longitude, Double altitude, String name) { + points.add(new GeoWaypoint(latitude, longitude, altitude, name)); + } + + /** + * Returns true if this list contains no points. + * + * @return True if this list contains no points. + */ + public boolean isEmpty() { + return points.isEmpty(); + } + + @Override + public Iterator<GeoWaypointList.GeoWaypoint> iterator() { + return points.iterator(); + } + + /** + * Class that represents a single waypoint made up of longitude, + * latitude, and altitude. + */ + public static class GeoWaypoint { + + private final Double latitude; + private final Double longitude; + private final Double altitude; + private final String name; + + /** + * Creates a GeoWaypoint instance. + * + * @param latitude The latitude, required + * @param longitude The longitude, required + * @param altitude The altitude, can be null + * @param name A name for the waypoint, optional + */ + public GeoWaypoint(Double latitude, Double longitude, Double altitude, String name) { + if (latitude == null || longitude == null) { + throw new IllegalArgumentException("Constructor was passed null coordinate"); + } + + this.latitude = latitude; + this.longitude = longitude; + this.altitude = altitude; + this.name = name; + } + + /** + * Returns latitude of the waypoint. + * + * @return Double latitude value + */ + public Double getLatitude() { + return latitude; + } + + /** + * Returns longitude of the waypoint. + * + * @return Double longitude value + */ + public Double getLongitude() { + return longitude; + } + + /** + * Get the altitude if available for this waypoint. + * + * @return Double altitude value, may be null if not available or + * applicable + */ + public Double getAltitude() { + return altitude; + } + + /** + * Returns the name for this waypoint. + * + * @return Returns waypoint name, may be null if not available or + * applicable. + */ + public String getName() { + return name; + } + } + } +}