Autopsy 4.22.1
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 */
20package org.sleuthkit.autopsy.geolocation.datamodel;
21
22import java.sql.ResultSet;
23import java.sql.SQLException;
24import java.util.ArrayList;
25import java.util.Arrays;
26import java.util.List;
27import java.util.logging.Level;
28import org.sleuthkit.autopsy.coreutils.Logger;
29import org.sleuthkit.datamodel.BlackboardArtifact;
30import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
31import org.sleuthkit.datamodel.CaseDbAccessManager;
32import org.sleuthkit.datamodel.BlackboardAttribute;
33import org.sleuthkit.datamodel.SleuthkitCase;
34import org.sleuthkit.datamodel.TskCoreException;
35import org.sleuthkit.datamodel.DataSource;
36
41public final class WaypointBuilder {
42
43 private static final Logger logger = Logger.getLogger(WaypointBuilder.class.getName());
44
45 private final static String TIME_TYPE_IDS = String.format("%d, %d",
46 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
47 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID());
48
49 private final static String GEO_ATTRIBUTE_TYPE_IDS = String.format("%d, %d, %d",
50 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),
51 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(),
52 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS.getTypeID());
53
54 // SELECT statement for getting a list of waypoints where %s is a comma separated list
55 // of attribute type ids.
56 private final static String GEO_ARTIFACT_QUERY
57 = "SELECT artifact_id, artifact_type_id "
58 + "FROM blackboard_attributes "
59 + "WHERE attribute_type_id IN (%s) "; //NON-NLS
60
61 // SELECT statement to get only artifact_ids
62 private final static String GEO_ARTIFACT_QUERY_ID_ONLY
63 = "SELECT artifact_id "
64 + "FROM blackboard_attributes "
65 + "WHERE attribute_type_id IN (%s) "; //NON-NLS
66
67 // This Query will return a list of waypoint artifacts
68 private final static String GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY
69 = "SELECT blackboard_attributes.artifact_id "
70 + "FROM blackboard_attributes, blackboard_artifacts "
71 + "WHERE blackboard_attributes.artifact_id = blackboard_artifacts.artifact_id "
72 + "AND blackboard_attributes.attribute_type_id IN(%s) "
73 + "AND data_source_obj_id IN (%s)"; //NON-NLS
74
75 // Select will return the "most recent" timestamp from all waypoings
76 private final static String MOST_RECENT_TIME
77 = "SELECT MAX(value_int64) - (%d * 86400)" //86400 is the number of seconds in a day.
78 + "FROM blackboard_attributes "
79 + "WHERE attribute_type_id IN(%s) "
80 + "AND artifact_id "
81 + "IN ( "
82 + "%s" //GEO_ARTIFACT with or without data source
83 + " )";
84
85 // Returns a list of artifacts with no time stamp
86 private final static String SELECT_WO_TIMESTAMP
87 = "SELECT DISTINCT artifact_id, artifact_type_id "
88 + "FROM blackboard_attributes "
89 + "WHERE artifact_id NOT IN (%s) "
90 + "AND artifact_id IN (%s)"; //NON-NLS
91
95 public interface WaypointFilterQueryCallBack {
96
104 }
105
109 private WaypointBuilder() {
110
111 }
112
126 public static List<Waypoint> getAllWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
127 List<Waypoint> points = new ArrayList<>();
128
129 points.addAll(getTrackpointWaypoints(skCase));
130 points.addAll(getEXIFWaypoints(skCase));
131 points.addAll(getSearchWaypoints(skCase));
132 points.addAll(getLastKnownWaypoints(skCase));
133 points.addAll(getBookmarkWaypoints(skCase));
134
135 return points;
136 }
137
145 public static List<Route> getRoutes(List<Waypoint> waypoints) {
146 List<Route> routeList = new ArrayList<>();
147 for (Waypoint point : waypoints) {
148 GeoPath path = point.getParentGeoPath();
149 if (path instanceof Route) {
150 Route route = (Route) path;
151 if (!routeList.contains(route)) {
152 routeList.add(route);
153 }
154 }
155 }
156
157 return routeList;
158 }
159
167 public static List<Track> getTracks(List<Waypoint> waypoints) {
168 List<Track> trackList = new ArrayList<>();
169 for (Waypoint point : waypoints) {
170 GeoPath path = point.getParentGeoPath();
171 if (path instanceof Track) {
172 Track route = (Track) path;
173 if (!trackList.contains(route)) {
174 trackList.add(route);
175 }
176 }
177 }
178
179 return trackList;
180 }
181
189 public static List<Area> getAreas(List<Waypoint> waypoints) {
190 List<Area> areaList = new ArrayList<>();
191 for (Waypoint point : waypoints) {
192 GeoPath path = point.getParentGeoPath();
193 if (path instanceof Area) {
194 Area area = (Area) path;
195 if (!areaList.contains(area)) {
196 areaList.add(area);
197 }
198 }
199 }
200
201 return areaList;
202 }
203
213 @SuppressWarnings("deprecation")
214 public static List<Waypoint> getTrackpointWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
215 List<BlackboardArtifact> artifacts = null;
216 try {
217 artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);
218 } catch (TskCoreException ex) {
219 throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_TRACKPOINT", ex);//NON-NLS
220 }
221
222 List<Waypoint> points = new ArrayList<>();
223 for (BlackboardArtifact artifact : artifacts) {
224 try {
225 Waypoint point = new TrackpointWaypoint(artifact);
226 points.add(point);
227 } catch (GeoLocationDataException ex) {
228 logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_TRACKPOINT artifactID: %d", artifact.getArtifactID()));//NON-NLS
229 }
230 }
231 return points;
232 }
233
241 public static List<Waypoint> getTrackpointWaypoints(List<Waypoint> waypoints) {
242 List<Waypoint> specificPoints = new ArrayList<>();
243
244 for (Waypoint point : waypoints) {
245 if (point instanceof TrackpointWaypoint) {
246 specificPoints.add(point);
247 }
248 }
249
250 return specificPoints;
251 }
252
262 static public List<Waypoint> getEXIFWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
263 List<BlackboardArtifact> artifacts = null;
264 try {
265 artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_METADATA_EXIF);
266 } catch (TskCoreException ex) {
267 throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);//NON-NLS
268 }
269
270 List<Waypoint> points = new ArrayList<>();
271 if (artifacts != null) {
272 for (BlackboardArtifact artifact : artifacts) {
273 try {
274 Waypoint point = new EXIFWaypoint(artifact);
275 points.add(point);
276 } catch (GeoLocationDataException ex) {
277 // I am a little relucant to log this error because I suspect
278 // this will happen more often than not. It is valid for
279 // METADAT_EXIF to not have longitude and latitude
280 }
281 }
282 }
283 return points;
284 }
285
293 public static List<Waypoint> getEXIFWaypoints(List<Waypoint> waypoints) {
294 List<Waypoint> specificPoints = new ArrayList<>();
295
296 for (Waypoint point : waypoints) {
297 if (point instanceof EXIFWaypoint) {
298 specificPoints.add(point);
299 }
300 }
301
302 return specificPoints;
303 }
304
314 public static List<Waypoint> getSearchWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
315 List<BlackboardArtifact> artifacts = null;
316 try {
317 artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_SEARCH);
318 } catch (TskCoreException ex) {
319 throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_SEARCH", ex);//NON-NLS
320 }
321
322 List<Waypoint> points = new ArrayList<>();
323 if (artifacts != null) {
324 for (BlackboardArtifact artifact : artifacts) {
325 try {
326 Waypoint point = new SearchWaypoint(artifact);
327 points.add(point);
328 } catch (GeoLocationDataException ex) {
329 logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_SEARCH artifactID: %d", artifact.getArtifactID()));//NON-NLS
330 }
331 }
332 }
333 return points;
334 }
335
343 public static List<Waypoint> getSearchWaypoints(List<Waypoint> waypoints) {
344 List<Waypoint> specificPoints = new ArrayList<>();
345
346 for (Waypoint point : waypoints) {
347 if (point instanceof SearchWaypoint) {
348 specificPoints.add(point);
349 }
350 }
351
352 return specificPoints;
353 }
354
364 public static List<Waypoint> getLastKnownWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
365 List<BlackboardArtifact> artifacts = null;
366 try {
367 artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION);
368 } catch (TskCoreException ex) {
369 throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);//NON-NLS
370 }
371
372 List<Waypoint> points = new ArrayList<>();
373 if (artifacts != null) {
374 for (BlackboardArtifact artifact : artifacts) {
375 try {
376 Waypoint point = new LastKnownWaypoint(artifact);
377 points.add(point);
378 } catch (GeoLocationDataException ex) {
379 logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_LAST_KNOWN_LOCATION artifactID: %d", artifact.getArtifactID()));//NON-NLS
380 }
381 }
382 }
383 return points;
384 }
385
394 public static List<Waypoint> getLastKnownWaypoints(List<Waypoint> waypoints) {
395 List<Waypoint> specificPoints = new ArrayList<>();
396
397 for (Waypoint point : waypoints) {
398 if (point instanceof LastKnownWaypoint) {
399 specificPoints.add(point);
400 }
401 }
402
403 return specificPoints;
404 }
405
415 public static List<Waypoint> getBookmarkWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
416 List<BlackboardArtifact> artifacts = null;
417 try {
418 artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_BOOKMARK);
419 } catch (TskCoreException ex) {
420 throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_BOOKMARK", ex);//NON-NLS
421 }
422
423 List<Waypoint> points = new ArrayList<>();
424 if (artifacts != null) {
425 for (BlackboardArtifact artifact : artifacts) {
426 try {
427 Waypoint point = new BookmarkWaypoint(artifact);
428 points.add(point);
429 } catch (GeoLocationDataException ex) {
430 logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_BOOKMARK artifactID: %d", artifact.getArtifactID()), ex);//NON-NLS
431 }
432 }
433 }
434 return points;
435 }
436
445 public static List<Waypoint> getBookmarkWaypoints(List<Waypoint> waypoints) {
446 List<Waypoint> specificPoints = new ArrayList<>();
447
448 for (Waypoint point : waypoints) {
449 if (point instanceof BookmarkWaypoint) {
450 specificPoints.add(point);
451 }
452 }
453
454 return specificPoints;
455 }
456
490 static public void getAllWaypoints(SleuthkitCase skCase, List<DataSource> dataSources, List<ARTIFACT_TYPE> artifactTypes, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp, WaypointFilterQueryCallBack queryCallBack) throws GeoLocationDataException {
491 String query = buildQuery(dataSources, showAll, cntDaysFromRecent, noTimeStamp);
492
493 try {
494 // The CaseDBAccessManager.select function will add a SELECT
495 // to the beginning of the query
496 if (query.startsWith("SELECT")) { //NON-NLS
497 query = query.replaceFirst("SELECT", ""); //NON-NLS
498 }
499
500 skCase.getCaseDbAccessManager().select(query, new CaseDbAccessManager.CaseDbAccessQueryCallback() {
501 @Override
502 public void process(ResultSet rs) {
503 GeoLocationParseResult<Waypoint> waypointResults = new GeoLocationParseResult<>();
504 try {
505 while (rs.next()) {
506 int artifact_type_id = rs.getInt("artifact_type_id"); //NON-NLS
507 long artifact_id = rs.getLong("artifact_id"); //NON-NLS
508
509 ARTIFACT_TYPE type = ARTIFACT_TYPE.fromID(artifact_type_id);
510 if (artifactTypes.contains(type)) {
511 waypointResults.add(getWaypointForArtifact(skCase.getBlackboardArtifact(artifact_id), type));
512 }
513
514 }
515
516 queryCallBack.process(waypointResults);
517 } catch (SQLException | TskCoreException ex) {
518 logger.log(Level.WARNING, "Failed to filter waypoint.", ex); //NON-NLS
519 }
520
521 }
522 });
523 } catch (TskCoreException ex) {
524 logger.log(Level.WARNING, "Failed to filter waypoint.", ex); //NON-NLS
525 }
526 }
527
536 static private String buildQueryForWaypointsWOTimeStamps(List<DataSource> dataSources) {
537
538// SELECT_WO_TIMESTAMP
539// SELECT DISTINCT artifact_id, artifact_type_id
540// FROM blackboard_attributes
541// WHERE artifact_id NOT IN (%s)
542// AND artifact_id IN (%s)
543// GEO_ARTIFACT_QUERY_ID_ONLY
544// SELECT artifact_id
545// FROM blackboard_attributes
546// WHERE attribute_type_id IN (%d, %d)
547 return String.format(SELECT_WO_TIMESTAMP,
549 getWaypointListQuery(dataSources));
550 }
551
574 static private String buildQuery(List<DataSource> dataSources, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp) {
575 String mostRecentQuery = "";
576
577 if (!showAll && cntDaysFromRecent > 0) {
578// MOST_RECENT_TIME
579// SELECT MAX(value_int64) - (%d * 86400)
580// FROM blackboard_attributes
581// WHERE attribute_type_id IN(%s)
582// AND artifact_id
583// IN ( %s )
584//
585 mostRecentQuery = String.format("AND value_int64 > (%s)", //NON-NLS
586 String.format(MOST_RECENT_TIME,
587 cntDaysFromRecent, TIME_TYPE_IDS,
588 getWaypointListQuery(dataSources)
589 ));
590 }
591
592// GEO_ARTIFACT_QUERY
593// SELECT artifact_id, artifact_type_id
594// FROM blackboard_attributes
595// WHERE attribute_type_id IN (%s)
596 String query = String.format(GEO_ARTIFACT_QUERY, TIME_TYPE_IDS);
597
598 // That are in the list of artifacts for the given data Sources
599 query += String.format("AND artifact_id IN(%s)", getWaypointListQuery(dataSources)); //NON-NLS
600 query += mostRecentQuery;
601
602 if (showAll || noTimeStamp) {
603 query = String.format("%s UNION %s", buildQueryForWaypointsWOTimeStamps(dataSources), query); //NON-NLS
604 }
605
606 return query;
607 }
608
621 static private String getWaypointListQuery(List<DataSource> dataSources) {
622
623 if (dataSources == null || dataSources.isEmpty()) {
624// GEO_ARTIFACT_QUERY
625// SELECT artifact_id, artifact_type_id
626// FROM blackboard_attributes
627// WHERE attribute_type_id IN (%s)
628 return String.format(GEO_ARTIFACT_QUERY, GEO_ATTRIBUTE_TYPE_IDS);
629 }
630
631 String dataSourceList = "";
632 for (DataSource source : dataSources) {
633 dataSourceList += Long.toString(source.getId()) + ",";
634 }
635
636 if (!dataSourceList.isEmpty()) {
637 // Remove the last ,
638 dataSourceList = dataSourceList.substring(0, dataSourceList.length() - 1);
639 }
640
642 dataSourceList);
643 }
644
651 private interface ParserWithError<T> {
652
653 T parse(BlackboardArtifact artifact) throws GeoLocationDataException;
654 }
655
665 private static GeoLocationParseResult<Waypoint> parseWaypoint(ParserWithError<Waypoint> parser, BlackboardArtifact artifact) {
666 try {
667 return new GeoLocationParseResult<>(Arrays.asList(parser.parse(artifact)), true);
668 } catch (GeoLocationDataException ex) {
669 return new GeoLocationParseResult<>(null, false);
670 }
671 }
672
682 private static GeoLocationParseResult<Waypoint> parseWaypoints(ParserWithError<List<Waypoint>> parser, BlackboardArtifact artifact) {
683 try {
684 return new GeoLocationParseResult<>(parser.parse(artifact), true);
685 } catch (GeoLocationDataException ignored) {
686 return new GeoLocationParseResult<>(null, false);
687 }
688 }
689
698 private static GeoLocationParseResult<Waypoint> getWaypointForArtifact(BlackboardArtifact artifact, ARTIFACT_TYPE type) {
700 switch (type) {
701 case TSK_METADATA_EXIF:
702 waypoints.add(parseWaypoint(EXIFWaypoint::new, artifact));
703 break;
704 case TSK_GPS_BOOKMARK:
705 waypoints.add(parseWaypoint(BookmarkWaypoint::new, artifact));
706 break;
707 case TSK_GPS_TRACKPOINT:
708 waypoints.add(parseWaypoint(TrackpointWaypoint::new, artifact));
709 break;
710 case TSK_GPS_SEARCH:
711 waypoints.add(parseWaypoint(SearchWaypoint::new, artifact));
712 break;
713 case TSK_GPS_ROUTE:
714 waypoints.add(parseWaypoints((a) -> new Route(a).getRoute(), artifact));
715 break;
716 case TSK_GPS_LAST_KNOWN_LOCATION:
717 waypoints.add(parseWaypoint(LastKnownWaypoint::new, artifact));
718 break;
719 case TSK_GPS_TRACK:
720 waypoints.add(parseWaypoints((a) -> new Track(a).getPath(), artifact));
721 break;
722 default:
723 waypoints.add(parseWaypoint(CustomArtifactWaypoint::new, artifact));
724 }
725
726 return waypoints;
727 }
728}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static GeoLocationParseResult< Waypoint > parseWaypoint(ParserWithError< Waypoint > parser, BlackboardArtifact artifact)
static String buildQuery(List< DataSource > dataSources, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp)
static List< Waypoint > getBookmarkWaypoints(SleuthkitCase skCase)
static List< Area > getAreas(List< Waypoint > waypoints)
static List< Waypoint > getBookmarkWaypoints(List< Waypoint > waypoints)
static List< Waypoint > getSearchWaypoints(SleuthkitCase skCase)
static List< Waypoint > getLastKnownWaypoints(SleuthkitCase skCase)
static void getAllWaypoints(SleuthkitCase skCase, List< DataSource > dataSources, List< ARTIFACT_TYPE > artifactTypes, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp, WaypointFilterQueryCallBack queryCallBack)
static List< Route > getRoutes(List< Waypoint > waypoints)
static List< Waypoint > getSearchWaypoints(List< Waypoint > waypoints)
static List< Waypoint > getEXIFWaypoints(List< Waypoint > waypoints)
static GeoLocationParseResult< Waypoint > parseWaypoints(ParserWithError< List< Waypoint > > parser, BlackboardArtifact artifact)
static String getWaypointListQuery(List< DataSource > dataSources)
static List< Waypoint > getTrackpointWaypoints(List< Waypoint > waypoints)
static List< Waypoint > getLastKnownWaypoints(List< Waypoint > waypoints)
static GeoLocationParseResult< Waypoint > getWaypointForArtifact(BlackboardArtifact artifact, ARTIFACT_TYPE type)
static List< Waypoint > getTrackpointWaypoints(SleuthkitCase skCase)
static String buildQueryForWaypointsWOTimeStamps(List< DataSource > dataSources)
static List< Waypoint > getAllWaypoints(SleuthkitCase skCase)
static List< Waypoint > getEXIFWaypoints(SleuthkitCase skCase)
static List< Track > getTracks(List< Waypoint > waypoints)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.