Merge pull request #5469 from kellykelly3/5797-highlite-selected-waypoints

5797 highlite selected waypoints
This commit is contained in:
Richard Cordovano 2019-12-06 11:04:17 -05:00 committed by GitHub
commit 4222a004e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 636 additions and 255 deletions

View File

@ -4,7 +4,6 @@ CTL_GeolocationTopComponent=Geolocation
RefreshPanel.refreshLabel.text=The geolocation data has been updated, the visualization may be out of date. RefreshPanel.refreshLabel.text=The geolocation data has been updated, the visualization may be out of date.
RefreshPanel.refreshButton.text=Refresh View RefreshPanel.refreshButton.text=Refresh View
RefreshPanel.closeButton.text= RefreshPanel.closeButton.text=
MapPanel.cordLabel.text=
WaypointDetailPanel.closeButton.text= WaypointDetailPanel.closeButton.text=
WaypointDetailPanel.imageLabel.text= WaypointDetailPanel.imageLabel.text=
GeoFilterPanel.waypointSettings.border.title= GeoFilterPanel.waypointSettings.border.title=
@ -30,3 +29,5 @@ GeolocationSettingsPanel.osmZipFileField.text=
GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse
GeolocationSettingsPanel.serverTestButton.text=Test GeolocationSettingsPanel.serverTestButton.text=Test
GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file
GeolocationTopComponent.reportButton.text=KML Report
GeolocationTopComponent.coordLabel.text=jLabel1

View File

@ -11,6 +11,9 @@ GeolocationSettingsPanel_osm_server_test_success_message=The provide OSM tile se
GeolocationSettingsPanel_osm_server_test_success_message_title=Success 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=Failed to connect to map title source.\nPlease review map source in Options dialog.
GeolocationTC_connection_failure_message_title=Connection Failure 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_msg=Unable to run waypoint filter.\nPlease select one or more data sources.
GeoTopComponent_filer_data_invalid_Title=Filter Failure GeoTopComponent_filer_data_invalid_Title=Filter Failure
GeoTopComponent_filter_exception_msg=Exception occured during waypoint filtering. 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.refreshLabel.text=The geolocation data has been updated, the visualization may be out of date.
RefreshPanel.refreshButton.text=Refresh View RefreshPanel.refreshButton.text=Refresh View
RefreshPanel.closeButton.text= RefreshPanel.closeButton.text=
MapPanel.cordLabel.text=
WaypointDetailPanel.closeButton.text= WaypointDetailPanel.closeButton.text=
WaypointDetailPanel.imageLabel.text= WaypointDetailPanel.imageLabel.text=
GeoFilterPanel.waypointSettings.border.title= GeoFilterPanel.waypointSettings.border.title=
@ -54,4 +56,6 @@ GeolocationSettingsPanel.osmZipFileField.text=
GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse
GeolocationSettingsPanel.serverTestButton.text=Test GeolocationSettingsPanel.serverTestButton.text=Test
GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file
GeolocationTopComponent.reportButton.text=KML Report
GeolocationTopComponent.coordLabel.text=jLabel1
WaypointExtractAction_label=Extract Files(s) WaypointExtractAction_label=Extract Files(s)

View File

