diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties
index 84d4ab700c..8330a6ea62 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties
@@ -4,7 +4,6 @@ CTL_GeolocationTopComponent=Geolocation
RefreshPanel.refreshLabel.text=The geolocation data has been updated, the visualization may be out of date.
RefreshPanel.refreshButton.text=Refresh View
RefreshPanel.closeButton.text=
-MapPanel.cordLabel.text=
WaypointDetailPanel.closeButton.text=
WaypointDetailPanel.imageLabel.text=
GeoFilterPanel.waypointSettings.border.title=
@@ -30,3 +29,5 @@ GeolocationSettingsPanel.osmZipFileField.text=
GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse
GeolocationSettingsPanel.serverTestButton.text=Test
GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file
+GeolocationTopComponent.reportButton.text=KML Report
+GeolocationTopComponent.coordLabel.text=jLabel1
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED
index c69264acae..8ba4bfd036 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED
@@ -11,6 +11,9 @@ GeolocationSettingsPanel_osm_server_test_success_message=The provide OSM tile se
GeolocationSettingsPanel_osm_server_test_success_message_title=Success
GeolocationTC_connection_failure_message=Failed to connect to map title source.\nPlease review map source in Options dialog.
GeolocationTC_connection_failure_message_title=Connection Failure
+GeolocationTC_empty_waypoint_message=Unable to generate KML report due to a lack of waypoints.\nPlease make sure there are waypoints visible before generating the KML report
+GeolocationTC_KML_report_title=KML Report
+GeolocationTC_report_progress_title=KML Report Progress
GeoTopComponent_filer_data_invalid_msg=Unable to run waypoint filter.\nPlease select one or more data sources.
GeoTopComponent_filer_data_invalid_Title=Filter Failure
GeoTopComponent_filter_exception_msg=Exception occured during waypoint filtering.
@@ -28,7 +31,6 @@ OpenGeolocationAction_name=Geolocation
RefreshPanel.refreshLabel.text=The geolocation data has been updated, the visualization may be out of date.
RefreshPanel.refreshButton.text=Refresh View
RefreshPanel.closeButton.text=
-MapPanel.cordLabel.text=
WaypointDetailPanel.closeButton.text=
WaypointDetailPanel.imageLabel.text=
GeoFilterPanel.waypointSettings.border.title=
@@ -54,4 +56,6 @@ GeolocationSettingsPanel.osmZipFileField.text=
GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse
GeolocationSettingsPanel.serverTestButton.text=Test
GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file
+GeolocationTopComponent.reportButton.text=KML Report
+GeolocationTopComponent.coordLabel.text=jLabel1
WaypointExtractAction_label=Extract Files(s)
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.form b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.form
index 16cd5368a6..c51c8d496e 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.form
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.form
@@ -16,6 +16,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -24,17 +81,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java
index 969eab6b91..7658f80571 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java
@@ -21,14 +21,22 @@ package org.sleuthkit.autopsy.geolocation;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.EnumSet;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
+import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.RetainLocation;
import org.openide.windows.TopComponent;
@@ -46,6 +54,8 @@ import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder.WaypointFilte
import org.sleuthkit.autopsy.ingest.IngestManager;
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
+import org.sleuthkit.autopsy.report.ReportProgressPanel;
+import org.sleuthkit.autopsy.report.modules.kml.KMLReport;
import org.sleuthkit.datamodel.BlackboardArtifact;
/**
@@ -70,6 +80,11 @@ public final class GeolocationTopComponent extends TopComponent {
final RefreshPanel refreshPanel = new RefreshPanel();
+ private static final String REPORT_PATH_FMT_STR = "%s" + File.separator + "%s %s %s" + File.separator;
+
+ // This is the hardcoded report name from KMLReport.java
+ private static final String REPORT_KML = "ReportKML.kml";
+
@Messages({
"GLTopComponent_name=Geolocation",
"GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete."
@@ -81,7 +96,7 @@ public final class GeolocationTopComponent extends TopComponent {
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
public GeolocationTopComponent() {
initComponents();
-
+
setName(Bundle.GLTopComponent_name());
this.ingestListener = pce -> {
@@ -134,6 +149,20 @@ public final class GeolocationTopComponent extends TopComponent {
updateWaypoints();
}
});
+
+ mapPanel.addPropertyChangeListener(MapPanel.CURRENT_MOUSE_GEOPOSITION, new PropertyChangeListener() {
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ String label = "";
+ Object newValue = evt.getNewValue();
+ if (newValue != null) {
+ label = newValue.toString();
+ }
+
+ coordLabel.setText(label);
+ }
+
+ });
}
@Override
@@ -156,7 +185,7 @@ public final class GeolocationTopComponent extends TopComponent {
WindowManager.getDefault().setTopComponentFloating(this, true);
}
-
+
@Messages({
"GeolocationTC_connection_failure_message=Failed to connect to map title source.\nPlease review map source in Options dialog.",
"GeolocationTC_connection_failure_message_title=Connection Failure"
@@ -169,15 +198,15 @@ public final class GeolocationTopComponent extends TopComponent {
try {
mapPanel.initMap();
} catch (GeoLocationDataException ex) {
- JOptionPane.showMessageDialog(this,
- Bundle.GeolocationTC_connection_failure_message(),
- Bundle.GeolocationTC_connection_failure_message_title(),
- JOptionPane.ERROR_MESSAGE);
- MessageNotifyUtil.Notify.error(
- Bundle.GeolocationTC_connection_failure_message_title(),
- Bundle.GeolocationTC_connection_failure_message());
- logger.log(Level.SEVERE, ex.getMessage(), ex);
- return; // Doen't set the waypoints.
+ JOptionPane.showMessageDialog(this,
+ Bundle.GeolocationTC_connection_failure_message(),
+ Bundle.GeolocationTC_connection_failure_message_title(),
+ JOptionPane.ERROR_MESSAGE);
+ MessageNotifyUtil.Notify.error(
+ Bundle.GeolocationTC_connection_failure_message_title(),
+ Bundle.GeolocationTC_connection_failure_message());
+ logger.log(Level.SEVERE, ex.getMessage(), ex);
+ return; // Doen't set the waypoints.
}
mapPanel.setWaypoints(new ArrayList<>());
updateWaypoints();
@@ -216,20 +245,58 @@ public final class GeolocationTopComponent extends TopComponent {
try {
filters = geoFilterPanel.getFilterState();
} catch (GeoLocationUIException ex) {
- JOptionPane.showMessageDialog(this,
- Bundle.GeoTopComponent_filer_data_invalid_msg(),
- Bundle.GeoTopComponent_filer_data_invalid_Title(),
- JOptionPane.INFORMATION_MESSAGE);
+ JOptionPane.showMessageDialog(this,
+ Bundle.GeoTopComponent_filer_data_invalid_msg(),
+ Bundle.GeoTopComponent_filer_data_invalid_Title(),
+ JOptionPane.INFORMATION_MESSAGE);
return;
}
-
- mapPanel.setWaypointLoading(true);
+
+ setWaypointLoading(true);
geoFilterPanel.setEnabled(false);
-
+
Thread thread = new Thread(new WaypointRunner(filters));
thread.start();
}
+ /**
+ * Show or hide the waypoint loading progress bar.
+ *
+ * @param loading
+ */
+ void setWaypointLoading(boolean loading) {
+ progressBar.setEnabled(true);
+ progressBar.setVisible(loading);
+ progressBar.setString("Loading Waypoints");
+ }
+
+ /**
+ * Create the directory path for the KML report.
+ *
+ * This is a modified version of the similar private function from
+ * KMLReport.
+ *
+ * @return Path for the report
+ *
+ * @throws IOException
+ */
+ private static String createReportDirectory() throws IOException {
+ Case currentCase = Case.getCurrentCase();
+
+ // Create the root reports directory path of the form: /Reports/ /
+ DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss", Locale.US);
+ Date date = new Date();
+ String dateNoTime = dateFormat.format(date);
+ String reportPath = String.format(REPORT_PATH_FMT_STR, currentCase.getReportDirectory(), currentCase.getDisplayName(), "Goggle Earth KML", dateNoTime);
+ // Create the root reports directory.
+ try {
+ FileUtil.createFolder(new File(reportPath));
+ } catch (IOException ex) {
+ throw new IOException("Failed to make report folder, unable to generate reports.", ex);
+ }
+ return reportPath;
+ }
+
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@@ -238,23 +305,88 @@ public final class GeolocationTopComponent extends TopComponent {
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
+ java.awt.GridBagConstraints gridBagConstraints;
- mapPanel = new org.sleuthkit.autopsy.geolocation.MapPanel();
filterPane = new org.sleuthkit.autopsy.geolocation.HidingPane();
+ statusBar = new javax.swing.JPanel();
+ reportButton = new javax.swing.JButton();
+ progressBar = new javax.swing.JProgressBar();
+ coordLabel = new javax.swing.JLabel();
+ mapPanel = new org.sleuthkit.autopsy.geolocation.MapPanel();
setLayout(new java.awt.BorderLayout());
+ add(filterPane, java.awt.BorderLayout.WEST);
- mapPanel.add(filterPane, java.awt.BorderLayout.LINE_START);
+ statusBar.setLayout(new java.awt.GridBagLayout());
+ org.openide.awt.Mnemonics.setLocalizedText(reportButton, org.openide.util.NbBundle.getMessage(GeolocationTopComponent.class, "GeolocationTopComponent.reportButton.text")); // NOI18N
+ reportButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ reportButtonActionPerformed(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 2;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
+ statusBar.add(reportButton, gridBagConstraints);
+
+ progressBar.setIndeterminate(true);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ statusBar.add(progressBar, gridBagConstraints);
+
+ org.openide.awt.Mnemonics.setLocalizedText(coordLabel, org.openide.util.NbBundle.getMessage(GeolocationTopComponent.class, "GeolocationTopComponent.coordLabel.text")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0);
+ statusBar.add(coordLabel, gridBagConstraints);
+
+ add(statusBar, java.awt.BorderLayout.SOUTH);
add(mapPanel, java.awt.BorderLayout.CENTER);
}// //GEN-END:initComponents
+ @Messages({
+ "GeolocationTC_empty_waypoint_message=Unable to generate KML report due to a lack of waypoints.\nPlease make sure there are waypoints visible before generating the KML report",
+ "GeolocationTC_KML_report_title=KML Report",
+ "GeolocationTC_report_progress_title=KML Report Progress"
+ })
+ private void reportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reportButtonActionPerformed
+ List visiblePoints = mapPanel.getVisibleWaypoints();
+ if (visiblePoints.isEmpty()) {
+ JOptionPane.showConfirmDialog(this, Bundle.GeolocationTC_empty_waypoint_message(), Bundle.GeolocationTC_KML_report_title(), JOptionPane.OK_OPTION, JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+
+ try {
+ ReportProgressPanel progressPanel = new ReportProgressPanel();
+ String reportBaseDir = createReportDirectory();
+
+ progressPanel.setLabels(REPORT_KML, reportBaseDir);
+
+ KMLReport.getDefault().generateReport(reportBaseDir, progressPanel, MapWaypoint.getDataModelWaypoints(visiblePoints));
+ JOptionPane.showConfirmDialog(this, progressPanel, Bundle.GeolocationTC_report_progress_title(), JOptionPane.CLOSED_OPTION, JOptionPane.PLAIN_MESSAGE);
+ } catch (IOException ex) {
+ logger.log(Level.WARNING, "Unable to create KML report", ex);
+ }
+ }//GEN-LAST:event_reportButtonActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel coordLabel;
private org.sleuthkit.autopsy.geolocation.HidingPane filterPane;
private org.sleuthkit.autopsy.geolocation.MapPanel mapPanel;
+ private javax.swing.JProgressBar progressBar;
+ private javax.swing.JButton reportButton;
+ private javax.swing.JPanel statusBar;
// End of variables declaration//GEN-END:variables
-
+
/**
* A runnable class for getting waypoints based on the current filters.
*/
@@ -264,8 +396,8 @@ public final class GeolocationTopComponent extends TopComponent {
/**
* Constructs the Waypoint Runner
- *
- * @param filters
+ *
+ * @param filters
*/
WaypointRunner(GeoFilter filters) {
this.filters = filters;
@@ -281,16 +413,16 @@ public final class GeolocationTopComponent extends TopComponent {
filters.getMostRecentNumDays(),
filters.showWaypointsWithoutTimeStamp(),
new WaypointCallBack());
-
+
} catch (GeoLocationDataException ex) {
logger.log(Level.SEVERE, "Failed to filter waypoints.", ex);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- JOptionPane.showMessageDialog(GeolocationTopComponent.this,
- Bundle.GeoTopComponent_filter_exception_Title(),
- Bundle.GeoTopComponent_filter_exception_msg(),
- JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(GeolocationTopComponent.this,
+ Bundle.GeoTopComponent_filter_exception_Title(),
+ Bundle.GeoTopComponent_filter_exception_msg(),
+ JOptionPane.ERROR_MESSAGE);
}
});
}
@@ -321,6 +453,7 @@ public final class GeolocationTopComponent extends TopComponent {
return;
}
mapPanel.setWaypoints(MapWaypoint.getWaypoints(waypoints));
+ setWaypointLoading(false);
geoFilterPanel.setEnabled(true);
}
});
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.form b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.form
index 5158982822..bea654be40 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.form
@@ -91,39 +91,5 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java
index 918f2de88d..3007a8021a 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java
@@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.geolocation;
import java.awt.Dimension;
+import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
@@ -27,9 +28,12 @@ import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
@@ -46,6 +50,7 @@ import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.Timer;
import javax.swing.event.MouseInputListener;
+import org.jxmapviewer.JXMapViewer;
import org.jxmapviewer.OSMTileFactoryInfo;
import org.jxmapviewer.VirtualEarthTileFactoryInfo;
import org.jxmapviewer.input.CenterMapListener;
@@ -57,6 +62,7 @@ import org.jxmapviewer.viewer.TileFactory;
import org.jxmapviewer.viewer.TileFactoryInfo;
import org.jxmapviewer.viewer.Waypoint;
import org.jxmapviewer.viewer.WaypointPainter;
+import org.jxmapviewer.viewer.WaypointRenderer;
import org.jxmapviewer.viewer.util.GeoUtil;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.core.UserPreferences;
@@ -64,12 +70,15 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
import org.sleuthkit.datamodel.TskCoreException;
+import javax.imageio.ImageIO;
+import org.jxmapviewer.viewer.DefaultWaypointRenderer;
/**
* The map panel. This panel contains the jxmapviewer MapViewer
*/
final public class MapPanel extends javax.swing.JPanel {
+ static final String CURRENT_MOUSE_GEOPOSITION = "CURRENT_MOUSE_GEOPOSITION";
private static final Logger logger = Logger.getLogger(MapPanel.class.getName());
private static final long serialVersionUID = 1L;
@@ -123,13 +132,34 @@ final public class MapPanel extends javax.swing.JPanel {
Bundle.MapPanel_connection_failure_message_title(),
JOptionPane.ERROR_MESSAGE);
MessageNotifyUtil.Notify.error(
- Bundle.MapPanel_connection_failure_message_title(),
- Bundle.MapPanel_connection_failure_message());
+ Bundle.MapPanel_connection_failure_message_title(),
+ Bundle.MapPanel_connection_failure_message());
}
}
});
}
+ /**
+ * Get a list of the waypoints that are currently visible in the viewport.
+ *
+ * @return A list of waypoints or empty list if none were found.
+ */
+ List getVisibleWaypoints() {
+
+ Rectangle viewport = mapViewer.getViewportBounds();
+ List waypoints = new ArrayList<>();
+
+ Iterator iterator = waypointTree.iterator();
+ while (iterator.hasNext()) {
+ MapWaypoint waypoint = iterator.next();
+ if (viewport.contains(mapViewer.getTileFactory().geoToPixel(waypoint.getPosition(), mapViewer.getZoom()))) {
+ waypoints.add(waypoint);
+ }
+ }
+
+ return waypoints;
+ }
+
/**
* Initialize the map.
*/
@@ -159,8 +189,8 @@ final public class MapPanel extends javax.swing.JPanel {
zoomSlider.setMaximum(tileFactory.getInfo().getMaximumZoomLevel());
setZoom(tileFactory.getInfo().getMaximumZoomLevel() - 1);
-
- mapViewer.setCenterPosition(new GeoPosition(0,0));
+
+ mapViewer.setCenterPosition(new GeoPosition(0, 0));
// Basic painters for the way points.
WaypointPainter waypointPainter = new WaypointPainter() {
@@ -176,20 +206,16 @@ final public class MapPanel extends javax.swing.JPanel {
return set;
}
};
+
+ try {
+ waypointPainter.setRenderer(new MapWaypointRenderer());
+ } catch (IOException ex) {
+ logger.log(Level.WARNING, "Failed to load waypoint image resource, using DefaultWaypointRenderer", ex);
+ waypointPainter.setRenderer(new DefaultWaypointRenderer());
+ }
mapViewer.setOverlayPainter(waypointPainter);
}
-
- /**
- * Show or hide the waypoint loading progress bar.
- *
- * @param loading
- */
- void setWaypointLoading(boolean loading) {
- progressBar.setEnabled(true);
- progressBar.setVisible(loading);
- progressBar.setString("Loading Waypoints");
- }
/**
* Setup the zoom slider based on the current tileFactory.
@@ -218,15 +244,15 @@ final public class MapPanel extends javax.swing.JPanel {
return new VirtualEarthTileFactoryInfo(VirtualEarthTileFactoryInfo.MAP);
}
}
-
+
/**
* Create the TileFactoryInfo for an online OSM tile server.
- *
- * @param address Tile server address
- *
+ *
+ * @param address Tile server address
+ *
* @return TileFactoryInfo object for server address.
- *
- * @throws GeoLocationDataException
+ *
+ * @throws GeoLocationDataException
*/
private TileFactoryInfo createOnlineOSMFactory(String address) throws GeoLocationDataException {
if (address.isEmpty()) {
@@ -239,15 +265,15 @@ final public class MapPanel extends javax.swing.JPanel {
return info;
}
}
-
+
/**
* Create the TileFactoryInfo for OSM zip File
- *
+ *
* @param zipPath Path to zip file.
- *
+ *
* @return TileFactoryInfo for zip file.
- *
- * @throws GeoLocationDataException
+ *
+ * @throws GeoLocationDataException
*/
private TileFactoryInfo createOSMZipFactory(String path) throws GeoLocationDataException {
if (path.isEmpty()) {
@@ -277,7 +303,6 @@ final public class MapPanel extends javax.swing.JPanel {
}
mapViewer.repaint();
- setWaypointLoading(false);
}
/**
@@ -316,6 +341,7 @@ final public class MapPanel extends javax.swing.JPanel {
if(currentPopup != null) {
showDetailsPopup();
}
+ mapViewer.repaint();
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Failed to show popup for waypoint", ex);
@@ -373,6 +399,8 @@ final public class MapPanel extends javax.swing.JPanel {
currentPopup = popupFactory.getPopup(this, detailPane, popupLocation.x, popupLocation.y);
currentPopup.show();
+
+ mapViewer.repaint();
}
}
@@ -499,9 +527,6 @@ final public class MapPanel extends javax.swing.JPanel {
mapViewer = new org.jxmapviewer.JXMapViewer();
zoomPanel = new javax.swing.JPanel();
zoomSlider = new javax.swing.JSlider();
- infoPanel = new javax.swing.JPanel();
- cordLabel = new javax.swing.JLabel();
- progressBar = new javax.swing.JProgressBar();
setFocusable(false);
setLayout(new java.awt.BorderLayout());
@@ -568,27 +593,6 @@ final public class MapPanel extends javax.swing.JPanel {
mapViewer.add(zoomPanel, gridBagConstraints);
add(mapViewer, java.awt.BorderLayout.CENTER);
-
- infoPanel.setLayout(new java.awt.GridBagLayout());
-
- org.openide.awt.Mnemonics.setLocalizedText(cordLabel, org.openide.util.NbBundle.getMessage(MapPanel.class, "MapPanel.cordLabel.text")); // NOI18N
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 0;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
- infoPanel.add(cordLabel, gridBagConstraints);
-
- progressBar.setIndeterminate(true);
- progressBar.setStringPainted(true);
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 0;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
- infoPanel.add(progressBar, gridBagConstraints);
-
- add(infoPanel, java.awt.BorderLayout.SOUTH);
}// //GEN-END:initComponents
private void zoomSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_zoomSliderStateChanged
@@ -611,7 +615,7 @@ final public class MapPanel extends javax.swing.JPanel {
private void mapViewerMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseMoved
GeoPosition geopos = mapViewer.getTileFactory().pixelToGeo(evt.getPoint(), mapViewer.getZoom());
- cordLabel.setText(geopos.toString());
+ firePropertyChange(CURRENT_MOUSE_GEOPOSITION, null, geopos);
}//GEN-LAST:event_mapViewerMouseMoved
private void mapViewerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseClicked
@@ -623,11 +627,39 @@ final public class MapPanel extends javax.swing.JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JLabel cordLabel;
- private javax.swing.JPanel infoPanel;
private org.jxmapviewer.JXMapViewer mapViewer;
- private javax.swing.JProgressBar progressBar;
private javax.swing.JPanel zoomPanel;
private javax.swing.JSlider zoomSlider;
// End of variables declaration//GEN-END:variables
+
+ /**
+ * Renderer for the map waypoints.
+ */
+ private class MapWaypointRenderer implements WaypointRenderer {
+ private final BufferedImage defaultWaypointImage;
+ private final BufferedImage selectedWaypointImage;
+
+ /**
+ * Construct a WaypointRenederer
+ *
+ * @throws IOException
+ */
+ MapWaypointRenderer() throws IOException {
+ defaultWaypointImage = ImageIO.read(getClass().getResource("/org/sleuthkit/autopsy/images/waypoint_teal.png"));
+ selectedWaypointImage = ImageIO.read(getClass().getResource("/org/sleuthkit/autopsy/images/waypoint_yellow.png"));
+ }
+
+ @Override
+ public void paintWaypoint(Graphics2D gd, JXMapViewer jxmv, Waypoint waypoint) {
+ Point2D point = jxmv.getTileFactory().geoToPixel(waypoint.getPosition(), jxmv.getZoom());
+
+ int x = (int)point.getX();
+ int y = (int)point.getY();
+
+ BufferedImage image = (waypoint == currentlySelectedWaypoint ? selectedWaypointImage: defaultWaypointImage);
+
+ (gd.create()).drawImage(image, x -image.getWidth() / 2, y -image.getHeight(), null);
+ }
+
+ }
}
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java
index 7a28f49737..61b4800d7a 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java
@@ -95,21 +95,21 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return mapPoints;
}
-
+
/**
- * Returns a list of of MapWaypoint objects for the given list of
+ * Returns a list of of MapWaypoint objects for the given list of
* datamodel.Waypoint objects.
- *
+ *
* @param dmWaypoints
- *
- * @return List of MapWaypoint objects. List will be empty if dmWaypoints was
- * empty or null.
+ *
+ * @return List of MapWaypoint objects. List will be empty if dmWaypoints
+ * was empty or null.
*/
static List getWaypoints(List dmWaypoints) {
List mapPoints = new ArrayList<>();
if (dmWaypoints != null) {
-
+
for (Waypoint point : dmWaypoints) {
mapPoints.add(new MapWaypoint(point));
}
@@ -118,6 +118,27 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return mapPoints;
}
+ /**
+ * Helper function to get a list of data model waypoints from a list of
+ * MapWaypoints.
+ *
+ * @param mapWaypoints
+ *
+ * @return A list of Waypoint objects, or empty list if mapWaypoints was
+ * null or empty.
+ */
+ static List getDataModelWaypoints(List mapWaypoints) {
+ List waypoints = new ArrayList<>();
+
+ if (mapWaypoints != null) {
+ for (MapWaypoint point : mapWaypoints) {
+ waypoints.add(point.dataModelWaypoint);
+ }
+ }
+
+ return waypoints;
+ }
+
/**
* Returns a MapWaypoint without a reference to the datamodel waypoint.
*
@@ -271,20 +292,20 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
}
return menuItems;
}
-
- /**
+
+ /**
* Get the nicely formatted details for the given waypoint.
- *
- * @param point Waypoint object
+ *
+ * @param point Waypoint object
* @param header String details header
- *
- * @return HTML formatted String of details for given waypoint
+ *
+ * @return HTML formatted String of details for given waypoint
*/
private String getFormattedDetails(Waypoint point) {
StringBuilder result = new StringBuilder(); //NON-NLS
-
+
result.append("").append(formatAttribute("Name", point.getLabel()));
-
+
Long timestamp = point.getTimestamp();
if (timestamp != null) {
result.append(formatAttribute("Timestamp", getTimeStamp(timestamp)));
@@ -292,19 +313,19 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
result.append(formatAttribute("Latitude", point.getLatitude().toString()))
.append(formatAttribute("Longitude", point.getLongitude().toString()));
-
+
if (point.getAltitude() != null) {
result.append(formatAttribute("Altitude", point.getAltitude().toString()));
}
List list = point.getOtherProperties();
- for(Waypoint.Property prop: list) {
+ for (Waypoint.Property prop : list) {
String value = prop.getValue();
- if(value != null && !value.isEmpty()) {
+ if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value));
}
}
-
+
result.append("");
return result.toString();
@@ -312,16 +333,16 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
/**
* Format a title value pair.
- *
+ *
* @param title Title of the property
* @param value Value of the property
- *
- * @return Formatted string with the title and value
+ *
+ * @return Formatted string with the title and value
*/
private String formatAttribute(String title, String value) {
return String.format(HTML_PROP_FORMAT, title, value);
}
-
+
/**
* Format a point time stamp (in seconds) to the report format.
*
@@ -333,7 +354,6 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return DATE_FORMAT.format(new java.util.Date(timeStamp * 1000));
}
-
/**
* An action class for Extracting artifact files.
*/
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/BookmarkWaypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/BookmarkWaypoint.java
new file mode 100755
index 0000000000..08fdfeccb6
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/BookmarkWaypoint.java
@@ -0,0 +1,78 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2019 Basis Technology Corp.
+ * contact: carrier sleuthkit 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.Map;
+import org.sleuthkit.datamodel.BlackboardArtifact;
+import org.sleuthkit.datamodel.BlackboardAttribute;
+
+/**
+ * Class to represent TSK_GPS_BOOKMARK waypoints
+ *
+ */
+final class BookmarkWaypoint extends Waypoint {
+
+ /**
+ * Constructs a new BookmarkWaypoint from the given artifact.
+ *
+ * @param artifact BlackboardArtifact for this waypoint
+ *
+ * @throws GeoLocationDataException
+ */
+ BookmarkWaypoint(BlackboardArtifact artifact) throws GeoLocationDataException {
+ this(artifact, getAttributesFromArtifactAsMap(artifact));
+ }
+
+ /**
+ * Constructs a new BookmarkWaypoint.
+ *
+ * @param artifact BlackboardArtifact for this waypoint
+ * @param attributeMap A Map of the BlackboardAttributes for the given
+ * artifact.
+ *
+ * @throws GeoLocationDataException
+ */
+ private BookmarkWaypoint(BlackboardArtifact artifact, Map attributeMap) throws GeoLocationDataException {
+ super(artifact,
+ getLabelFromArtifact(attributeMap),
+ attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME).getValueLong() : null,
+ attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE).getValueDouble() : null,
+ attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE).getValueDouble() : null,
+ attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE).getValueDouble() : null,
+ null, attributeMap, null);
+ }
+
+ /**
+ * Gets the label for this waypoint.
+ *
+ * @param artifact BlackboardArtifact for waypoint
+ *
+ * @return Returns a label for the waypoint, or empty string if no label was
+ * found.
+ */
+ private static String getLabelFromArtifact(Map attributeMap) {
+ BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
+ if (attribute != null) {
+ return attribute.getDisplayString();
+ }
+
+ return "";
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java
index 27e5da0dbd..8cc35555eb 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java
@@ -50,10 +50,10 @@ public class Waypoint {
final private List immutablePropertiesList;
/**
- * This is a list of attributes that are already being handled by the
- * by getter functions.
+ * This is a list of attributes that are already being handled by the by
+ * getter functions.
*/
- static private BlackboardAttribute.ATTRIBUTE_TYPE[] ALREADY_HANDLED_ATTRIBUTES = {
+ static final private BlackboardAttribute.ATTRIBUTE_TYPE[] ALREADY_HANDLED_ATTRIBUTES = {
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE,
@@ -65,19 +65,6 @@ public class Waypoint {
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END,};
- /**
- * Construct a waypoint with the given artifact.
- *
- * @param artifact BlackboardArtifact for this waypoint
- *
- * @throws GeoLocationDataException Exception will be thrown if artifact did
- * not have a valid longitude and latitude.
- */
- Waypoint(BlackboardArtifact artifact) throws GeoLocationDataException {
- this(artifact,
- getAttributesFromArtifactAsMap(artifact));
- }
-
/**
* Constructor that initializes all of the member variables.
*
@@ -110,25 +97,6 @@ public class Waypoint {
immutablePropertiesList = Collections.unmodifiableList(createGeolocationProperties(attributeMap));
}
- /**
- * Constructs a new ArtifactWaypoint.
- *
- * @param artifact BlackboardArtifact for this waypoint
- * @param attributeMap A Map of the BlackboardAttributes for the given
- * artifact.
- *
- * @throws GeoLocationDataException
- */
- private Waypoint(BlackboardArtifact artifact, Map attributeMap) throws GeoLocationDataException {
- this(artifact,
- getLabelFromArtifact(attributeMap),
- attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME).getValueLong() : null,
- attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE).getValueDouble() : null,
- attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE).getValueDouble() : null,
- attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE).getValueDouble() : null,
- null, attributeMap, null);
- }
-
/**
* Get the BlackboardArtifact that this waypoint represents.
*
@@ -205,11 +173,12 @@ public class Waypoint {
public List getOtherProperties() {
return immutablePropertiesList;
}
-
+
/**
* Returns the route that this waypoint is apart of .
- *
- * @return The waypoint route or null if the waypoint is not apart of a route.
+ *
+ * @return The waypoint route or null if the waypoint is not apart of a
+ * route.
*/
public Route getRoute() {
return route;
diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java
index 7189302809..86539412be 100755
--- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java
+++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java
@@ -45,7 +45,7 @@ public final class WaypointBuilder {
= "SELECT artifact_id, artifact_type_id "
+ "FROM blackboard_attributes "
+ "WHERE attribute_type_id IN (%d, %d) "; //NON-NLS
-
+
// SELECT statement to get only artifact_ids
final static String GEO_ARTIFACT_QUERY_ID_ONLY
= "SELECT artifact_id "
@@ -70,8 +70,8 @@ public final class WaypointBuilder {
+ " )";
// Returns a list of artifacts with no time stamp
- final static String SELECT_WO_TIMESTAMP =
- "SELECT DISTINCT artifact_id, artifact_type_id "
+ final static String SELECT_WO_TIMESTAMP
+ = "SELECT DISTINCT artifact_id, artifact_type_id "
+ "FROM blackboard_attributes "
+ "WHERE artifact_id NOT IN (%s) "
+ "AND artifact_id IN (%s)"; //NON-NLS
@@ -121,6 +121,25 @@ public final class WaypointBuilder {
return points;
}
+ /**
+ * Returns a list of routes from the given list of waypoints.
+ *
+ * @param waypoints A list of waypoints
+ *
+ * @return A list of routes or an empty list if none were found.
+ */
+ public static List getRoutes(List waypoints) {
+ List routeList = new ArrayList<>();
+ for (Waypoint point : waypoints) {
+ Route route = point.getRoute();
+ if (route != null && !routeList.contains(route)) {
+ routeList.add(route);
+ }
+ }
+
+ return routeList;
+ }
+
/**
* Gets a list of Waypoints for TSK_GPS_TRACKPOINT artifacts.
*
@@ -150,6 +169,25 @@ public final class WaypointBuilder {
return points;
}
+ /**
+ * Returns a list of waypoints that come from TSK_GEO_TRACKPOINT artifacts.
+ *
+ * @param waypoints A list of waypoints
+ *
+ * @return A list of trackpoint waypoints or empty list if none were found.
+ */
+ public static List getTrackpointWaypoints(List waypoints) {
+ List specificPoints = new ArrayList<>();
+
+ for (Waypoint point : waypoints) {
+ if (point instanceof TrackpointWaypoint) {
+ specificPoints.add(point);
+ }
+ }
+
+ return specificPoints;
+ }
+
/**
* Gets a list of Waypoints for TSK_METADATA_EXIF artifacts.
*
@@ -183,6 +221,25 @@ public final class WaypointBuilder {
return points;
}
+ /**
+ * Returns a list of waypoints that come from TSK_METADATA_EXIF artifacts.
+ *
+ * @param waypoints A list of waypoints
+ *
+ * @return A list of trackpoint waypoints or empty list if none were found.
+ */
+ public static List getEXIFWaypoints(List waypoints) {
+ List specificPoints = new ArrayList<>();
+
+ for (Waypoint point : waypoints) {
+ if (point instanceof EXIFWaypoint) {
+ specificPoints.add(point);
+ }
+ }
+
+ return specificPoints;
+ }
+
/**
* Gets a list of Waypoints for TSK_GPS_SEARCH artifacts.
*
@@ -214,6 +271,25 @@ public final class WaypointBuilder {
return points;
}
+ /**
+ * Returns a list of waypoints that come from TSK_GPS_SEARCH artifacts.
+ *
+ * @param waypoints A list of waypoints
+ *
+ * @return A list of trackpoint waypoints or empty list if none were found.
+ */
+ public static List getSearchWaypoints(List waypoints) {
+ List specificPoints = new ArrayList<>();
+
+ for (Waypoint point : waypoints) {
+ if (point instanceof SearchWaypoint) {
+ specificPoints.add(point);
+ }
+ }
+
+ return specificPoints;
+ }
+
/**
* Gets a list of Waypoints for TSK_GPS_LAST_KNOWN_LOCATION artifacts.
*
@@ -245,6 +321,26 @@ public final class WaypointBuilder {
return points;
}
+ /**
+ * Returns a list of waypoints that come from TSK_GPS_LAST_KNOWN_LOCATION
+ * artifacts.
+ *
+ * @param waypoints A list of waypoints
+ *
+ * @return A list of trackpoint waypoints or empty list if none were found.
+ */
+ public static List getLastKnownWaypoints(List waypoints) {
+ List specificPoints = new ArrayList<>();
+
+ for (Waypoint point : waypoints) {
+ if (point instanceof LastKnownWaypoint) {
+ specificPoints.add(point);
+ }
+ }
+
+ return specificPoints;
+ }
+
/**
* Gets a list of Waypoints for TSK_GPS_BOOKMARK artifacts.
*
@@ -266,7 +362,7 @@ public final class WaypointBuilder {
if (artifacts != null) {
for (BlackboardArtifact artifact : artifacts) {
try {
- Waypoint point = new Waypoint(artifact);
+ Waypoint point = new BookmarkWaypoint(artifact);
points.add(point);
} catch (GeoLocationDataException ex) {
logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_BOOKMARK artifactID: %d", artifact.getArtifactID()), ex);//NON-NLS
@@ -276,6 +372,26 @@ public final class WaypointBuilder {
return points;
}
+ /**
+ * Returns a list of waypoints that come from TSK_GPS_LAST_KNOWN_LOCATION
+ * artifacts.
+ *
+ * @param waypoints A list of waypoints
+ *
+ * @return A list of trackpoint waypoints or empty list if none were found.
+ */
+ public static List getBookmarkWaypoints(List waypoints) {
+ List specificPoints = new ArrayList<>();
+
+ for (Waypoint point : waypoints) {
+ if (point instanceof BookmarkWaypoint) {
+ specificPoints.add(point);
+ }
+ }
+
+ return specificPoints;
+ }
+
/**
* Get a filtered list of waypoints.
*
@@ -386,7 +502,7 @@ public final class WaypointBuilder {
String mostRecentQuery = "";
if (!showAll && cntDaysFromRecent > 0) {
- mostRecentQuery = String.format("AND value_int64 > (%s)", //NON-NLS
+ mostRecentQuery = String.format("AND value_int64 > (%s)", //NON-NLS
String.format(MOST_RECENT_TIME,
cntDaysFromRecent,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
@@ -464,7 +580,7 @@ public final class WaypointBuilder {
waypoints.add(new EXIFWaypoint(artifact));
break;
case TSK_GPS_BOOKMARK:
- waypoints.add(new Waypoint(artifact));
+ waypoints.add(new BookmarkWaypoint(artifact));
break;
case TSK_GPS_TRACKPOINT:
waypoints.add(new TrackpointWaypoint(artifact));
@@ -477,8 +593,7 @@ public final class WaypointBuilder {
waypoints.addAll(route.getRoute());
break;
default:
- waypoints.add(new Waypoint(artifact));
- break;
+ throw new GeoLocationDataException(String.format("Unable to create waypoint for artifact of type %s", type.toString()));
}
return waypoints;
diff --git a/Core/src/org/sleuthkit/autopsy/images/waypoint_teal.png b/Core/src/org/sleuthkit/autopsy/images/waypoint_teal.png
new file mode 100755
index 0000000000..3860d1973c
Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/waypoint_teal.png differ
diff --git a/Core/src/org/sleuthkit/autopsy/images/waypoint_yellow.png b/Core/src/org/sleuthkit/autopsy/images/waypoint_yellow.png
new file mode 100755
index 0000000000..1cd715c101
Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/waypoint_yellow.png differ
diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java b/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java
index a140338524..e7e7a49503 100644
--- a/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java
+++ b/Core/src/org/sleuthkit/autopsy/report/modules/kml/KMLReport.java
@@ -33,6 +33,7 @@ import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.jdom2.Document;
@@ -59,7 +60,7 @@ import org.sleuthkit.datamodel.TskCoreException;
/**
* Generates a KML file based on geospatial information from the BlackBoard.
*/
-class KMLReport implements GeneralReportModule {
+public class KMLReport implements GeneralReportModule {
private static final Logger logger = Logger.getLogger(KMLReport.class.getName());
private static final String KML_STYLE_FILE = "style.kml";
@@ -79,6 +80,8 @@ class KMLReport implements GeneralReportModule {
private Element gpsSearchesFolder;
private Element gpsTrackpointsFolder;
+ private List waypointList = null;
+
private enum FeatureColor {
RED("style.kml#redFeature"),
GREEN("style.kml#greenFeature"),
@@ -141,6 +144,11 @@ class KMLReport implements GeneralReportModule {
"Route_Details_Header=GPS Route"
})
+ public void generateReport(String baseReportDir, ReportProgressPanel progressPanel, List waypointList) {
+ this.waypointList = waypointList;
+ generateReport(baseReportDir, progressPanel);
+ }
+
@Override
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
try {
@@ -298,7 +306,7 @@ class KMLReport implements GeneralReportModule {
* @throws IOException
*/
void addExifMetadataContent(List points, String baseReportDirectory) throws IOException {
- for(Waypoint point: points) {
+ for (Waypoint point : points) {
Element mapPoint = makePoint(point);
if (mapPoint == null) {
return;
@@ -332,41 +340,49 @@ class KMLReport implements GeneralReportModule {
* @throws IOException
*/
void addLocationsToReport(SleuthkitCase skCase, String baseReportDir) throws GeoLocationDataException, IOException {
- addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(skCase), baseReportDir);
- addWaypoints(WaypointBuilder.getBookmarkWaypoints(skCase), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String());
- addWaypoints(WaypointBuilder.getLastKnownWaypoints(skCase), gpsLastKnownLocationFolder, FeatureColor.PURPLE, Bundle.Waypoint_Last_Known_Display_String());
- addWaypoints(WaypointBuilder.getSearchWaypoints(skCase), gpsSearchesFolder, FeatureColor.WHITE, Bundle.Waypoint_Search_Display_String());
- addWaypoints(WaypointBuilder.getTrackpointWaypoints(skCase), gpsTrackpointsFolder, FeatureColor.WHITE, Bundle.Waypoint_Trackpoint_Display_String());
+ if (waypointList == null) {
+ addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(skCase), baseReportDir);
+ addWaypoints(WaypointBuilder.getBookmarkWaypoints(skCase), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String());
+ addWaypoints(WaypointBuilder.getLastKnownWaypoints(skCase), gpsLastKnownLocationFolder, FeatureColor.PURPLE, Bundle.Waypoint_Last_Known_Display_String());
+ addWaypoints(WaypointBuilder.getSearchWaypoints(skCase), gpsSearchesFolder, FeatureColor.WHITE, Bundle.Waypoint_Search_Display_String());
+ addWaypoints(WaypointBuilder.getTrackpointWaypoints(skCase), gpsTrackpointsFolder, FeatureColor.WHITE, Bundle.Waypoint_Trackpoint_Display_String());
+ } else {
+ addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(waypointList), baseReportDir);
+ addWaypoints(WaypointBuilder.getBookmarkWaypoints(waypointList), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String());
+ addWaypoints(WaypointBuilder.getLastKnownWaypoints(waypointList), gpsLastKnownLocationFolder, FeatureColor.PURPLE, Bundle.Waypoint_Last_Known_Display_String());
+ addWaypoints(WaypointBuilder.getSearchWaypoints(waypointList), gpsSearchesFolder, FeatureColor.WHITE, Bundle.Waypoint_Search_Display_String());
+ addWaypoints(WaypointBuilder.getTrackpointWaypoints(waypointList), gpsTrackpointsFolder, FeatureColor.WHITE, Bundle.Waypoint_Trackpoint_Display_String());
+ }
}
-
+
/**
- * For each point in the waypoint list an Element to represent the given waypoint
- * is created and added it to the given Element folder.
- *
- * @param points List of waypoints to add to the report
- * @param folder The Element folder to add the points to
+ * For each point in the waypoint list an Element to represent the given
+ * waypoint is created and added it to the given Element folder.
+ *
+ * @param points List of waypoints to add to the report
+ * @param folder The Element folder to add the points to
* @param waypointColor The color the waypoint should appear in the report
*/
void addWaypoints(List points, Element folder, FeatureColor waypointColor, String headerLabel) {
- for(Waypoint point: points) {
+ for (Waypoint point : points) {
addContent(folder, point.getLabel(), waypointColor, getFormattedDetails(point, headerLabel), point.getTimestamp(), makePoint(point), point.getLatitude(), point.getLongitude());
}
}
-
+
/**
* Adds the waypoint Element with details to the report in the given folder.
- *
- * @param folder Element folder to add the waypoint to
- * @param waypointLabel String waypoint Label
- * @param waypointColor FeatureColor for the waypoint
+ *
+ * @param folder Element folder to add the waypoint to
+ * @param waypointLabel String waypoint Label
+ * @param waypointColor FeatureColor for the waypoint
* @param formattedDetails String HTML formatted waypoint details
- * @param timestamp Long timestamp (unix\jave epoch seconds)
- * @param point Element point object
- * @param latitude Double latitude value
- * @param longitude Double longitude value
+ * @param timestamp Long timestamp (unix\jave epoch seconds)
+ * @param point Element point object
+ * @param latitude Double latitude value
+ * @param longitude Double longitude value
*/
void addContent(Element folder, String waypointLabel, FeatureColor waypointColor, String formattedDetails, Long timestamp, Element point, Double latitude, Double longitude) {
- if(folder != null && point != null) {
+ if (folder != null && point != null) {
String formattedCords = formattedCoordinates(latitude, longitude);
folder.addContent(makePlacemark(waypointLabel, waypointColor, formattedDetails, timestamp, point, formattedCords));
}
@@ -380,17 +396,19 @@ class KMLReport implements GeneralReportModule {
* @throws TskCoreException
*/
void makeRoutes(SleuthkitCase skCase) throws GeoLocationDataException {
- List routes = Route.getRoutes(skCase);
-
- if(routes == null) {
- return;
+ List routes = null;
+
+ if (waypointList == null) {
+ routes = Route.getRoutes(skCase);
+ } else {
+ routes = new ArrayList<>();
}
for (Route route : routes) {
addRouteToReport(route);
}
}
-
+
void addRouteToReport(Route route) {
List routePoints = route.getRoute();
Waypoint start = null;
@@ -423,15 +441,15 @@ class KMLReport implements GeneralReportModule {
}
if (startingPoint != null) {
- gpsRouteFolder.addContent(makePlacemark(start.getLabel(),
- FeatureColor.GREEN, getFormattedDetails(start, Bundle.Waypoint_Route_Point_Display_String()),
+ gpsRouteFolder.addContent(makePlacemark(start.getLabel(),
+ FeatureColor.GREEN, getFormattedDetails(start, Bundle.Waypoint_Route_Point_Display_String()),
start.getTimestamp(), startingPoint, formattedStart)); //NON-NLS
}
if (endingPoint != null) {
- gpsRouteFolder.addContent(makePlacemark(end.getLabel(),
- FeatureColor.GREEN,
- getFormattedDetails(end, Bundle.Waypoint_Route_Point_Display_String()),
+ gpsRouteFolder.addContent(makePlacemark(end.getLabel(),
+ FeatureColor.GREEN,
+ getFormattedDetails(end, Bundle.Waypoint_Route_Point_Display_String()),
end.getTimestamp(), endingPoint, formattedEnd)); //NON-NLS
}
}
@@ -688,11 +706,11 @@ class KMLReport implements GeneralReportModule {
/**
* Get the nicely formatted details for the given waypoint.
- *
- * @param point Waypoint object
+ *
+ * @param point Waypoint object
* @param header String details header
- *
- * @return HTML formatted String of details for given waypoint
+ *
+ * @return HTML formatted String of details for given waypoint
*/
private String getFormattedDetails(Waypoint point, String header) {
StringBuilder result = new StringBuilder(); //NON-NLS
@@ -706,15 +724,15 @@ class KMLReport implements GeneralReportModule {
result.append(formatAttribute("Latitude", point.getLatitude().toString()))
.append(formatAttribute("Longitude", point.getLongitude().toString()));
-
+
if (point.getAltitude() != null) {
result.append(formatAttribute("Altitude", point.getAltitude().toString()));
}
List list = point.getOtherProperties();
- for(Waypoint.Property prop: list) {
+ for (Waypoint.Property prop : list) {
String value = prop.getValue();
- if(value != null && !value.isEmpty()) {
+ if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value));
}
}
@@ -733,8 +751,7 @@ class KMLReport implements GeneralReportModule {
*
* @return A HTML formatted list of the Route attributes
*/
-
- private String getFormattedDetails(Route route) {
+ private String getFormattedDetails(Route route) {
List points = route.getRoute();
StringBuilder result = new StringBuilder(); //NON-NLS
@@ -752,38 +769,38 @@ class KMLReport implements GeneralReportModule {
result.append(formatAttribute("Start Latitude", start.getLatitude().toString()))
.append(formatAttribute("Start Longitude", start.getLongitude().toString()));
-
+
Double altitude = start.getAltitude();
- if(altitude != null) {
+ if (altitude != null) {
result.append(formatAttribute("Start Altitude", altitude.toString()));
}
-
+
result.append(formatAttribute("End Latitude", end.getLatitude().toString()))
.append(formatAttribute("End Longitude", end.getLongitude().toString()));
-
+
altitude = end.getAltitude();
- if(altitude != null) {
+ if (altitude != null) {
result.append(formatAttribute("End Altitude", altitude.toString()));
}
}
List list = route.getOtherProperties();
- for(Waypoint.Property prop: list) {
+ for (Waypoint.Property prop : list) {
String value = prop.getValue();
- if(value != null && !value.isEmpty()) {
+ if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value));
}
}
return result.toString();
}
-
+
/**
* Helper functions for consistently formatting longitude and latitude.
- *
- * @param latitude Double latitude value
+ *
+ * @param latitude Double latitude value
* @param longitude Double longitude value
- *
+ *
* @return String Nicely formatted double values separated by a comma
*/
private String formattedCoordinates(Double latitude, Double longitude) {