Autopsy  4.14.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
WaypointBuilder.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2019 Basis Technology Corp.
6  * contact: carrier <at> sleuthkit <dot> org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 package org.sleuthkit.autopsy.geolocation.datamodel;
21 
22 import java.sql.ResultSet;
23 import java.sql.SQLException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.logging.Level;
28 import org.sleuthkit.datamodel.BlackboardArtifact;
29 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
30 import org.sleuthkit.datamodel.CaseDbAccessManager;
31 import org.sleuthkit.datamodel.BlackboardAttribute;
32 import org.sleuthkit.datamodel.SleuthkitCase;
33 import org.sleuthkit.datamodel.TskCoreException;
34 import org.sleuthkit.datamodel.DataSource;
35 
40 public final class WaypointBuilder {
41 
42  private static final Logger logger = Logger.getLogger(WaypointBuilder.class.getName());
43 
44  private final static String TIME_TYPE_IDS = String.format("%d, %d",
45  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
46  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID());
47 
48  private final static String GEO_ATTRIBUTE_TYPE_IDS = String.format("%d, %d, %d",
49  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),
50  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(),
51  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS.getTypeID());
52 
53  // SELECT statement for getting a list of waypoints where %s is a comma separated list
54  // of attribute type ids.
55  private final static String GEO_ARTIFACT_QUERY
56  = "SELECT artifact_id, artifact_type_id "
57  + "FROM blackboard_attributes "
58  + "WHERE attribute_type_id IN (%s) "; //NON-NLS
59 
60  // SELECT statement to get only artifact_ids
61  private final static String GEO_ARTIFACT_QUERY_ID_ONLY
62  = "SELECT artifact_id "
63  + "FROM blackboard_attributes "
64  + "WHERE attribute_type_id IN (%s) "; //NON-NLS
65 
66  // This Query will return a list of waypoint artifacts
67  private final static String GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY
68  = "SELECT blackboard_attributes.artifact_id "
69  + "FROM blackboard_attributes, blackboard_artifacts "
70  + "WHERE blackboard_attributes.artifact_id = blackboard_artifacts.artifact_id "
71  + "AND blackboard_attributes.attribute_type_id IN(%s) "
72  + "AND data_source_obj_id IN (%s)"; //NON-NLS
73 
74  // Select will return the "most recent" timestamp from all waypoings
75  private final static String MOST_RECENT_TIME
76  = "SELECT MAX(value_int64) - (%d * 86400)" //86400 is the number of seconds in a day.
77  + "FROM blackboard_attributes "
78  + "WHERE attribute_type_id IN(%s) "
79  + "AND artifact_id "
80  + "IN ( "
81  + "%s" //GEO_ARTIFACT with or without data source
82  + " )";
83 
84  // Returns a list of artifacts with no time stamp
85  private final static String SELECT_WO_TIMESTAMP
86  = "SELECT DISTINCT artifact_id, artifact_type_id "
87  + "FROM blackboard_attributes "
88  + "WHERE artifact_id NOT IN (%s) "
89  + "AND artifact_id IN (%s)"; //NON-NLS
90 
94  public interface WaypointFilterQueryCallBack {
95 
101  void process(List<Waypoint> wwaypoints);
102  }
103 
107  private WaypointBuilder() {
108 
109  }
110 
124  public static List<Waypoint> getAllWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
125  List<Waypoint> points = new ArrayList<>();
126 
127  points.addAll(getTrackpointWaypoints(skCase));
128  points.addAll(getEXIFWaypoints(skCase));
129  points.addAll(getSearchWaypoints(skCase));
130  points.addAll(getLastKnownWaypoints(skCase));
131  points.addAll(getBookmarkWaypoints(skCase));
132 
133  return points;
134  }
135 
143  public static List<Route> getRoutes(List<Waypoint> waypoints) {
144  List<Route> routeList = new ArrayList<>();
145  for (Waypoint point : waypoints) {
146  GeoPath path = point.getParentGeoPath();
147  if (path instanceof Route) {
148  Route route = (Route) path;
149  if (!routeList.contains(route)) {
150  routeList.add(route);
151  }
152  }
153  }
154 
155  return routeList;
156  }
157 
165  public static List<Track> getTracks(List<Waypoint> waypoints) {
166  List<Track> trackList = new ArrayList<>();
167  for (Waypoint point : waypoints) {
168  GeoPath path = point.getParentGeoPath();
169  if (path instanceof Track) {
170  Track route = (Track) path;
171  if (!trackList.contains(route)) {
172  trackList.add(route);
173  }
174  }
175  }
176 
177  return trackList;
178  }
179 
189  @SuppressWarnings("deprecation")
190  public static List<Waypoint> getTrackpointWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
191  List<BlackboardArtifact> artifacts = null;
192  try {
193  artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);
194  } catch (TskCoreException ex) {
195  throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_TRACKPOINT", ex);//NON-NLS
196  }
197 
198  List<Waypoint> points = new ArrayList<>();
199  for (BlackboardArtifact artifact : artifacts) {
200  try {
201  Waypoint point = new TrackpointWaypoint(artifact);
202  points.add(point);
203  } catch (GeoLocationDataException ex) {
204  logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_TRACKPOINT artifactID: %d", artifact.getArtifactID()));//NON-NLS
205  }
206  }
207  return points;
208  }
209 
217  public static List<Waypoint> getTrackpointWaypoints(List<Waypoint> waypoints) {
218  List<Waypoint> specificPoints = new ArrayList<>();
219 
220  for (Waypoint point : waypoints) {
221  if (point instanceof TrackpointWaypoint) {
222  specificPoints.add(point);
223  }
224  }
225 
226  return specificPoints;
227  }
228 
238  static public List<Waypoint> getEXIFWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
239  List<BlackboardArtifact> artifacts = null;
240  try {
241  artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_METADATA_EXIF);
242  } catch (TskCoreException ex) {
243  throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);//NON-NLS
244  }
245 
246  List<Waypoint> points = new ArrayList<>();
247  if (artifacts != null) {
248  for (BlackboardArtifact artifact : artifacts) {
249  try {
250  Waypoint point = new EXIFWaypoint(artifact);
251  points.add(point);
252  } catch (GeoLocationDataException ex) {
253  // I am a little relucant to log this error because I suspect
254  // this will happen more often than not. It is valid for
255  // METADAT_EXIF to not have longitude and latitude
256  }
257  }
258  }
259  return points;
260  }
261 
269  public static List<Waypoint> getEXIFWaypoints(List<Waypoint> waypoints) {
270  List<Waypoint> specificPoints = new ArrayList<>();
271 
272  for (Waypoint point : waypoints) {
273  if (point instanceof EXIFWaypoint) {
274  specificPoints.add(point);
275  }
276  }
277 
278  return specificPoints;
279  }
280 
290  public static List<Waypoint> getSearchWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
291  List<BlackboardArtifact> artifacts = null;
292  try {
293  artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_SEARCH);
294  } catch (TskCoreException ex) {
295  throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_SEARCH", ex);//NON-NLS
296  }
297 
298  List<Waypoint> points = new ArrayList<>();
299  if (artifacts != null) {
300  for (BlackboardArtifact artifact : artifacts) {
301  try {
302  Waypoint point = new SearchWaypoint(artifact);
303  points.add(point);
304  } catch (GeoLocationDataException ex) {
305  logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_SEARCH artifactID: %d", artifact.getArtifactID()));//NON-NLS
306  }
307  }
308  }
309  return points;
310  }
311 
319  public static List<Waypoint> getSearchWaypoints(List<Waypoint> waypoints) {
320  List<Waypoint> specificPoints = new ArrayList<>();
321 
322  for (Waypoint point : waypoints) {
323  if (point instanceof SearchWaypoint) {
324  specificPoints.add(point);
325  }
326  }
327 
328  return specificPoints;
329  }
330 
340  public static List<Waypoint> getLastKnownWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
341  List<BlackboardArtifact> artifacts = null;
342  try {
343  artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION);
344  } catch (TskCoreException ex) {
345  throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);//NON-NLS
346  }
347 
348  List<Waypoint> points = new ArrayList<>();
349  if (artifacts != null) {
350  for (BlackboardArtifact artifact : artifacts) {
351  try {
352  Waypoint point = new LastKnownWaypoint(artifact);
353  points.add(point);
354  } catch (GeoLocationDataException ex) {
355  logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_LAST_KNOWN_LOCATION artifactID: %d", artifact.getArtifactID()));//NON-NLS
356  }
357  }
358  }
359  return points;
360  }
361 
370  public static List<Waypoint> getLastKnownWaypoints(List<Waypoint> waypoints) {
371  List<Waypoint> specificPoints = new ArrayList<>();
372 
373  for (Waypoint point : waypoints) {
374  if (point instanceof LastKnownWaypoint) {
375  specificPoints.add(point);
376  }
377  }
378 
379  return specificPoints;
380  }
381 
391  public static List<Waypoint> getBookmarkWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
392  List<BlackboardArtifact> artifacts = null;
393  try {
394  artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_BOOKMARK);
395  } catch (TskCoreException ex) {
396  throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_BOOKMARK", ex);//NON-NLS
397  }
398 
399  List<Waypoint> points = new ArrayList<>();
400  if (artifacts != null) {
401  for (BlackboardArtifact artifact : artifacts) {
402  try {
403  Waypoint point = new BookmarkWaypoint(artifact);
404  points.add(point);
405  } catch (GeoLocationDataException ex) {
406  logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_BOOKMARK artifactID: %d", artifact.getArtifactID()), ex);//NON-NLS
407  }
408  }
409  }
410  return points;
411  }
412 
421  public static List<Waypoint> getBookmarkWaypoints(List<Waypoint> waypoints) {
422  List<Waypoint> specificPoints = new ArrayList<>();
423 
424  for (Waypoint point : waypoints) {
425  if (point instanceof BookmarkWaypoint) {
426  specificPoints.add(point);
427  }
428  }
429 
430  return specificPoints;
431  }
432 
466  static public void getAllWaypoints(SleuthkitCase skCase, List<DataSource> dataSources, List<ARTIFACT_TYPE> artifactTypes, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp, WaypointFilterQueryCallBack queryCallBack) throws GeoLocationDataException {
467  String query = buildQuery(dataSources, showAll, cntDaysFromRecent, noTimeStamp);
468 
469  logger.log(Level.INFO, query);
470 
471  try {
472  // The CaseDBAccessManager.select function will add a SELECT
473  // to the beginning of the query
474  if (query.startsWith("SELECT")) { //NON-NLS
475  query = query.replaceFirst("SELECT", ""); //NON-NLS
476  }
477 
478  skCase.getCaseDbAccessManager().select(query, new CaseDbAccessManager.CaseDbAccessQueryCallback() {
479  @Override
480  public void process(ResultSet rs) {
481  List<Waypoint> waypoints = new ArrayList<>();
482  try {
483  while (rs.next()) {
484  int artifact_type_id = rs.getInt("artifact_type_id"); //NON-NLS
485  long artifact_id = rs.getLong("artifact_id"); //NON-NLS
486 
487  ARTIFACT_TYPE type = ARTIFACT_TYPE.fromID(artifact_type_id);
488  if (artifactTypes.contains(type)) {
489  waypoints.addAll(getWaypointForArtifact(skCase.getBlackboardArtifact(artifact_id), type));
490  }
491 
492  }
493  queryCallBack.process(waypoints);
494  } catch (GeoLocationDataException | SQLException | TskCoreException ex) {
495  logger.log(Level.WARNING, "Failed to filter waypoint.", ex); //NON-NLS
496  }
497 
498  }
499  });
500  } catch (TskCoreException ex) {
501  logger.log(Level.WARNING, "Failed to filter waypoint.", ex); //NON-NLS
502  }
503  }
504 
513  static private String buildQueryForWaypointsWOTimeStamps(List<DataSource> dataSources) {
514 
515 // SELECT_WO_TIMESTAMP
516 // SELECT DISTINCT artifact_id, artifact_type_id
517 // FROM blackboard_attributes
518 // WHERE artifact_id NOT IN (%s)
519 // AND artifact_id IN (%s)
520 // GEO_ARTIFACT_QUERY_ID_ONLY
521 // SELECT artifact_id
522 // FROM blackboard_attributes
523 // WHERE attribute_type_id IN (%d, %d)
524  return String.format(SELECT_WO_TIMESTAMP,
525  String.format(GEO_ARTIFACT_QUERY_ID_ONLY,TIME_TYPE_IDS),
526  getWaypointListQuery(dataSources));
527  }
528 
551  static private String buildQuery(List<DataSource> dataSources, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp) {
552  String mostRecentQuery = "";
553 
554  if (!showAll && cntDaysFromRecent > 0) {
555 // MOST_RECENT_TIME
556 // SELECT MAX(value_int64) - (%d * 86400)
557 // FROM blackboard_attributes
558 // WHERE attribute_type_id IN(%s)
559 // AND artifact_id
560 // IN ( %s )
561 //
562  mostRecentQuery = String.format("AND value_int64 > (%s)", //NON-NLS
563  String.format(MOST_RECENT_TIME,
564  cntDaysFromRecent, TIME_TYPE_IDS,
565  getWaypointListQuery(dataSources)
566  ));
567  }
568 
569 // GEO_ARTIFACT_QUERY
570 // SELECT artifact_id, artifact_type_id
571 // FROM blackboard_attributes
572 // WHERE attribute_type_id IN (%s)
573  String query = String.format(GEO_ARTIFACT_QUERY, TIME_TYPE_IDS);
574 
575  // That are in the list of artifacts for the given data Sources
576  query += String.format("AND artifact_id IN(%s)", getWaypointListQuery(dataSources)); //NON-NLS
577  query += mostRecentQuery;
578 
579  if (showAll || noTimeStamp) {
580  query = String.format("%s UNION %s", buildQueryForWaypointsWOTimeStamps(dataSources), query); //NON-NLS
581  }
582 
583  return query;
584  }
585 
598  static private String getWaypointListQuery(List<DataSource> dataSources) {
599 
600  if (dataSources == null || dataSources.isEmpty()) {
601 // GEO_ARTIFACT_QUERY
602 // SELECT artifact_id, artifact_type_id
603 // FROM blackboard_attributes
604 // WHERE attribute_type_id IN (%s)
605  return String.format(GEO_ARTIFACT_QUERY, GEO_ATTRIBUTE_TYPE_IDS);
606  }
607 
608  String dataSourceList = "";
609  for (DataSource source : dataSources) {
610  dataSourceList += Long.toString(source.getId()) + ",";
611  }
612 
613  if (!dataSourceList.isEmpty()) {
614  // Remove the last ,
615  dataSourceList = dataSourceList.substring(0, dataSourceList.length() - 1);
616  }
617 
618  return String.format(GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY, GEO_ATTRIBUTE_TYPE_IDS,
619  dataSourceList);
620  }
621 
632  static private List<Waypoint> getWaypointForArtifact(BlackboardArtifact artifact, ARTIFACT_TYPE type) throws GeoLocationDataException {
633  List<Waypoint> waypoints = new ArrayList<>();
634  switch (type) {
635  case TSK_METADATA_EXIF:
636  waypoints.add(new EXIFWaypoint(artifact));
637  break;
638  case TSK_GPS_BOOKMARK:
639  waypoints.add(new BookmarkWaypoint(artifact));
640  break;
641  case TSK_GPS_TRACKPOINT:
642  waypoints.add(new TrackpointWaypoint(artifact));
643  break;
644  case TSK_GPS_SEARCH:
645  waypoints.add(new SearchWaypoint(artifact));
646  break;
647  case TSK_GPS_ROUTE:
648  Route route = new Route(artifact);
649  waypoints.addAll(route.getRoute());
650  break;
651  case TSK_GPS_LAST_KNOWN_LOCATION:
652  waypoints.add(new LastKnownWaypoint(artifact));
653  break;
654  case TSK_GPS_TRACK:
655  Track track = new Track(artifact);
656  waypoints.addAll(track.getPath());
657  break;
658  default:
659  waypoints.add(new CustomArtifactWaypoint(artifact));
660  }
661 
662  return waypoints;
663  }
664 }
static List< Waypoint > getLastKnownWaypoints(List< Waypoint > waypoints)
static String buildQuery(List< DataSource > dataSources, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp)
static List< Waypoint > getBookmarkWaypoints(SleuthkitCase skCase)
static List< Waypoint > getWaypointForArtifact(BlackboardArtifact artifact, ARTIFACT_TYPE type)
static List< Waypoint > getBookmarkWaypoints(List< Waypoint > waypoints)
static void getAllWaypoints(SleuthkitCase skCase, List< DataSource > dataSources, List< ARTIFACT_TYPE > artifactTypes, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp, WaypointFilterQueryCallBack queryCallBack)
static List< Waypoint > getSearchWaypoints(SleuthkitCase skCase)
static List< Waypoint > getSearchWaypoints(List< Waypoint > waypoints)
static List< Track > getTracks(List< Waypoint > waypoints)
static List< Waypoint > getTrackpointWaypoints(SleuthkitCase skCase)
static List< Route > getRoutes(List< Waypoint > waypoints)
static List< Waypoint > getAllWaypoints(SleuthkitCase skCase)
static String getWaypointListQuery(List< DataSource > dataSources)
static List< Waypoint > getEXIFWaypoints(List< Waypoint > waypoints)
static List< Waypoint > getTrackpointWaypoints(List< Waypoint > waypoints)
static String buildQueryForWaypointsWOTimeStamps(List< DataSource > dataSources)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static List< Waypoint > getLastKnownWaypoints(SleuthkitCase skCase)
static List< Waypoint > getEXIFWaypoints(SleuthkitCase skCase)

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.