diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java index a4ba698b3ca283fa2ff24534e650c59b90e00606..ca96479e47afbe5f663552fbbc48fdde523d946e 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java +++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java @@ -1,7 +1,7 @@ /* * Sleuth Kit Data Model * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2020 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1228,7 +1228,10 @@ public enum ARTIFACT_TYPE implements SleuthkitVisitableItem { * Stores metadata about an object. */ TSK_METADATA(57, "TSK_METADATA", //NON-NLS - bundle.getString("BlackboardArtifact.tskMetadata.text")); + bundle.getString("BlackboardArtifact.tskMetadata.text")), + + TSK_GPS_TRACK(58, "TSK_GPS_TRACK", + bundle.getString("BlackboardArtifact.tskTrack.text")); private final String label; private final int typeId; diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java index 93d5f4d5ab2c6bd295aba1c3355d845bfccb3b52..f448236346dcd6466fdadf4b59d6c98b73687473 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java +++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java @@ -1,7 +1,7 @@ /* * Sleuth Kit Data Model * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2020 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1371,8 +1371,20 @@ public enum ATTRIBUTE_TYPE { TSK_ATTACHMENTS (141, "TSK_ATTACHMENTS", bundle.getString("BlackboardAttribute.tskattachments.text"), - TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON); + 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", + bundle.getString("BlackboardAttribute.tskgeopath.text"), + TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON), + ; private final int typeID; diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties index ece4a3767815020281d967aede5b5e5a204efd53..dfcd926e960a73f339742f659befcc9decf2baee 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties +++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties @@ -53,6 +53,7 @@ BlackboardArtifact.tskWebCache.text=Web Cache BlackboardArtifact.tskClipboardContent.text=Clipboard Content BlackboardArtifact.tskUserContentSuspected.text=User Content Suspected BlackboardArtifact.tskMetadata.text=Metadata +BlackboardArtifact.tskTrack.text=GPS Track BlackboardArtifact.shortDescriptionDate.text=at {0} BlackboardArtifact.tskAssociatedObject.text=Associated Object BlackboardAttribute.tskAccountType.text=Account Type @@ -190,6 +191,9 @@ 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 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/blackboardutils/GeoArtifactsHelper.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/GeoArtifactsHelper.java index 4a19e2a4d180f3b72b3bef04bea9f852c9a63611..61e4c6daa3f6df22b1c751c7b57da64d1819cb08 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/GeoArtifactsHelper.java +++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/GeoArtifactsHelper.java @@ -18,18 +18,21 @@ */ package org.sleuthkit.datamodel.blackboardutils; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; import org.sleuthkit.datamodel.Blackboard.BlackboardException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint.GeoTrackPoint; /** - * Class to help ingest modules create Geolocation artifacts. + * Class to help ingest modules create Geolocation artifacts. * */ public final class GeoArtifactsHelper extends ArtifactHelperBase { @@ -44,7 +47,40 @@ public final class GeoArtifactsHelper extends ArtifactHelperBase { public GeoArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcFile) { super(caseDb, moduleName, srcFile); } - + + /** + * Creates and adds a TSK_GPS_TRACK artifact to the case with specified + * attributes and posts the artifact to the Blackboard. + * + * @param trackName Name of GPS track, not required + * @param points GeoTrackPoints, required. + * + * @return TSK_GPS_TRACK 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"); + } + + BlackboardArtifact artifact = getContent().newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK); + if (trackName != null) { + artifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, getModuleName(), trackName)); + } + + artifact.addAttribute( + new BlackboardAttribute( + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS, + getModuleName(), + GeoTrackPoints.serializePoints(points))); + + getSleuthkitCase().getBlackboard().postArtifact(artifact, getModuleName()); + + return artifact; + } + /** * Adds a TSK_GPS_TRACKPOINT artifact. * @@ -58,7 +94,7 @@ public GeoArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcFi * * @return GPS trackpoint artifact added * - * @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 addGPSTrackpoint(double latitude, double longitude, @@ -84,7 +120,7 @@ public BlackboardArtifact addGPSTrackpoint(double latitude, double longitude, * * @return GPS trackpoint artifact added * - * @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 addGPSTrackpoint(double latitude, double longitude, long timeStamp, String name, String programName, @@ -115,5 +151,5 @@ public BlackboardArtifact addGPSTrackpoint(double latitude, double longitude, lo // return the artifact return gpsTrackpointArtifact; } - + } diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoTrackPoints.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoTrackPoints.java new file mode 100755 index 0000000000000000000000000000000000000000..21474995e57360bf5102f1283424ec6ec86bcdfc --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoTrackPoints.java @@ -0,0 +1,91 @@ +/* + * 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 new file mode 100755 index 0000000000000000000000000000000000000000..14fb0358d991a7a3c495c849a02361337d9d6bde --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/attributes/GeoWaypoint.java @@ -0,0 +1,179 @@ +/* + * 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()); + } + } + } + +}