@ -16,6 +16,63 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents> <SubComponents>
<Container class="org.sleuthkit.autopsy.geolocation.HidingPane" name="filterPane">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="West"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="statusBar">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="South"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JButton" name="reportButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="GeolocationTopComponent.reportButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="reportButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JProgressBar" name="progressBar">
<Properties>
<Property name="indeterminate" type="boolean" value="true"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="coordLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="GeolocationTopComponent.coordLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="org.sleuthkit.autopsy.geolocation.MapPanel" name="mapPanel"> <Container class="org.sleuthkit.autopsy.geolocation.MapPanel" name="mapPanel">
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
@ -24,17 +81,6 @@
</Constraints> </Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="org.sleuthkit.autopsy.geolocation.HidingPane" name="filterPane">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Before"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container>
</SubComponents>
</Container> </Container>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -21,14 +21,22 @@ package org.sleuthkit.autopsy.geolocation;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; 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.ArrayList;
import java.util.Date;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.windows.RetainLocation; import org.openide.windows.RetainLocation;
import org.openide.windows.TopComponent; import org.openide.windows.TopComponent;
@ -46,6 +54,8 @@ import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder.WaypointFilte
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED; import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; 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; import org.sleuthkit.datamodel.BlackboardArtifact;
/** /**
@ -70,6 +80,11 @@ public final class GeolocationTopComponent extends TopComponent {
final RefreshPanel refreshPanel = new RefreshPanel(); 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({ @Messages({
"GLTopComponent_name=Geolocation", "GLTopComponent_name=Geolocation",
"GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete." "GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete."
@ -134,6 +149,20 @@ public final class GeolocationTopComponent extends TopComponent {
updateWaypoints(); 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 @Override
@ -169,15 +198,15 @@ public final class GeolocationTopComponent extends TopComponent {
try { try {
mapPanel.initMap(); mapPanel.initMap();
} catch (GeoLocationDataException ex) { } catch (GeoLocationDataException ex) {
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
Bundle.GeolocationTC_connection_failure_message(), Bundle.GeolocationTC_connection_failure_message(),
Bundle.GeolocationTC_connection_failure_message_title(), Bundle.GeolocationTC_connection_failure_message_title(),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
Bundle.GeolocationTC_connection_failure_message_title(), Bundle.GeolocationTC_connection_failure_message_title(),
Bundle.GeolocationTC_connection_failure_message()); Bundle.GeolocationTC_connection_failure_message());
logger.log(Level.SEVERE, ex.getMessage(), ex); logger.log(Level.SEVERE, ex.getMessage(), ex);
return; // Doen't set the waypoints. return; // Doen't set the waypoints.
} }
mapPanel.setWaypoints(new ArrayList<>()); mapPanel.setWaypoints(new ArrayList<>());
updateWaypoints(); updateWaypoints();
@ -217,19 +246,57 @@ public final class GeolocationTopComponent extends TopComponent {
filters = geoFilterPanel.getFilterState(); filters = geoFilterPanel.getFilterState();
} catch (GeoLocationUIException ex) { } catch (GeoLocationUIException ex) {
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
Bundle.GeoTopComponent_filer_data_invalid_msg(), Bundle.GeoTopComponent_filer_data_invalid_msg(),
Bundle.GeoTopComponent_filer_data_invalid_Title(), Bundle.GeoTopComponent_filer_data_invalid_Title(),
JOptionPane.INFORMATION_MESSAGE); JOptionPane.INFORMATION_MESSAGE);
return; return;
} }
mapPanel.setWaypointLoading(true); setWaypointLoading(true);
geoFilterPanel.setEnabled(false); geoFilterPanel.setEnabled(false);
Thread thread = new Thread(new WaypointRunner(filters)); Thread thread = new Thread(new WaypointRunner(filters));
thread.start(); 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: <CASE DIRECTORY>/Reports/<Case fileName> <Timestamp>/
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. * 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 * WARNING: Do NOT modify this code. The content of this method is always
@ -238,21 +305,86 @@ public final class GeolocationTopComponent extends TopComponent {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
mapPanel = new org.sleuthkit.autopsy.geolocation.MapPanel();
filterPane = new org.sleuthkit.autopsy.geolocation.HidingPane(); 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()); 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); add(mapPanel, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//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<MapWaypoint> 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 // 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.HidingPane filterPane;
private org.sleuthkit.autopsy.geolocation.MapPanel mapPanel; 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 // End of variables declaration//GEN-END:variables
/** /**
@ -287,10 +419,10 @@ public final class GeolocationTopComponent extends TopComponent {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
JOptionPane.showMessageDialog(GeolocationTopComponent.this, JOptionPane.showMessageDialog(GeolocationTopComponent.this,
Bundle.GeoTopComponent_filter_exception_Title(), Bundle.GeoTopComponent_filter_exception_Title(),
Bundle.GeoTopComponent_filter_exception_msg(), Bundle.GeoTopComponent_filter_exception_msg(),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} }
}); });
} }
@ -321,6 +453,7 @@ public final class GeolocationTopComponent extends TopComponent {
return; return;
} }
mapPanel.setWaypoints(MapWaypoint.getWaypoints(waypoints)); mapPanel.setWaypoints(MapWaypoint.getWaypoints(waypoints));
setWaypointLoading(false);
geoFilterPanel.setEnabled(true); geoFilterPanel.setEnabled(true);
} }
}); });

View File

@ -91,39 +91,5 @@
</Container> </Container>
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JPanel" name="infoPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="South"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="cordLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="MapPanel.cordLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JProgressBar" name="progressBar">
<Properties>
<Property name="indeterminate" type="boolean" value="true"/>
<Property name="stringPainted" type="boolean" value="true"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.geolocation; package org.sleuthkit.autopsy.geolocation;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -27,9 +28,12 @@ import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -46,6 +50,7 @@ import javax.swing.Popup;
import javax.swing.PopupFactory; import javax.swing.PopupFactory;
import javax.swing.Timer; import javax.swing.Timer;
import javax.swing.event.MouseInputListener; import javax.swing.event.MouseInputListener;
import org.jxmapviewer.JXMapViewer;
import org.jxmapviewer.OSMTileFactoryInfo; import org.jxmapviewer.OSMTileFactoryInfo;
import org.jxmapviewer.VirtualEarthTileFactoryInfo; import org.jxmapviewer.VirtualEarthTileFactoryInfo;
import org.jxmapviewer.input.CenterMapListener; import org.jxmapviewer.input.CenterMapListener;
@ -57,6 +62,7 @@ import org.jxmapviewer.viewer.TileFactory;
import org.jxmapviewer.viewer.TileFactoryInfo; import org.jxmapviewer.viewer.TileFactoryInfo;
import org.jxmapviewer.viewer.Waypoint; import org.jxmapviewer.viewer.Waypoint;
import org.jxmapviewer.viewer.WaypointPainter; import org.jxmapviewer.viewer.WaypointPainter;
import org.jxmapviewer.viewer.WaypointRenderer;
import org.jxmapviewer.viewer.util.GeoUtil; import org.jxmapviewer.viewer.util.GeoUtil;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.core.UserPreferences; 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.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import javax.imageio.ImageIO;
import org.jxmapviewer.viewer.DefaultWaypointRenderer;
/** /**
* The map panel. This panel contains the jxmapviewer MapViewer * The map panel. This panel contains the jxmapviewer MapViewer
*/ */
final public class MapPanel extends javax.swing.JPanel { 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 Logger logger = Logger.getLogger(MapPanel.class.getName());
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -123,13 +132,34 @@ final public class MapPanel extends javax.swing.JPanel {
Bundle.MapPanel_connection_failure_message_title(), Bundle.MapPanel_connection_failure_message_title(),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
Bundle.MapPanel_connection_failure_message_title(), Bundle.MapPanel_connection_failure_message_title(),
Bundle.MapPanel_connection_failure_message()); 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<MapWaypoint> getVisibleWaypoints() {
Rectangle viewport = mapViewer.getViewportBounds();
List<MapWaypoint> waypoints = new ArrayList<>();
Iterator<MapWaypoint> 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. * Initialize the map.
*/ */
@ -160,7 +190,7 @@ final public class MapPanel extends javax.swing.JPanel {
setZoom(tileFactory.getInfo().getMaximumZoomLevel() - 1); setZoom(tileFactory.getInfo().getMaximumZoomLevel() - 1);
mapViewer.setCenterPosition(new GeoPosition(0,0)); mapViewer.setCenterPosition(new GeoPosition(0, 0));
// Basic painters for the way points. // Basic painters for the way points.
WaypointPainter<Waypoint> waypointPainter = new WaypointPainter<Waypoint>() { WaypointPainter<Waypoint> waypointPainter = new WaypointPainter<Waypoint>() {
@ -177,18 +207,14 @@ final public class MapPanel extends javax.swing.JPanel {
} }
}; };
mapViewer.setOverlayPainter(waypointPainter); 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");
} }
/** /**
@ -277,7 +303,6 @@ final public class MapPanel extends javax.swing.JPanel {
} }
mapViewer.repaint(); mapViewer.repaint();
setWaypointLoading(false);
} }
/** /**
@ -316,6 +341,7 @@ final public class MapPanel extends javax.swing.JPanel {
if(currentPopup != null) { if(currentPopup != null) {
showDetailsPopup(); showDetailsPopup();
} }
mapViewer.repaint();
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Failed to show popup for waypoint", 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 = popupFactory.getPopup(this, detailPane, popupLocation.x, popupLocation.y);
currentPopup.show(); currentPopup.show();
mapViewer.repaint();
} }
} }
@ -499,9 +527,6 @@ final public class MapPanel extends javax.swing.JPanel {
mapViewer = new org.jxmapviewer.JXMapViewer(); mapViewer = new org.jxmapviewer.JXMapViewer();
zoomPanel = new javax.swing.JPanel(); zoomPanel = new javax.swing.JPanel();
zoomSlider = new javax.swing.JSlider(); zoomSlider = new javax.swing.JSlider();
infoPanel = new javax.swing.JPanel();
cordLabel = new javax.swing.JLabel();
progressBar = new javax.swing.JProgressBar();
setFocusable(false); setFocusable(false);
setLayout(new java.awt.BorderLayout()); setLayout(new java.awt.BorderLayout());
@ -568,27 +593,6 @@ final public class MapPanel extends javax.swing.JPanel {
mapViewer.add(zoomPanel, gridBagConstraints); mapViewer.add(zoomPanel, gridBagConstraints);
add(mapViewer, java.awt.BorderLayout.CENTER); 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);
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void zoomSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_zoomSliderStateChanged 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 private void mapViewerMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseMoved
GeoPosition geopos = mapViewer.getTileFactory().pixelToGeo(evt.getPoint(), mapViewer.getZoom()); GeoPosition geopos = mapViewer.getTileFactory().pixelToGeo(evt.getPoint(), mapViewer.getZoom());
cordLabel.setText(geopos.toString()); firePropertyChange(CURRENT_MOUSE_GEOPOSITION, null, geopos);
}//GEN-LAST:event_mapViewerMouseMoved }//GEN-LAST:event_mapViewerMouseMoved
private void mapViewerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseClicked 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 // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel cordLabel;
private javax.swing.JPanel infoPanel;
private org.jxmapviewer.JXMapViewer mapViewer; private org.jxmapviewer.JXMapViewer mapViewer;
private javax.swing.JProgressBar progressBar;
private javax.swing.JPanel zoomPanel; private javax.swing.JPanel zoomPanel;
private javax.swing.JSlider zoomSlider; private javax.swing.JSlider zoomSlider;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
/**
* Renderer for the map waypoints.
*/
private class MapWaypointRenderer implements WaypointRenderer<Waypoint> {
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);
}
}
} }

