mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge pull request #6493 from APriestman/6984_addSupportForGPSArea
6984 Add support for GPS area artifacts
This commit is contained in:
commit
3acada9c25
@ -121,6 +121,8 @@ public final class IconsUtil {
|
||||
imageFile = "web-account-type.png"; //NON-NLS
|
||||
} else if (typeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) {
|
||||
imageFile = "web-form-address.png"; //NON-NLS
|
||||
} else if (typeID == ARTIFACT_TYPE.TSK_GPS_AREA.getTypeID()) {
|
||||
imageFile = "gps-area.png"; //NON-NLS
|
||||
} else {
|
||||
imageFile = "artifact-icon.png"; //NON-NLS
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javafx.util.Pair;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationParseResult;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.Area;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.Track;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.Waypoint;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder;
|
||||
@ -81,7 +81,7 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
* @param wasEntirelySuccessful True if no errors occurred while processing.
|
||||
*/
|
||||
abstract void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks,
|
||||
boolean wasEntirelySuccessful);
|
||||
List<Set<MapWaypoint>> areas, boolean wasEntirelySuccessful);
|
||||
|
||||
@Override
|
||||
public void process(GeoLocationParseResult<Waypoint> waypointResults) {
|
||||
@ -93,36 +93,54 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
logger.log(Level.WARNING, "Exception thrown while retrieving list of Tracks", ex);
|
||||
}
|
||||
}
|
||||
|
||||
Pair<List<Waypoint>, List<List<Waypoint>>> waypointsAndTracks = createWaypointList(
|
||||
|
||||
GeoLocationParseResult<Area> areaResults = null;
|
||||
if (filters.getArtifactTypes().contains(ARTIFACT_TYPE.TSK_GPS_AREA)) {
|
||||
try {
|
||||
areaResults = Area.getAreas(Case.getCurrentCase().getSleuthkitCase(), filters.getDataSources());
|
||||
} catch (GeoLocationDataException ex) {
|
||||
logger.log(Level.WARNING, "Exception thrown while retrieving list of Areas", ex);
|
||||
}
|
||||
}
|
||||
|
||||
GeoDataSet geoDataSet = createWaypointList(
|
||||
waypointResults.getItems(),
|
||||
(trackResults == null) ? new ArrayList<Track>() : trackResults.getItems());
|
||||
(trackResults == null) ? new ArrayList<>() : trackResults.getItems(),
|
||||
(areaResults == null) ? new ArrayList<>() : areaResults.getItems());
|
||||
|
||||
|
||||
final Set<MapWaypoint> pointSet = MapWaypoint.getWaypoints(waypointsAndTracks.getKey());
|
||||
final Set<MapWaypoint> pointSet = MapWaypoint.getWaypoints(geoDataSet.getWaypoints());
|
||||
final List<Set<MapWaypoint>> trackSets = new ArrayList<>();
|
||||
for (List<Waypoint> t : waypointsAndTracks.getValue()) {
|
||||
for (List<Waypoint> t : geoDataSet.getTracks()) {
|
||||
trackSets.add(MapWaypoint.getWaypoints(t));
|
||||
}
|
||||
final List<Set<MapWaypoint>> areaSets = new ArrayList<>();
|
||||
for (List<Waypoint> t : geoDataSet.getAreas()) {
|
||||
areaSets.add(MapWaypoint.getWaypoints(t));
|
||||
}
|
||||
|
||||
handleFilteredWaypointSet(
|
||||
pointSet, trackSets,
|
||||
(trackResults == null || trackResults.isSuccessfullyParsed()) && waypointResults.isSuccessfullyParsed());
|
||||
pointSet, trackSets, areaSets,
|
||||
(trackResults == null || trackResults.isSuccessfullyParsed())
|
||||
&& (areaResults == null || areaResults.isSuccessfullyParsed())
|
||||
&& waypointResults.isSuccessfullyParsed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a complete list of waypoints including the tracks. Takes into
|
||||
* Returns a complete list of waypoints including the tracks and areas. Takes into
|
||||
* account the current filters and includes waypoints as approprate.
|
||||
*
|
||||
* @param waypoints List of waypoints
|
||||
* @param tracks List of tracks
|
||||
* @param areas List of areas
|
||||
*
|
||||
* @return A list of waypoints including the tracks based on the current
|
||||
* filters.
|
||||
* @return A GeoDataSet object containing a list of waypoints including the tracks and areas based on the current
|
||||
filters.
|
||||
*/
|
||||
private Pair<List<Waypoint>, List<List<Waypoint>>> createWaypointList(List<Waypoint> waypoints, List<Track> tracks) {
|
||||
private GeoDataSet createWaypointList(List<Waypoint> waypoints, List<Track> tracks, List<Area> areas) {
|
||||
final List<Waypoint> completeList = new ArrayList<>();
|
||||
List<List<Waypoint>> filteredTracks = new ArrayList<>();
|
||||
List<List<Waypoint>> filteredAreas = new ArrayList<>();
|
||||
|
||||
if (tracks != null) {
|
||||
Long timeRangeEnd;
|
||||
@ -149,7 +167,14 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
} else {
|
||||
completeList.addAll(waypoints);
|
||||
}
|
||||
return new Pair<>(completeList, filteredTracks);
|
||||
|
||||
// Areas don't have timestamps so add all of them
|
||||
for (Area area : areas) {
|
||||
completeList.addAll(area.getPath());
|
||||
filteredAreas.add(area.getPath());
|
||||
}
|
||||
|
||||
return new GeoDataSet(completeList, filteredTracks, filteredAreas);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -270,4 +295,31 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
|
||||
return -1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to collect filtered GPS objects.
|
||||
*/
|
||||
static class GeoDataSet {
|
||||
private final List<Waypoint> waypoints;
|
||||
private final List<List<Waypoint>> tracks;
|
||||
private final List<List<Waypoint>> areas;
|
||||
|
||||
GeoDataSet(List<Waypoint> waypoints, List<List<Waypoint>> tracks, List<List<Waypoint>> areas) {
|
||||
this.waypoints = waypoints;
|
||||
this.tracks = tracks;
|
||||
this.areas = areas;
|
||||
}
|
||||
|
||||
List<Waypoint> getWaypoints() {
|
||||
return waypoints;
|
||||
}
|
||||
|
||||
List<List<Waypoint>> getTracks() {
|
||||
return tracks;
|
||||
}
|
||||
|
||||
List<List<Waypoint>> getAreas() {
|
||||
return areas;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,8 @@ class GeoFilterPanel extends javax.swing.JPanel {
|
||||
ARTIFACT_TYPE.TSK_GPS_SEARCH,
|
||||
ARTIFACT_TYPE.TSK_GPS_TRACK,
|
||||
ARTIFACT_TYPE.TSK_GPS_TRACKPOINT,
|
||||
ARTIFACT_TYPE.TSK_METADATA_EXIF
|
||||
ARTIFACT_TYPE.TSK_METADATA_EXIF,
|
||||
ARTIFACT_TYPE.TSK_GPS_AREA
|
||||
};
|
||||
|
||||
/**
|
||||
@ -523,6 +524,7 @@ class GeoFilterPanel extends javax.swing.JPanel {
|
||||
+ " or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()
|
||||
+ " or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS.getTypeID()
|
||||
+ " or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS.getTypeID()
|
||||
+ " or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_AREAPOINTS.getTypeID()
|
||||
+ " )"
|
||||
+ " ) as innerTable";
|
||||
try (SleuthkitCase.CaseDbQuery queryResult = sleuthkitCase.executeQuery(queryStr);
|
||||
|
@ -115,7 +115,8 @@ public final class GeolocationTopComponent extends TopComponent {
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID())) {
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_AREA.getTypeID())) {
|
||||
|
||||
showRefreshPanel(true);
|
||||
}
|
||||
@ -330,7 +331,7 @@ public final class GeolocationTopComponent extends TopComponent {
|
||||
*
|
||||
* @param waypointList
|
||||
*/
|
||||
void addWaypointsToMap(Set<MapWaypoint> waypointList, List<Set<MapWaypoint>> tracks) {
|
||||
void addWaypointsToMap(Set<MapWaypoint> waypointList, List<Set<MapWaypoint>> tracks, List<Set<MapWaypoint>> areas) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -348,6 +349,7 @@ public final class GeolocationTopComponent extends TopComponent {
|
||||
mapPanel.clearWaypoints();
|
||||
mapPanel.setWaypoints(waypointList);
|
||||
mapPanel.setTracks(tracks);
|
||||
mapPanel.setAreas(areas);
|
||||
mapPanel.initializePainter();
|
||||
setWaypointLoading(false);
|
||||
geoFilterPanel.setEnabled(true);
|
||||
@ -505,8 +507,9 @@ public final class GeolocationTopComponent extends TopComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks, boolean wasEntirelySuccessful) {
|
||||
addWaypointsToMap(mapWaypoints, tracks);
|
||||
void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks,
|
||||
List<Set<MapWaypoint>> areas, boolean wasEntirelySuccessful) {
|
||||
addWaypointsToMap(mapWaypoints, tracks, areas);
|
||||
|
||||
// if there is an error, present to the user.
|
||||
if (!wasEntirelySuccessful) {
|
||||
|
@ -23,6 +23,7 @@ import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
@ -30,6 +31,7 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@ -91,11 +93,14 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Set<Integer> DOT_WAYPOINT_TYPES = new HashSet<>();
|
||||
private static final int DOT_SIZE = 12;
|
||||
private static final Set<Integer> VERY_SMALL_DOT_WAYPOINT_TYPES = new HashSet<>();
|
||||
private static final int VERY_SMALL_DOT_SIZE = 6;
|
||||
|
||||
private boolean zoomChanging;
|
||||
private KdTree<MapWaypoint> waypointTree;
|
||||
private Set<MapWaypoint> waypointSet;
|
||||
private List<Set<MapWaypoint>> tracks = new ArrayList<>();
|
||||
private List<Set<MapWaypoint>> areas = new ArrayList<>();
|
||||
|
||||
private Popup currentPopup;
|
||||
private final PopupFactory popupFactory;
|
||||
@ -108,12 +113,13 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
private BufferedImage transparentWaypointImage;
|
||||
|
||||
private MapWaypoint currentlySelectedWaypoint;
|
||||
private Set<MapWaypoint> currentlySelectedTrack;
|
||||
private Set<MapWaypoint> currentlySelectedSet;
|
||||
|
||||
static {
|
||||
DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID());
|
||||
DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID());
|
||||
DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID());
|
||||
VERY_SMALL_DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_AREA.getTypeID());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,6 +247,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
waypointPainter.setRenderer(new MapWaypointRenderer());
|
||||
|
||||
ArrayList<Painter<JXMapViewer>> painters = new ArrayList<>();
|
||||
painters.add(new MapAreaRenderer(areas));
|
||||
painters.add(new MapTrackRenderer(tracks));
|
||||
painters.add(waypointPainter);
|
||||
|
||||
@ -342,6 +349,15 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
void setTracks(List<Set<MapWaypoint>> tracks) {
|
||||
this.tracks = tracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given list of areas from which to draw paths later
|
||||
*
|
||||
* @param areas
|
||||
*/
|
||||
void setAreas(List<Set<MapWaypoint>> areas) {
|
||||
this.areas = areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current zoom level.
|
||||
@ -361,7 +377,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
void clearWaypoints() {
|
||||
waypointTree = null;
|
||||
currentlySelectedWaypoint = null;
|
||||
currentlySelectedTrack = null;
|
||||
currentlySelectedSet = null;
|
||||
if (currentPopup != null) {
|
||||
currentPopup.hide();
|
||||
}
|
||||
@ -514,6 +530,13 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
DOT_SIZE,
|
||||
DOT_SIZE
|
||||
);
|
||||
} else if (VERY_SMALL_DOT_WAYPOINT_TYPES.contains(nextWaypoint.getArtifactTypeID())) {
|
||||
rect = new Rectangle(
|
||||
pointX - (VERY_SMALL_DOT_SIZE / 2),
|
||||
pointY - (VERY_SMALL_DOT_SIZE / 2),
|
||||
VERY_SMALL_DOT_SIZE,
|
||||
VERY_SMALL_DOT_SIZE
|
||||
);
|
||||
} else {
|
||||
rect = new Rectangle(
|
||||
pointX - (whiteWaypointImage.getWidth() / 2),
|
||||
@ -717,16 +740,24 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
if (waypoints.size() > 0) {
|
||||
MapWaypoint selection = waypoints.get(0);
|
||||
currentlySelectedWaypoint = selection;
|
||||
currentlySelectedTrack = null;
|
||||
currentlySelectedSet = null;
|
||||
for (Set<MapWaypoint> track : tracks) {
|
||||
if (track.contains(selection)) {
|
||||
currentlySelectedTrack = track;
|
||||
currentlySelectedSet = track;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currentlySelectedSet == null) {
|
||||
for (Set<MapWaypoint> area : areas) {
|
||||
if (area.contains(selection)) {
|
||||
currentlySelectedSet = area;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentlySelectedWaypoint = null;
|
||||
currentlySelectedTrack = null;
|
||||
currentlySelectedSet = null;
|
||||
}
|
||||
showDetailsPopup();
|
||||
}
|
||||
@ -755,6 +786,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
private class MapWaypointRenderer implements WaypointRenderer<MapWaypoint> {
|
||||
|
||||
private final Map<Color, BufferedImage> dotImageCache = new HashMap<>();
|
||||
private final Map<Color, BufferedImage> verySmallDotImageCache = new HashMap<>();
|
||||
private final Map<Color, BufferedImage> waypointImageCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
@ -766,7 +798,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
private Color getColor(MapWaypoint waypoint) {
|
||||
Color baseColor = waypoint.getColor();
|
||||
if (waypoint.equals(currentlySelectedWaypoint)
|
||||
|| (currentlySelectedTrack != null && currentlySelectedTrack.contains(waypoint))) {
|
||||
|| (currentlySelectedSet != null && currentlySelectedSet.contains(waypoint))) {
|
||||
// Highlight this waypoint since it is selected
|
||||
return Color.YELLOW;
|
||||
} else {
|
||||
@ -778,11 +810,11 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
* Creates a dot image with the specified color
|
||||
*
|
||||
* @param color the color of the new image
|
||||
* @param s the size of the dot
|
||||
*
|
||||
* @return the new dot image
|
||||
*/
|
||||
private BufferedImage createTrackDotImage(Color color) {
|
||||
int s = DOT_SIZE;
|
||||
private BufferedImage createTrackDotImage(Color color, int s) {
|
||||
|
||||
BufferedImage ret = new BufferedImage(s, s, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = ret.createGraphics();
|
||||
@ -831,7 +863,13 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
|
||||
if (DOT_WAYPOINT_TYPES.contains(waypoint.getArtifactTypeID())) {
|
||||
image = dotImageCache.computeIfAbsent(color, k -> {
|
||||
return createTrackDotImage(color);
|
||||
return createTrackDotImage(color, DOT_SIZE);
|
||||
});
|
||||
// Center the dot on the GPS coordinate
|
||||
y -= image.getHeight() / 2;
|
||||
} else if (VERY_SMALL_DOT_WAYPOINT_TYPES.contains(waypoint.getArtifactTypeID())) {
|
||||
image = verySmallDotImageCache.computeIfAbsent(color, k -> {
|
||||
return createTrackDotImage(color, VERY_SMALL_DOT_SIZE);
|
||||
});
|
||||
// Center the dot on the GPS coordinate
|
||||
y -= image.getHeight() / 2;
|
||||
@ -903,4 +941,74 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderer for map areas
|
||||
*/
|
||||
private class MapAreaRenderer implements Painter<JXMapViewer> {
|
||||
|
||||
private final List<Set<MapWaypoint>> areas;
|
||||
|
||||
MapAreaRenderer(List<Set<MapWaypoint>> areas) {
|
||||
this.areas = areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shade in the area on the map.
|
||||
*
|
||||
* @param area The waypoints defining the outline of the area.
|
||||
* @param g Graphics2D
|
||||
* @param map JXMapViewer
|
||||
*/
|
||||
private void drawArea(Set<MapWaypoint> area, Graphics2D g, JXMapViewer map) {
|
||||
if (area.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
boolean first = true;
|
||||
|
||||
GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, area.size());
|
||||
|
||||
for (MapWaypoint wp : area) {
|
||||
Point2D p = map.getTileFactory().geoToPixel(wp.getPosition(), map.getZoom());
|
||||
int thisX = (int) p.getX();
|
||||
int thisY = (int) p.getY();
|
||||
|
||||
if (first) {
|
||||
polygon.moveTo(thisX, thisY);
|
||||
first = false;
|
||||
} else {
|
||||
polygon.lineTo(thisX, thisY);
|
||||
}
|
||||
}
|
||||
polygon.closePath();
|
||||
|
||||
Color areaColor = area.iterator().next().getColor();
|
||||
final double maxColorValue = 255.0;
|
||||
g.setPaint(new Color((float)(areaColor.getRed() / maxColorValue),
|
||||
(float)(areaColor.getGreen() / maxColorValue),
|
||||
(float)(areaColor.getBlue() / maxColorValue),
|
||||
.2f));
|
||||
g.fill(polygon);
|
||||
g.draw(polygon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics2D g, JXMapViewer map, int w, int h) {
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
|
||||
Rectangle bounds = map.getViewportBounds();
|
||||
g2d.translate(-bounds.x, -bounds.y);
|
||||
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.setStroke(new BasicStroke(2));
|
||||
|
||||
for (Set<MapWaypoint> area : areas) {
|
||||
drawArea(area, g2d, map);
|
||||
}
|
||||
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
|
||||
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID(), Color.ORANGE);
|
||||
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID(), Color.ORANGE);
|
||||
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID(), Color.MAGENTA);
|
||||
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_AREA.getTypeID(), new Color(0x8a2be2)); // Blue violet
|
||||
}
|
||||
|
||||
private final Waypoint dataModelWaypoint;
|
||||
|
171
Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Area.java
Normal file
171
Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Area.java
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* 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.autopsy.geolocation.datamodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil;
|
||||
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil.InvalidJsonException;
|
||||
import org.sleuthkit.datamodel.blackboardutils.attributes.GeoAreaPoints;
|
||||
|
||||
/**
|
||||
* A GPS track with which wraps the TSK_GPS_AREA artifact.
|
||||
*/
|
||||
public final class Area extends GeoPath {
|
||||
/**
|
||||
* Construct a new Area for the given artifact.
|
||||
*
|
||||
* @param artifact
|
||||
*
|
||||
* @throws GeoLocationDataException
|
||||
*/
|
||||
public Area(BlackboardArtifact artifact) throws GeoLocationDataException {
|
||||
this(artifact, Waypoint.getAttributesFromArtifactAsMap(artifact));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an Area for the given artifact and attributeMap.
|
||||
*
|
||||
* @param artifact TSK_GPD_TRACK artifact
|
||||
* @param attributeMap Map of the artifact attributes
|
||||
*
|
||||
* @throws GeoLocationDataException
|
||||
*/
|
||||
private Area(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
|
||||
super(artifact, getAreaName(attributeMap));
|
||||
|
||||
GeoAreaPoints points = getPointsList(attributeMap);
|
||||
buildPath(points, artifact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the area from the attributeMap. Track name is stored
|
||||
* in the attribute TSK_NAME
|
||||
*
|
||||
* @param attributeMap
|
||||
*
|
||||
* @return Area name or empty string if none was available.
|
||||
*/
|
||||
private static String getAreaName(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) {
|
||||
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
|
||||
|
||||
return attribute != null ? attribute.getValueString() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the list of AreaWaypoints from the GeoTrackPoint list.
|
||||
*
|
||||
* @param points GeoAreaPoints object.
|
||||
* @param artifact The artifact to which these points belong
|
||||
*
|
||||
* @throws GeoLocationDataException
|
||||
*/
|
||||
@Messages({
|
||||
"# {0} - area name",
|
||||
"GEOArea_point_label_header=Area outline point for area: {0}"
|
||||
})
|
||||
private void buildPath(GeoAreaPoints points, BlackboardArtifact artifact) throws GeoLocationDataException {
|
||||
for (GeoAreaPoints.AreaPoint point : points) {
|
||||
addToPath(new AreaWaypoint(artifact, Bundle.GEOArea_point_label_header(getLabel()), point));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of GeoAreaPoints from the attributeMap. Creates the
|
||||
* GeoAreaPoint list from the TSK_GEO_AREAPOINTS attribute.
|
||||
*
|
||||
* @param attributeMap Map of artifact attributes.
|
||||
*
|
||||
* @return GeoTrackPoint list empty list if the attribute was not found.
|
||||
*
|
||||
* @throws GeoLocationDataException
|
||||
*/
|
||||
private GeoAreaPoints getPointsList(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
|
||||
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_AREAPOINTS);
|
||||
if (attribute == null) {
|
||||
throw new GeoLocationDataException("No TSK_GEO_AREAPOINTS attribute present in attribute map to parse.");
|
||||
}
|
||||
|
||||
try {
|
||||
return BlackboardJsonAttrUtil.fromAttribute(attribute, GeoAreaPoints.class);
|
||||
} catch (InvalidJsonException ex) {
|
||||
throw new GeoLocationDataException("Unable to parse area points in TSK_GEO_AREAPOINTS attribute", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Waypoint subclass for the points of an area outline.
|
||||
*/
|
||||
final class AreaWaypoint extends Waypoint {
|
||||
|
||||
private final List<Waypoint.Property> propertyList;
|
||||
|
||||
/**
|
||||
* Construct a AreaWaypoint.
|
||||
*
|
||||
* @param artifact the artifact to which this waypoint belongs
|
||||
*
|
||||
* @param pointLabel the label for the waypoint
|
||||
*
|
||||
* @param point GeoAreaPoint
|
||||
*
|
||||
* @throws GeoLocationDataException
|
||||
*/
|
||||
AreaWaypoint(BlackboardArtifact artifact, String pointLabel, GeoAreaPoints.AreaPoint point) throws GeoLocationDataException {
|
||||
super(artifact, pointLabel,
|
||||
null,
|
||||
point.getLatitude(),
|
||||
point.getLongitude(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Area.this);
|
||||
|
||||
propertyList = createPropertyList(point);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded to return a property list that is generated from the
|
||||
* GeoTrackPoint instead of an artifact.
|
||||
*
|
||||
* @return unmodifiable list of Waypoint.Property
|
||||
*/
|
||||
@Override
|
||||
public List<Waypoint.Property> getOtherProperties() {
|
||||
return Collections.unmodifiableList(propertyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a propertyList specific to GeoAreaPoints.
|
||||
*
|
||||
* @param point GeoAreaPoint to get values from.
|
||||
*
|
||||
* @return A list of Waypoint.properies.
|
||||
*/
|
||||
private List<Waypoint.Property> createPropertyList(GeoAreaPoints.AreaPoint point) {
|
||||
List<Waypoint.Property> list = new ArrayList<>();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
# {0} - area name
|
||||
GEOArea_point_label_header=Area outline point for area: {0}
|
||||
# {0} - track name
|
||||
GEOTrack_point_label_header=Trackpoint for track: {0}
|
||||
LastKnownWaypoint_Label=Last Known Location
|
||||
|
@ -22,6 +22,8 @@ package org.sleuthkit.autopsy.geolocation.datamodel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
@ -31,6 +33,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Class representing a series of waypoints that form a path.
|
||||
*/
|
||||
public class GeoPath {
|
||||
private static final Logger LOGGER = Logger.getLogger(GeoPath.class.getName());
|
||||
|
||||
private final List<Waypoint> waypointList;
|
||||
private final String pathName;
|
||||
private final BlackboardArtifact artifact;
|
||||
@ -62,13 +66,13 @@ public class GeoPath {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of Routes from the TSK_GPS_TRACK artifacts.
|
||||
* Gets the list of Tracks from the TSK_GPS_TRACK artifacts.
|
||||
*
|
||||
* @param skCase Currently open SleuthkitCase
|
||||
* @param sourceList List of source to return tracks from, maybe null to
|
||||
* return tracks from all sources
|
||||
*
|
||||
* @return List of Route objects, empty list will be returned if no Routes
|
||||
* @return List of Track objects, empty list will be returned if no tracks
|
||||
* were found
|
||||
*
|
||||
* @throws GeoLocationDataException
|
||||
@ -85,6 +89,7 @@ public class GeoPath {
|
||||
tracks.add(new Track(artifact));
|
||||
|
||||
} catch (GeoLocationDataException e) {
|
||||
LOGGER.log(Level.WARNING, "Error loading track from artifact with ID " + artifact.getArtifactID(), e);
|
||||
allParsedSuccessfully = false;
|
||||
}
|
||||
}
|
||||
@ -94,6 +99,41 @@ public class GeoPath {
|
||||
}
|
||||
return new GeoLocationParseResult<Track>(tracks, allParsedSuccessfully);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of Areas from the TSK_GPS_AREA artifacts.
|
||||
*
|
||||
* @param skCase Currently open SleuthkitCase
|
||||
* @param sourceList List of source to return areas from, may be null to
|
||||
* return areas from all sources
|
||||
*
|
||||
* @return List of Area objects, empty list will be returned if no areas
|
||||
* were found
|
||||
*
|
||||
* @throws GeoLocationDataException
|
||||
*/
|
||||
public static GeoLocationParseResult<Area> getAreas(SleuthkitCase skCase, List<? extends Content> sourceList) throws GeoLocationDataException {
|
||||
List<BlackboardArtifact> artifacts;
|
||||
boolean allParsedSuccessfully = true;
|
||||
List<Area> areas = new ArrayList<>();
|
||||
try {
|
||||
artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_AREA);
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
if (sourceList == null || sourceList.contains(artifact.getDataSource())) {
|
||||
try {
|
||||
areas.add(new Area(artifact));
|
||||
|
||||
} catch (GeoLocationDataException e) {
|
||||
LOGGER.log(Level.WARNING, "Error loading track from artifact with ID " + artifact.getArtifactID(), e);
|
||||
allParsedSuccessfully = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_BOOKMARK", ex);
|
||||
}
|
||||
return new GeoLocationParseResult<>(areas, allParsedSuccessfully);
|
||||
}
|
||||
|
||||
/**
|
||||
* Path constructor.
|
||||
|
@ -22,20 +22,17 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil;
|
||||
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil.InvalidJsonException;
|
||||
import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* A GPS track with which wraps the TSK_GPS_TRACK artifact.
|
||||
*/
|
||||
public final class Track extends GeoPath {
|
||||
private static final Logger LOGGER = Logger.getLogger(Track.class.getName());
|
||||
|
||||
private final Long startTimestamp;
|
||||
private final Long endTimeStamp;
|
||||
@ -134,14 +131,12 @@ public final class Track extends GeoPath {
|
||||
private GeoTrackPoints getPointsList(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
|
||||
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS);
|
||||
if (attribute == null) {
|
||||
LOGGER.log(Level.SEVERE, "No TSK_GEO_TRACKPOINTS attribute was present on the artifact.");
|
||||
throw new GeoLocationDataException("No TSK_GEO_TRACKPOINTS attribute present in attribute map to parse.");
|
||||
}
|
||||
|
||||
try {
|
||||
return BlackboardJsonAttrUtil.fromAttribute(attribute, GeoTrackPoints.class);
|
||||
} catch (InvalidJsonException ex) {
|
||||
LOGGER.log(Level.SEVERE, "TSK_GEO_TRACKPOINTS could not be properly parsed from TSK_GEO_TRACKPOINTS attribute.");
|
||||
throw new GeoLocationDataException("Unable to parse track points in TSK_GEO_TRACKPOINTS attribute", ex);
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +178,28 @@ public final class WaypointBuilder {
|
||||
|
||||
return trackList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of areas from the given list of waypoints.
|
||||
*
|
||||
* @param waypoints A list of waypoints
|
||||
*
|
||||
* @return A list of areas or an empty list if none were found.
|
||||
*/
|
||||
public static List<Area> getAreas(List<Waypoint> waypoints) {
|
||||
List<Area> areaList = new ArrayList<>();
|
||||
for (Waypoint point : waypoints) {
|
||||
GeoPath path = point.getParentGeoPath();
|
||||
if (path instanceof Area) {
|
||||
Area area = (Area) path;
|
||||
if (!areaList.contains(area)) {
|
||||
areaList.add(area);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return areaList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of Waypoints for TSK_GPS_TRACKPOINT artifacts.
|
||||
|
BIN
Core/src/org/sleuthkit/autopsy/images/gps-area.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/images/gps-area.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 984 B |
@ -1793,6 +1793,7 @@ class TableReportGenerator {
|
||||
|| artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID()
|
||||
|| artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID()
|
||||
|| artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID()
|
||||
|| artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_AREA.getTypeID()
|
||||
|| artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID()
|
||||
|| artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()
|
||||
|| artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED.getTypeID()
|
||||
|
@ -384,6 +384,9 @@ public class HTMLReport implements TableReportModule {
|
||||
case TSK_WEB_FORM_ADDRESS:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/web-form-address.png"); //NON-NLS
|
||||
break;
|
||||
case TSK_GPS_AREA:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/gps-area.png"); //NON-NLS
|
||||
break;
|
||||
default:
|
||||
logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = {0}", dataType); //NON-NLS
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS
|
||||
|
@ -27,6 +27,7 @@ ReportKML.genReport.reportName=KML Report
|
||||
ReportKML.latLongStartPoint={0};{1};;{2} (Start)\n
|
||||
ReportKML.latLongEndPoint={0};{1};;{2} (End)\n
|
||||
Route_Details_Header=GPS Route
|
||||
Waypoint_Area_Point_Display_String=GPS Area Outline Point
|
||||
Waypoint_Bookmark_Display_String=GPS Bookmark
|
||||
Waypoint_EXIF_Display_String=EXIF Metadata With Location
|
||||
Waypoint_Last_Known_Display_String=GPS Last Known Location
|
||||
|
@ -50,6 +50,7 @@ import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationParseResult;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.Waypoint;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.Route;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.Track;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.Area;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder;
|
||||
import org.sleuthkit.autopsy.report.GeneralReportSettings;
|
||||
import org.sleuthkit.autopsy.report.ReportBranding;
|
||||
@ -84,6 +85,7 @@ public final class KMLReport implements GeneralReportModule {
|
||||
private Element gpsSearchesFolder;
|
||||
private Element gpsTrackpointsFolder;
|
||||
private Element gpsTracksFolder;
|
||||
private Element gpsAreasFolder;
|
||||
|
||||
private GeneralReportSettings settings;
|
||||
|
||||
@ -154,7 +156,8 @@ public final class KMLReport implements GeneralReportModule {
|
||||
"Waypoint_Track_Display_String=GPS Track",
|
||||
"Route_Details_Header=GPS Route",
|
||||
"ReportBodyFile.ingestWarning.text=Ingest Warning message",
|
||||
"Waypoint_Track_Point_Display_String=GPS Individual Track Point"
|
||||
"Waypoint_Track_Point_Display_String=GPS Individual Track Point",
|
||||
"Waypoint_Area_Point_Display_String=GPS Area Outline Point",
|
||||
})
|
||||
|
||||
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel, List<Waypoint> waypointList) {
|
||||
@ -216,6 +219,11 @@ public final class KMLReport implements GeneralReportModule {
|
||||
result = ReportProgressPanel.ReportStatus.ERROR;
|
||||
errorMessage = Bundle.KMLReport_partialFailure();
|
||||
}
|
||||
entirelySuccessful = makeAreas(skCase);
|
||||
if (!entirelySuccessful) {
|
||||
result = ReportProgressPanel.ReportStatus.ERROR;
|
||||
errorMessage = Bundle.KMLReport_partialFailure();
|
||||
}
|
||||
|
||||
addLocationsToReport(skCase, baseReportDir);
|
||||
} catch (GeoLocationDataException | IOException | TskCoreException ex) {
|
||||
@ -326,6 +334,11 @@ public final class KMLReport implements GeneralReportModule {
|
||||
CDATA cdataTrack = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-trackpoint.png"); //NON-NLS
|
||||
Element hrefTrack = new Element("href", ns).addContent(cdataTrack); //NON-NLS
|
||||
gpsTracksFolder.addContent(new Element("Icon", ns).addContent(hrefTrack)); //NON-NLS
|
||||
|
||||
gpsAreasFolder = new Element("Folder", ns); //NON-NLS
|
||||
CDATA cdataArea = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-area.png"); //NON-NLS
|
||||
Element hrefArea = new Element("href", ns).addContent(cdataArea); //NON-NLS
|
||||
gpsAreasFolder.addContent(new Element("Icon", ns).addContent(hrefArea)); //NON-NLS
|
||||
|
||||
gpsExifMetadataFolder.addContent(new Element("name", ns).addContent("EXIF Metadata")); //NON-NLS
|
||||
gpsBookmarksFolder.addContent(new Element("name", ns).addContent("GPS Bookmarks")); //NON-NLS
|
||||
@ -334,6 +347,7 @@ public final class KMLReport implements GeneralReportModule {
|
||||
gpsSearchesFolder.addContent(new Element("name", ns).addContent("GPS Searches")); //NON-NLS
|
||||
gpsTrackpointsFolder.addContent(new Element("name", ns).addContent("GPS Trackpoints")); //NON-NLS
|
||||
gpsTracksFolder.addContent(new Element("name", ns).addContent("GPS Tracks")); //NON-NLS
|
||||
gpsAreasFolder.addContent(new Element("name", ns).addContent("GPS Areas")); //NON-NLS
|
||||
|
||||
document.addContent(gpsExifMetadataFolder);
|
||||
document.addContent(gpsBookmarksFolder);
|
||||
@ -342,6 +356,7 @@ public final class KMLReport implements GeneralReportModule {
|
||||
document.addContent(gpsSearchesFolder);
|
||||
document.addContent(gpsTrackpointsFolder);
|
||||
document.addContent(gpsTracksFolder);
|
||||
document.addContent(gpsAreasFolder);
|
||||
|
||||
return kmlDocument;
|
||||
}
|
||||
@ -570,6 +585,62 @@ public final class KMLReport implements GeneralReportModule {
|
||||
point.getTimestamp(), element, formattedCoordinates(point.getLatitude(), point.getLongitude()))); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the area to the area folder in the document.
|
||||
*
|
||||
* @param skCase Currently open case.
|
||||
* @return The operation was entirely successful.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
boolean makeAreas(SleuthkitCase skCase) throws GeoLocationDataException, TskCoreException {
|
||||
List<Area> areas;
|
||||
boolean successful = true;
|
||||
|
||||
if (waypointList == null) {
|
||||
GeoLocationParseResult<Area> result = Area.getAreas(skCase, null);
|
||||
areas = result.getItems();
|
||||
successful = result.isSuccessfullyParsed();
|
||||
} else {
|
||||
areas = WaypointBuilder.getAreas(waypointList);
|
||||
}
|
||||
|
||||
for (Area area : areas) {
|
||||
if(shouldFilterFromReport(area.getArtifact())) {
|
||||
continue;
|
||||
}
|
||||
addAreaToReport(area);
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a area to the KML report.
|
||||
*
|
||||
* @param area
|
||||
*/
|
||||
private void addAreaToReport(Area area) {
|
||||
List<Waypoint> areaPoints = area.getPath();
|
||||
|
||||
if (areaPoints.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Adding a folder with the area name so that all of the
|
||||
// area border points will be grouped together.
|
||||
Element areaFolder = new Element("Folder", ns); //NON-NLS
|
||||
areaFolder.addContent(new Element("name", ns).addContent(area.getLabel())); //NON-NLS
|
||||
gpsAreasFolder.addContent(areaFolder);
|
||||
|
||||
// Create a polygon using the waypoints
|
||||
Element element = makePolygon(areaPoints);
|
||||
Waypoint firstWp = areaPoints.get(0);
|
||||
areaFolder.addContent(makePlacemark("",
|
||||
FeatureColor.GREEN, getFormattedDetails(firstWp, Bundle.Waypoint_Area_Point_Display_String()),
|
||||
firstWp.getTimestamp(), element, formattedCoordinates(firstWp.getLatitude(), firstWp.getLongitude()))); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a point time stamp (in seconds) to the report format.
|
||||
@ -628,7 +699,7 @@ public final class KMLReport implements GeneralReportModule {
|
||||
point.addContent(coordinates);
|
||||
|
||||
return point;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LineString for use in a Placemark. Note in this method, start
|
||||
@ -662,6 +733,35 @@ public final class KMLReport implements GeneralReportModule {
|
||||
return lineString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Polygon for use in a Placemark.
|
||||
*
|
||||
* @param waypoints The waypoints making up the outline.
|
||||
*
|
||||
* @return the Polygon as an Element
|
||||
*/
|
||||
private Element makePolygon(List<Waypoint> waypoints) {
|
||||
|
||||
Element polygon = new Element("Polygon", ns); //NON-NLS
|
||||
|
||||
Element altitudeMode = new Element("altitudeMode", ns).addContent("clampToGround"); //NON-NLS
|
||||
polygon.addContent(altitudeMode);
|
||||
|
||||
// KML uses lon, lat. Deliberately reversed.
|
||||
Element coordinates = new Element("coordinates", ns);
|
||||
for (Waypoint wp : waypoints) {
|
||||
coordinates.addContent(wp.getLongitude() + "," + wp.getLatitude() + ",0 "); //NON-NLS
|
||||
}
|
||||
// Add the first one again
|
||||
coordinates.addContent(waypoints.get(0).getLongitude() + "," + waypoints.get(0).getLatitude() + ",0 "); //NON-NLS
|
||||
|
||||
Element linearRing = new Element("LinearRing", ns).addContent(coordinates);
|
||||
Element outerBoundary = new Element("outerBoundaryIs", ns).addContent(linearRing);
|
||||
polygon.addContent(outerBoundary);
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a Placemark for use in displaying features. Takes a
|
||||
* coordinate-bearing feature (Point, LineString, etc) and places it in the
|
||||
|
Loading…
x
Reference in New Issue
Block a user