19 package org.sleuthkit.autopsy.geolocation;
21 import java.awt.Color;
22 import java.awt.event.ActionEvent;
23 import java.awt.image.BufferedImage;
24 import java.text.SimpleDateFormat;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.LinkedHashSet;
29 import java.util.List;
30 import java.util.Locale;
33 import java.util.logging.Level;
34 import javax.swing.AbstractAction;
35 import javax.swing.Action;
36 import javax.swing.ImageIcon;
37 import javax.swing.JMenuItem;
38 import org.jxmapviewer.viewer.GeoPosition;
39 import org.openide.util.NbBundle.Messages;
65 @SuppressWarnings(
"deprecation")
66 final class MapWaypoint extends KdTree.XYZPoint implements
org.jxmapviewer.viewer.Waypoint {
68 private static final Logger logger = Logger.getLogger(MapWaypoint.class.getName());
69 private final static String HTML_PROP_FORMAT =
"<b>%s: </b>%s<br>";
70 static private final SimpleDateFormat DATE_FORMAT =
new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssX", Locale.US);
72 private static final Map<Integer, Color> artifactTypesToColors =
new HashMap<>();
75 artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID(), Color.BLUE);
76 artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID(), Color.RED);
77 artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID(), Color.CYAN);
78 artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID(), Color.GREEN);
79 artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID(), Color.ORANGE);
80 artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID(), Color.ORANGE);
81 artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID(), Color.MAGENTA);
84 private final Waypoint dataModelWaypoint;
85 private final GeoPosition position;
96 static Set<MapWaypoint> getWaypoints(List<Waypoint> dmWaypoints) {
97 Set<MapWaypoint> mapPoints =
new LinkedHashSet<>();
99 if (dmWaypoints != null) {
101 for (Waypoint point : dmWaypoints) {
102 mapPoints.add(
new MapWaypoint(point));
118 static List<Waypoint> getDataModelWaypoints(List<MapWaypoint> mapWaypoints) {
119 List<Waypoint> waypoints =
new ArrayList<>();
121 if (mapWaypoints != null) {
122 for (MapWaypoint point : mapWaypoints) {
123 waypoints.add(point.dataModelWaypoint);
137 static MapWaypoint getDummyWaypoint(GeoPosition position) {
138 return new MapWaypoint(position);
146 private MapWaypoint(Waypoint dataModelWaypoint) {
147 super(dataModelWaypoint.getLatitude(), dataModelWaypoint.getLongitude());
148 this.dataModelWaypoint = dataModelWaypoint;
149 position =
new GeoPosition(dataModelWaypoint.getLatitude(), dataModelWaypoint.getLongitude());
157 private MapWaypoint(GeoPosition position) {
158 super(position.getLatitude(), position.getLongitude());
159 dataModelWaypoint = null;
160 this.position = position;
168 ImageIcon getImage() {
169 if (dataModelWaypoint.getImage() != null && ImageUtils.isImageThumbnailSupported(dataModelWaypoint.getImage())) {
170 BufferedImage buffImage = ImageUtils.getThumbnail(dataModelWaypoint.getImage(), 150);
171 return new ImageIcon(buffImage);
181 public GeoPosition getPosition() {
191 return dataModelWaypoint.getLabel();
199 String getHTMLFormattedWaypointDetails() {
200 return getFormattedDetails(dataModelWaypoint);
206 int getArtifactTypeID() {
207 return dataModelWaypoint.getArtifact().getArtifactTypeID();
218 JMenuItem[] getMenuItems() throws TskCoreException {
219 List<JMenuItem> menuItems =
new ArrayList<>();
220 BlackboardArtifact artifact = dataModelWaypoint.getArtifact();
221 Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
223 menuItems.addAll(getTimelineMenuItems(dataModelWaypoint.getArtifact()));
224 menuItems.addAll(getDataModelActionFactoryMenuItems(artifact, content));
225 menuItems.add(DeleteFileContentTagAction.getInstance().getMenuForFiles(Arrays.asList((AbstractFile) content)));
226 menuItems.add(DeleteFileBlackboardArtifactTagAction.getInstance().getMenuForArtifacts(Arrays.asList(artifact)));
228 return menuItems.toArray(
new JMenuItem[0]);
238 private List<JMenuItem> getTimelineMenuItems(BlackboardArtifact artifact) {
239 List<JMenuItem> menuItems =
new ArrayList<>();
242 if (ViewArtifactInTimelineAction.hasSupportedTimeStamp(artifact)) {
243 menuItems.add(
new JMenuItem(
new ViewArtifactInTimelineAction(artifact)));
245 }
catch (TskCoreException ex) {
246 logger.log(Level.SEVERE, String.format(
"Error getting arttribute(s) from blackboard artifact %d.", artifact.getArtifactID()), ex);
263 "MayWaypoint_ExternalViewer_label=Open in ExternalViewer"
265 private List<JMenuItem> getDataModelActionFactoryMenuItems(BlackboardArtifact artifact, Content content) {
266 List<JMenuItem> menuItems =
new ArrayList<>();
268 List<Action> actions = DataModelActionsFactory.getActions(content,
true);
269 for (Action action : actions) {
270 if (action == null) {
272 }
else if (action instanceof ExportCSVAction) {
274 }
else if (action instanceof AddContentTagAction) {
275 menuItems.add(((AddContentTagAction) action).getMenuForContent(Arrays.asList((AbstractFile) content)));
276 }
else if (action instanceof AddBlackboardArtifactTagAction) {
277 menuItems.add(((AddBlackboardArtifactTagAction) action).getMenuForContent(Arrays.asList(artifact)));
278 }
else if (action instanceof ExternalViewerShortcutAction) {
280 ExternalViewerAction newAction =
new ExternalViewerAction(Bundle.MayWaypoint_ExternalViewer_label(),
new FileNode((AbstractFile) content));
281 menuItems.add(
new JMenuItem(newAction));
282 }
else if (action instanceof ExtractAction) {
283 menuItems.add(
new JMenuItem(
new WaypointExtractAction((AbstractFile) content)));
285 menuItems.add(
new JMenuItem(action));
299 private String getFormattedDetails(Waypoint point) {
300 StringBuilder result =
new StringBuilder();
302 result.append(
"<html>").append(formatAttribute(
"Name", point.getLabel()));
304 Long timestamp = point.getTimestamp();
305 if (timestamp != null) {
306 result.append(formatAttribute(
"Timestamp", getTimeStamp(timestamp)));
309 result.append(formatAttribute(
"Latitude", point.getLatitude().toString()))
310 .append(formatAttribute(
"Longitude", point.getLongitude().toString()));
312 if (point.getAltitude() != null) {
313 result.append(formatAttribute(
"Altitude", point.getAltitude().toString()));
316 List<Waypoint.Property> list = point.getOtherProperties();
317 for (Waypoint.Property prop : list) {
318 String value = prop.getValue();
319 if (value != null && !value.isEmpty()) {
320 result.append(formatAttribute(prop.getDisplayName(), value));
324 result.append(
"</html>");
326 return result.toString();
337 private String formatAttribute(String title, String value) {
338 return String.format(HTML_PROP_FORMAT, title, value);
348 private String getTimeStamp(
long timeStamp) {
349 return DATE_FORMAT.format(
new java.util.Date(timeStamp * 1000));
356 static Color getColor(
int artifactTypeId) {
357 return artifactTypesToColors.getOrDefault(artifactTypeId, Color.GRAY);
365 return getColor(dataModelWaypoint.getArtifact().getArtifactTypeID());
372 "WaypointExtractAction_label=Extract Files(s)"
374 final class WaypointExtractAction extends AbstractAction {
376 private static final long serialVersionUID = 1L;
377 final private AbstractFile file;
379 WaypointExtractAction(AbstractFile file) {
380 super(Bundle.WaypointExtractAction_label());
385 public void actionPerformed(ActionEvent e) {
386 ExtractActionHelper helper =
new ExtractActionHelper();
387 helper.extract(e, Arrays.asList(file));