View File

@ -102,8 +102,8 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
* *
* @param dmWaypoints * @param dmWaypoints
* *
* @return List of MapWaypoint objects. List will be empty if dmWaypoints was * @return List of MapWaypoint objects. List will be empty if dmWaypoints
* empty or null. * was empty or null.
*/ */
static List<MapWaypoint> getWaypoints(List<Waypoint> dmWaypoints) { static List<MapWaypoint> getWaypoints(List<Waypoint> dmWaypoints) {
List<MapWaypoint> mapPoints = new ArrayList<>(); List<MapWaypoint> mapPoints = new ArrayList<>();
@ -118,6 +118,27 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return mapPoints; 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<Waypoint> getDataModelWaypoints(List<MapWaypoint> mapWaypoints) {
List<Waypoint> 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. * Returns a MapWaypoint without a reference to the datamodel waypoint.
* *
@ -272,10 +293,10 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return menuItems; return menuItems;
} }
/** /**
* Get the nicely formatted details for the given waypoint. * Get the nicely formatted details for the given waypoint.
* *
* @param point Waypoint object * @param point Waypoint object
* @param header String details header * @param header String details header
* *
* @return HTML formatted String of details for given waypoint * @return HTML formatted String of details for given waypoint
@ -298,9 +319,9 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
} }
List<Waypoint.Property> list = point.getOtherProperties(); List<Waypoint.Property> list = point.getOtherProperties();
for(Waypoint.Property prop: list) { for (Waypoint.Property prop : list) {
String value = prop.getValue(); String value = prop.getValue();
if(value != null && !value.isEmpty()) { if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value)); result.append(formatAttribute(prop.getDisplayName(), value));
} }
} }
@ -333,7 +354,6 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return DATE_FORMAT.format(new java.util.Date(timeStamp * 1000)); return DATE_FORMAT.format(new java.util.Date(timeStamp * 1000));
} }
/** /**
* An action class for Extracting artifact files. * An action class for Extracting artifact files.
*/ */

View File

@ -0,0 +1,78 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 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.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<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> 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<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) {
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
if (attribute != null) {
return attribute.getDisplayString();
}
return "";
}
}

View File

@ -50,10 +50,10 @@ public class Waypoint {
final private List<Waypoint.Property> immutablePropertiesList; final private List<Waypoint.Property> immutablePropertiesList;
/** /**
* This is a list of attributes that are already being handled by the * This is a list of attributes that are already being handled by the by
* by getter functions. * 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_NAME,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, 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_LATITUDE_END,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_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. * Constructor that initializes all of the member variables.
* *
@ -110,25 +97,6 @@ public class Waypoint {
immutablePropertiesList = Collections.unmodifiableList(createGeolocationProperties(attributeMap)); 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<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> 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. * Get the BlackboardArtifact that this waypoint represents.
* *
@ -209,7 +177,8 @@ public class Waypoint {
/** /**
* Returns the route that this waypoint is apart of . * 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() { public Route getRoute() {
return route; return route;

View File

@ -70,8 +70,8 @@ public final class WaypointBuilder {
+ " )"; + " )";
// Returns a list of artifacts with no time stamp // Returns a list of artifacts with no time stamp
final static String SELECT_WO_TIMESTAMP = final static String SELECT_WO_TIMESTAMP
"SELECT DISTINCT artifact_id, artifact_type_id " = "SELECT DISTINCT artifact_id, artifact_type_id "
+ "FROM blackboard_attributes " + "FROM blackboard_attributes "
+ "WHERE artifact_id NOT IN (%s) " + "WHERE artifact_id NOT IN (%s) "
+ "AND artifact_id IN (%s)"; //NON-NLS + "AND artifact_id IN (%s)"; //NON-NLS
@ -121,6 +121,25 @@ public final class WaypointBuilder {
return points; 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<Route> getRoutes(List<Waypoint> waypoints) {
List<Route> 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. * Gets a list of Waypoints for TSK_GPS_TRACKPOINT artifacts.
* *
@ -150,6 +169,25 @@ public final class WaypointBuilder {
return points; 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<Waypoint> getTrackpointWaypoints(List<Waypoint> waypoints) {
List<Waypoint> 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. * Gets a list of Waypoints for TSK_METADATA_EXIF artifacts.
* *
@ -183,6 +221,25 @@ public final class WaypointBuilder {
return points; 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<Waypoint> getEXIFWaypoints(List<Waypoint> waypoints) {
List<Waypoint> 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. * Gets a list of Waypoints for TSK_GPS_SEARCH artifacts.
* *
@ -214,6 +271,25 @@ public final class WaypointBuilder {
return points; 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<Waypoint> getSearchWaypoints(List<Waypoint> waypoints) {
List<Waypoint> 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. * Gets a list of Waypoints for TSK_GPS_LAST_KNOWN_LOCATION artifacts.
* *
@ -245,6 +321,26 @@ public final class WaypointBuilder {
return points; 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<Waypoint> getLastKnownWaypoints(List<Waypoint> waypoints) {
List<Waypoint> 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. * Gets a list of Waypoints for TSK_GPS_BOOKMARK artifacts.
* *
@ -266,7 +362,7 @@ public final class WaypointBuilder {
if (artifacts != null) { if (artifacts != null) {
for (BlackboardArtifact artifact : artifacts) { for (BlackboardArtifact artifact : artifacts) {
try { try {
Waypoint point = new Waypoint(artifact); Waypoint point = new BookmarkWaypoint(artifact);
points.add(point); points.add(point);
} catch (GeoLocationDataException ex) { } 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 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; 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<Waypoint> getBookmarkWaypoints(List<Waypoint> waypoints) {
List<Waypoint> specificPoints = new ArrayList<>();
for (Waypoint point : waypoints) {
if (point instanceof BookmarkWaypoint) {
specificPoints.add(point);
}
}
return specificPoints;
}
/** /**
* Get a filtered list of waypoints. * Get a filtered list of waypoints.
* *
@ -386,7 +502,7 @@ public final class WaypointBuilder {
String mostRecentQuery = ""; String mostRecentQuery = "";
if (!showAll && cntDaysFromRecent > 0) { 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, String.format(MOST_RECENT_TIME,
cntDaysFromRecent, cntDaysFromRecent,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
@ -464,7 +580,7 @@ public final class WaypointBuilder {
waypoints.add(new EXIFWaypoint(artifact)); waypoints.add(new EXIFWaypoint(artifact));
break; break;
case TSK_GPS_BOOKMARK: case TSK_GPS_BOOKMARK:
waypoints.add(new Waypoint(artifact)); waypoints.add(new BookmarkWaypoint(artifact));
break; break;
case TSK_GPS_TRACKPOINT: case TSK_GPS_TRACKPOINT:
waypoints.add(new TrackpointWaypoint(artifact)); waypoints.add(new TrackpointWaypoint(artifact));
@ -477,8 +593,7 @@ public final class WaypointBuilder {
waypoints.addAll(route.getRoute()); waypoints.addAll(route.getRoute());
break; break;
default: default:
waypoints.add(new Waypoint(artifact)); throw new GeoLocationDataException(String.format("Unable to create waypoint for artifact of type %s", type.toString()));
break;
} }
return waypoints; return waypoints;

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

View File

@ -33,6 +33,7 @@ import java.io.OutputStream;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.jdom2.Document; import org.jdom2.Document;
@ -59,7 +60,7 @@ import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Generates a KML file based on geospatial information from the BlackBoard. * 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 Logger logger = Logger.getLogger(KMLReport.class.getName());
private static final String KML_STYLE_FILE = "style.kml"; private static final String KML_STYLE_FILE = "style.kml";
@ -79,6 +80,8 @@ class KMLReport implements GeneralReportModule {
private Element gpsSearchesFolder; private Element gpsSearchesFolder;
private Element gpsTrackpointsFolder; private Element gpsTrackpointsFolder;
private List<Waypoint> waypointList = null;
private enum FeatureColor { private enum FeatureColor {
RED("style.kml#redFeature"), RED("style.kml#redFeature"),
GREEN("style.kml#greenFeature"), GREEN("style.kml#greenFeature"),
@ -141,6 +144,11 @@ class KMLReport implements GeneralReportModule {
"Route_Details_Header=GPS Route" "Route_Details_Header=GPS Route"
}) })
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel, List<Waypoint> waypointList) {
this.waypointList = waypointList;
generateReport(baseReportDir, progressPanel);
}
@Override @Override
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) { public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
try { try {
@ -298,7 +306,7 @@ class KMLReport implements GeneralReportModule {
* @throws IOException * @throws IOException
*/ */
void addExifMetadataContent(List<Waypoint> points, String baseReportDirectory) throws IOException { void addExifMetadataContent(List<Waypoint> points, String baseReportDirectory) throws IOException {
for(Waypoint point: points) { for (Waypoint point : points) {
Element mapPoint = makePoint(point); Element mapPoint = makePoint(point);
if (mapPoint == null) { if (mapPoint == null) {
return; return;
@ -332,23 +340,31 @@ class KMLReport implements GeneralReportModule {
* @throws IOException * @throws IOException
*/ */
void addLocationsToReport(SleuthkitCase skCase, String baseReportDir) throws GeoLocationDataException, IOException { void addLocationsToReport(SleuthkitCase skCase, String baseReportDir) throws GeoLocationDataException, IOException {
addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(skCase), baseReportDir); if (waypointList == null) {
addWaypoints(WaypointBuilder.getBookmarkWaypoints(skCase), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String()); addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(skCase), baseReportDir);
addWaypoints(WaypointBuilder.getLastKnownWaypoints(skCase), gpsLastKnownLocationFolder, FeatureColor.PURPLE, Bundle.Waypoint_Last_Known_Display_String()); addWaypoints(WaypointBuilder.getBookmarkWaypoints(skCase), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String());
addWaypoints(WaypointBuilder.getSearchWaypoints(skCase), gpsSearchesFolder, FeatureColor.WHITE, Bundle.Waypoint_Search_Display_String()); addWaypoints(WaypointBuilder.getLastKnownWaypoints(skCase), gpsLastKnownLocationFolder, FeatureColor.PURPLE, Bundle.Waypoint_Last_Known_Display_String());
addWaypoints(WaypointBuilder.getTrackpointWaypoints(skCase), gpsTrackpointsFolder, FeatureColor.WHITE, Bundle.Waypoint_Trackpoint_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 * For each point in the waypoint list an Element to represent the given
* is created and added it to the given Element folder. * waypoint is created and added it to the given Element folder.
* *
* @param points List of waypoints to add to the report * @param points List of waypoints to add to the report
* @param folder The Element folder to add the points to * @param folder The Element folder to add the points to
* @param waypointColor The color the waypoint should appear in the report * @param waypointColor The color the waypoint should appear in the report
*/ */
void addWaypoints(List<Waypoint> points, Element folder, FeatureColor waypointColor, String headerLabel) { void addWaypoints(List<Waypoint> 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()); addContent(folder, point.getLabel(), waypointColor, getFormattedDetails(point, headerLabel), point.getTimestamp(), makePoint(point), point.getLatitude(), point.getLongitude());
} }
} }
@ -356,17 +372,17 @@ class KMLReport implements GeneralReportModule {
/** /**
* Adds the waypoint Element with details to the report in the given folder. * Adds the waypoint Element with details to the report in the given folder.
* *
* @param folder Element folder to add the waypoint to * @param folder Element folder to add the waypoint to
* @param waypointLabel String waypoint Label * @param waypointLabel String waypoint Label
* @param waypointColor FeatureColor for the waypoint * @param waypointColor FeatureColor for the waypoint
* @param formattedDetails String HTML formatted waypoint details * @param formattedDetails String HTML formatted waypoint details
* @param timestamp Long timestamp (unix\jave epoch seconds) * @param timestamp Long timestamp (unix\jave epoch seconds)
* @param point Element point object * @param point Element point object
* @param latitude Double latitude value * @param latitude Double latitude value
* @param longitude Double longitude value * @param longitude Double longitude value
*/ */
void addContent(Element folder, String waypointLabel, FeatureColor waypointColor, String formattedDetails, Long timestamp, Element point, Double latitude, Double longitude) { 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); String formattedCords = formattedCoordinates(latitude, longitude);
folder.addContent(makePlacemark(waypointLabel, waypointColor, formattedDetails, timestamp, point, formattedCords)); folder.addContent(makePlacemark(waypointLabel, waypointColor, formattedDetails, timestamp, point, formattedCords));
} }
@ -380,10 +396,12 @@ class KMLReport implements GeneralReportModule {
* @throws TskCoreException * @throws TskCoreException
*/ */
void makeRoutes(SleuthkitCase skCase) throws GeoLocationDataException { void makeRoutes(SleuthkitCase skCase) throws GeoLocationDataException {
List<Route> routes = Route.getRoutes(skCase); List<Route> routes = null;
if(routes == null) { if (waypointList == null) {
return; routes = Route.getRoutes(skCase);
} else {
routes = new ArrayList<>();
} }
for (Route route : routes) { for (Route route : routes) {
@ -431,7 +449,7 @@ class KMLReport implements GeneralReportModule {
if (endingPoint != null) { if (endingPoint != null) {
gpsRouteFolder.addContent(makePlacemark(end.getLabel(), gpsRouteFolder.addContent(makePlacemark(end.getLabel(),
FeatureColor.GREEN, FeatureColor.GREEN,
getFormattedDetails(end, Bundle.Waypoint_Route_Point_Display_String()), getFormattedDetails(end, Bundle.Waypoint_Route_Point_Display_String()),
end.getTimestamp(), endingPoint, formattedEnd)); //NON-NLS end.getTimestamp(), endingPoint, formattedEnd)); //NON-NLS
} }
} }
@ -689,7 +707,7 @@ class KMLReport implements GeneralReportModule {
/** /**
* Get the nicely formatted details for the given waypoint. * Get the nicely formatted details for the given waypoint.
* *
* @param point Waypoint object * @param point Waypoint object
* @param header String details header * @param header String details header
* *
* @return HTML formatted String of details for given waypoint * @return HTML formatted String of details for given waypoint
@ -712,9 +730,9 @@ class KMLReport implements GeneralReportModule {
} }
List<Waypoint.Property> list = point.getOtherProperties(); List<Waypoint.Property> list = point.getOtherProperties();
for(Waypoint.Property prop: list) { for (Waypoint.Property prop : list) {
String value = prop.getValue(); String value = prop.getValue();
if(value != null && !value.isEmpty()) { if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value)); result.append(formatAttribute(prop.getDisplayName(), value));
} }
} }
@ -733,8 +751,7 @@ class KMLReport implements GeneralReportModule {
* *
* @return A HTML formatted list of the Route attributes * @return A HTML formatted list of the Route attributes
*/ */
private String getFormattedDetails(Route route) {
private String getFormattedDetails(Route route) {
List<Waypoint> points = route.getRoute(); List<Waypoint> points = route.getRoute();
StringBuilder result = new StringBuilder(); //NON-NLS StringBuilder result = new StringBuilder(); //NON-NLS
@ -754,7 +771,7 @@ class KMLReport implements GeneralReportModule {
.append(formatAttribute("Start Longitude", start.getLongitude().toString())); .append(formatAttribute("Start Longitude", start.getLongitude().toString()));
Double altitude = start.getAltitude(); Double altitude = start.getAltitude();
if(altitude != null) { if (altitude != null) {
result.append(formatAttribute("Start Altitude", altitude.toString())); result.append(formatAttribute("Start Altitude", altitude.toString()));
} }
@ -762,15 +779,15 @@ class KMLReport implements GeneralReportModule {
.append(formatAttribute("End Longitude", end.getLongitude().toString())); .append(formatAttribute("End Longitude", end.getLongitude().toString()));
altitude = end.getAltitude(); altitude = end.getAltitude();
if(altitude != null) { if (altitude != null) {
result.append(formatAttribute("End Altitude", altitude.toString())); result.append(formatAttribute("End Altitude", altitude.toString()));
} }
} }
List<Waypoint.Property> list = route.getOtherProperties(); List<Waypoint.Property> list = route.getOtherProperties();
for(Waypoint.Property prop: list) { for (Waypoint.Property prop : list) {
String value = prop.getValue(); String value = prop.getValue();
if(value != null && !value.isEmpty()) { if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value)); result.append(formatAttribute(prop.getDisplayName(), value));
} }
} }
@ -781,7 +798,7 @@ class KMLReport implements GeneralReportModule {
/** /**
* Helper functions for consistently formatting longitude and latitude. * Helper functions for consistently formatting longitude and latitude.
* *
* @param latitude Double latitude value * @param latitude Double latitude value
* @param longitude Double longitude value * @param longitude Double longitude value
* *
* @return String Nicely formatted double values separated by a comma * @return String Nicely formatted double values separated by a comma