19 package org.sleuthkit.autopsy.geolocation;
22 import java.awt.Color;
23 import java.awt.Graphics;
24 import java.awt.GridBagConstraints;
25 import java.awt.event.ActionListener;
26 import java.awt.image.BufferedImage;
27 import java.sql.ResultSet;
28 import java.sql.SQLException;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.List;
34 import java.util.concurrent.ExecutionException;
35 import java.util.logging.Level;
36 import javafx.util.Pair;
37 import javax.swing.Icon;
38 import javax.swing.ImageIcon;
39 import javax.swing.SpinnerNumberModel;
40 import javax.swing.SwingWorker;
41 import org.openide.util.NbBundle.Messages;
45 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
55 class GeoFilterPanel
extends javax.swing.JPanel {
57 final static String INITPROPERTY =
"FilterPanelInitCompleted";
59 private static final long serialVersionUID = 1L;
60 private static final Logger logger = Logger.getLogger(GeoFilterPanel.class.getName());
62 private final SpinnerNumberModel numberModel;
63 private final CheckBoxListPanel<DataSource> dsCheckboxPanel;
64 private final CheckBoxListPanel<ARTIFACT_TYPE> atCheckboxPanel;
67 @SuppressWarnings(
"deprecation")
68 private static final ARTIFACT_TYPE[] GPS_ARTIFACT_TYPES = {
69 ARTIFACT_TYPE.TSK_GPS_BOOKMARK,
70 ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION,
71 ARTIFACT_TYPE.TSK_GPS_ROUTE,
72 ARTIFACT_TYPE.TSK_GPS_SEARCH,
73 ARTIFACT_TYPE.TSK_GPS_TRACK,
74 ARTIFACT_TYPE.TSK_GPS_TRACKPOINT,
75 ARTIFACT_TYPE.TSK_METADATA_EXIF
82 "GeoFilterPanel_DataSource_List_Title=Data Sources",
83 "GeoFilterPanel_ArtifactType_List_Title=Types"
87 numberModel =
new SpinnerNumberModel(10, 1, Integer.MAX_VALUE, 1);
93 dsCheckboxPanel =
new CheckBoxListPanel<>();
94 dsCheckboxPanel.setPanelTitle(Bundle.GeoFilterPanel_DataSource_List_Title());
95 dsCheckboxPanel.setPanelTitleIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/image.png")));
96 dsCheckboxPanel.setSetAllSelected(
true);
98 atCheckboxPanel =
new CheckBoxListPanel<>();
99 atCheckboxPanel.setPanelTitle(Bundle.GeoFilterPanel_ArtifactType_List_Title());
100 atCheckboxPanel.setPanelTitleIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/extracted_content.png")));
101 atCheckboxPanel.setSetAllSelected(
true);
103 GridBagConstraints gridBagConstraints =
new GridBagConstraints();
104 gridBagConstraints.gridx = 0;
105 gridBagConstraints.gridy = 3;
106 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
107 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
108 gridBagConstraints.weightx = 1.0;
109 gridBagConstraints.weighty = 1.0;
110 gridBagConstraints.insets =
new java.awt.Insets(0, 15, 0, 15);
111 add(dsCheckboxPanel, gridBagConstraints);
113 gridBagConstraints =
new GridBagConstraints();
114 gridBagConstraints.gridx = 0;
115 gridBagConstraints.gridy = 4;
116 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
117 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
118 gridBagConstraints.weightx = 1.0;
119 gridBagConstraints.weighty = 1.0;
120 gridBagConstraints.insets =
new java.awt.Insets(0, 15, 0, 15);
121 add(atCheckboxPanel, gridBagConstraints);
125 public void setEnabled(
boolean enabled) {
126 applyButton.setEnabled(enabled);
127 mostRecentButton.setEnabled(enabled);
128 allButton.setEnabled(enabled);
129 showWaypointsWOTSCheckBox.setEnabled(enabled && mostRecentButton.isSelected());
130 dsCheckboxPanel.setEnabled(enabled);
131 atCheckboxPanel.setEnabled(enabled);
132 daysLabel.setEnabled(enabled);
133 daysSpinner.setEnabled(enabled);
139 void updateDataSourceList() {
140 DataSourceUpdater updater =
new DataSourceUpdater();
147 void clearDataSourceList() {
148 dsCheckboxPanel.clearList();
149 atCheckboxPanel.clearList();
152 boolean hasDataSources() {
153 return !dsCheckboxPanel.isEmpty();
161 void addActionListener(ActionListener listener) {
162 applyButton.addActionListener(listener);
173 "GeoFilterPanel_empty_dataSource=Unable to apply filter, please select one or more data sources.",
174 "GeoFilterPanel_empty_artifactType=Unable to apply filter, please select one or more artifact types."
176 GeoFilter getFilterState() throws GeoLocationUIException {
177 List<DataSource> dataSources = dsCheckboxPanel.getSelectedElements();
178 if (dataSources.isEmpty()) {
179 throw new GeoLocationUIException(Bundle.GeoFilterPanel_empty_dataSource());
182 List<ARTIFACT_TYPE> artifactTypes = atCheckboxPanel.getSelectedElements();
183 if (artifactTypes.isEmpty()) {
184 throw new GeoLocationUIException(Bundle.GeoFilterPanel_empty_artifactType());
186 return new GeoFilter(allButton.isSelected(),
187 showWaypointsWOTSCheckBox.isSelected(),
188 numberModel.getNumber().intValue(),
197 private void updateWaypointOptions() {
198 boolean selected = mostRecentButton.isSelected();
199 showWaypointsWOTSCheckBox.setEnabled(selected);
200 daysSpinner.setEnabled(selected);
208 @SuppressWarnings(
"unchecked")
210 private
void initComponents() {
211 java.awt.GridBagConstraints gridBagConstraints;
213 javax.swing.ButtonGroup buttonGroup =
new javax.swing.ButtonGroup();
214 javax.swing.JPanel waypointSettings =
new javax.swing.JPanel();
215 allButton =
new javax.swing.JRadioButton();
216 mostRecentButton =
new javax.swing.JRadioButton();
217 showWaypointsWOTSCheckBox =
new javax.swing.JCheckBox();
218 daysSpinner =
new javax.swing.JSpinner(numberModel);
219 daysLabel =
new javax.swing.JLabel();
220 showLabel =
new javax.swing.JLabel();
221 javax.swing.JPanel buttonPanel =
new javax.swing.JPanel();
222 applyButton =
new javax.swing.JButton();
223 javax.swing.JLabel optionsLabel =
new javax.swing.JLabel();
225 setLayout(
new java.awt.GridBagLayout());
227 waypointSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.waypointSettings.border.title")));
228 waypointSettings.setLayout(
new java.awt.GridBagLayout());
230 buttonGroup.add(allButton);
231 allButton.setSelected(
true);
232 org.openide.awt.Mnemonics.setLocalizedText(allButton,
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.allButton.text"));
233 allButton.addActionListener(
new java.awt.event.ActionListener() {
234 public void actionPerformed(java.awt.event.ActionEvent evt) {
235 allButtonActionPerformed(evt);
238 gridBagConstraints =
new java.awt.GridBagConstraints();
239 gridBagConstraints.gridx = 0;
240 gridBagConstraints.gridy = 1;
241 gridBagConstraints.gridwidth = 4;
242 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
243 gridBagConstraints.weightx = 1.0;
244 waypointSettings.add(allButton, gridBagConstraints);
246 buttonGroup.add(mostRecentButton);
247 org.openide.awt.Mnemonics.setLocalizedText(mostRecentButton,
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.mostRecentButton.text"));
248 mostRecentButton.addActionListener(
new java.awt.event.ActionListener() {
249 public void actionPerformed(java.awt.event.ActionEvent evt) {
250 mostRecentButtonActionPerformed(evt);
253 gridBagConstraints =
new java.awt.GridBagConstraints();
254 gridBagConstraints.gridx = 0;
255 gridBagConstraints.gridy = 2;
256 gridBagConstraints.gridwidth = 2;
257 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
258 waypointSettings.add(mostRecentButton, gridBagConstraints);
260 org.openide.awt.Mnemonics.setLocalizedText(showWaypointsWOTSCheckBox,
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.showWaypointsWOTSCheckBox.text"));
261 showWaypointsWOTSCheckBox.setEnabled(
false);
262 gridBagConstraints =
new java.awt.GridBagConstraints();
263 gridBagConstraints.gridx = 1;
264 gridBagConstraints.gridy = 3;
265 gridBagConstraints.gridwidth = 3;
266 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
267 gridBagConstraints.insets =
new java.awt.Insets(0, -20, 0, 5);
268 waypointSettings.add(showWaypointsWOTSCheckBox, gridBagConstraints);
270 daysSpinner.setEnabled(
false);
271 daysSpinner.setPreferredSize(
new java.awt.Dimension(75, 26));
272 gridBagConstraints =
new java.awt.GridBagConstraints();
273 gridBagConstraints.gridx = 2;
274 gridBagConstraints.gridy = 2;
275 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
276 waypointSettings.add(daysSpinner, gridBagConstraints);
278 org.openide.awt.Mnemonics.setLocalizedText(daysLabel,
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.daysLabel.text"));
279 gridBagConstraints =
new java.awt.GridBagConstraints();
280 gridBagConstraints.gridx = 3;
281 gridBagConstraints.gridy = 2;
282 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
283 gridBagConstraints.weightx = 1.0;
284 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 0, 5);
285 waypointSettings.add(daysLabel, gridBagConstraints);
287 org.openide.awt.Mnemonics.setLocalizedText(showLabel,
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.showLabel.text"));
288 showLabel.setToolTipText(
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.showLabel.toolTipText"));
289 gridBagConstraints =
new java.awt.GridBagConstraints();
290 gridBagConstraints.gridx = 0;
291 gridBagConstraints.gridy = 0;
292 gridBagConstraints.insets =
new java.awt.Insets(0, 5, 0, 0);
293 waypointSettings.add(showLabel, gridBagConstraints);
295 gridBagConstraints =
new java.awt.GridBagConstraints();
296 gridBagConstraints.gridx = 0;
297 gridBagConstraints.gridy = 2;
298 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
299 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
300 gridBagConstraints.weightx = 1.0;
301 gridBagConstraints.insets =
new java.awt.Insets(5, 15, 9, 15);
302 add(waypointSettings, gridBagConstraints);
304 buttonPanel.setLayout(
new java.awt.GridBagLayout());
306 applyButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/tick.png")));
307 org.openide.awt.Mnemonics.setLocalizedText(applyButton,
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.applyButton.text"));
308 gridBagConstraints =
new java.awt.GridBagConstraints();
309 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
310 gridBagConstraints.weightx = 1.0;
311 buttonPanel.add(applyButton, gridBagConstraints);
313 gridBagConstraints =
new java.awt.GridBagConstraints();
314 gridBagConstraints.gridx = 0;
315 gridBagConstraints.gridy = 0;
316 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
317 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
318 gridBagConstraints.weightx = 1.0;
319 gridBagConstraints.insets =
new java.awt.Insets(9, 15, 0, 15);
320 add(buttonPanel, gridBagConstraints);
322 optionsLabel.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/blueGeo16.png")));
323 org.openide.awt.Mnemonics.setLocalizedText(optionsLabel,
org.openide.util.NbBundle.getMessage(GeoFilterPanel.class,
"GeoFilterPanel.optionsLabel.text"));
324 gridBagConstraints =
new java.awt.GridBagConstraints();
325 gridBagConstraints.gridx = 0;
326 gridBagConstraints.gridy = 1;
327 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
328 gridBagConstraints.insets =
new java.awt.Insets(0, 15, 0, 0);
329 add(optionsLabel, gridBagConstraints);
332 private void allButtonActionPerformed(java.awt.event.ActionEvent evt) {
333 updateWaypointOptions();
336 private void mostRecentButtonActionPerformed(java.awt.event.ActionEvent evt) {
337 updateWaypointOptions();
342 private javax.swing.JRadioButton allButton;
343 private javax.swing.JButton applyButton;
344 private javax.swing.JLabel daysLabel;
345 private javax.swing.JSpinner daysSpinner;
346 private javax.swing.JRadioButton mostRecentButton;
347 private javax.swing.JLabel showLabel;
348 private javax.swing.JCheckBox showWaypointsWOTSCheckBox;
354 final class GeoFilter {
356 private final boolean showAll;
357 private final boolean showWithoutTimeStamp;
358 private final int mostRecentNumDays;
359 private final List<DataSource> dataSources;
360 private final List<ARTIFACT_TYPE> artifactTypes;
380 GeoFilter(
boolean showAll,
boolean withoutTimeStamp,
381 int mostRecentNumDays, List<DataSource> dataSources,
382 List<ARTIFACT_TYPE> artifactTypes) {
383 this.showAll = showAll;
384 this.showWithoutTimeStamp = withoutTimeStamp;
385 this.mostRecentNumDays = mostRecentNumDays;
386 this.dataSources = dataSources;
387 this.artifactTypes = artifactTypes;
395 boolean showAllWaypoints() {
406 boolean showWaypointsWithoutTimeStamp() {
407 return showWithoutTimeStamp;
416 int getMostRecentNumDays() {
417 return mostRecentNumDays;
427 List<DataSource> getDataSources() {
428 return Collections.unmodifiableList(dataSources);
438 List<ARTIFACT_TYPE> getArtifactTypes() {
439 return Collections.unmodifiableList(artifactTypes);
449 final List<Pair<String, DataSource>> dataSources;
450 final Map<ARTIFACT_TYPE, Long> artifactTypes;
452 private Sources(List<Pair<String, DataSource>> dataSources,
453 Map<ARTIFACT_TYPE, Long> artifactTypes) {
454 this.dataSources = dataSources;
455 this.artifactTypes = artifactTypes;
470 List<Pair<String, DataSource>> validSources =
new ArrayList<>();
471 HashMap<ARTIFACT_TYPE, Long> atCountsTotal =
new HashMap<>();
473 for (DataSource dataSource : sleuthkitCase.getDataSources()) {
474 Map<ARTIFACT_TYPE, Long> atCounts =
getGPSDataSources(sleuthkitCase, dataSource);
475 if (!atCounts.isEmpty()) {
476 for (Map.Entry<ARTIFACT_TYPE, Long> entry : atCounts.entrySet()) {
477 atCountsTotal.putIfAbsent(entry.getKey(), 0L);
478 atCountsTotal.put(entry.getKey(), atCountsTotal.get(entry.getKey()) + entry.getValue());
480 String dsName = sleuthkitCase.getContentById(dataSource.getId()).getName();
481 Pair<String, DataSource> pair =
new Pair<>(dsName, dataSource);
482 validSources.add(pair);
485 return new Sources(validSources, atCountsTotal);
501 DataSource dataSource, BlackboardArtifact.ARTIFACT_TYPE artifactType) throws TskCoreException {
504 =
"SELECT count(DISTINCT artifact_id) AS count FROM"
506 +
" SELECT * FROM blackboard_artifacts as arts"
507 +
" INNER JOIN blackboard_attributes as attrs"
508 +
" ON attrs.artifact_id = arts.artifact_id"
509 +
" WHERE arts.artifact_type_id = " + artifactType.getTypeID()
510 +
" AND arts.data_source_obj_id = " + dataSource.getId()
511 +
" AND arts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()
514 +
"attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()
515 +
" or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()
516 +
" or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS.getTypeID()
517 +
" or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS.getTypeID()
520 try (SleuthkitCase.CaseDbQuery queryResult = sleuthkitCase.executeQuery(queryStr);
521 ResultSet resultSet = queryResult.getResultSet()) {
522 if (resultSet.next()) {
523 count = resultSet.getLong(
"count");
525 }
catch (SQLException ex) {
526 Throwable cause = ex.getCause();
528 logger.log(Level.SEVERE, cause.getMessage(), cause);
530 logger.log(Level.SEVERE, ex.getMessage(), ex);
547 private Map<ARTIFACT_TYPE, Long>
getGPSDataSources(SleuthkitCase sleuthkitCase, DataSource dataSource)
throws TskCoreException {
548 HashMap<ARTIFACT_TYPE, Long> ret =
new HashMap<>();
549 for (BlackboardArtifact.ARTIFACT_TYPE type : GPS_ARTIFACT_TYPES) {
552 ret.put(type, count);
567 Color color = MapWaypoint.getColor(artifactTypeId);
568 BufferedImage img =
new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
570 Graphics g = img.createGraphics();
572 g.fillRect(0, 0, 16, 16);
575 return new ImageIcon(img);
583 }
catch (InterruptedException | ExecutionException ex) {
584 Throwable cause = ex.getCause();
586 logger.log(Level.SEVERE, cause.getMessage(), cause);
588 logger.log(Level.SEVERE, ex.getMessage(), ex);
592 if (sources != null) {
593 for (Pair<String, DataSource> source : sources.dataSources) {
594 dsCheckboxPanel.addElement(source.getKey(), null, source.getValue());
596 for (Map.Entry<ARTIFACT_TYPE, Long> entry : sources.artifactTypes.entrySet()) {
597 String dispName = entry.getKey().getDisplayName() +
" (" + entry.getValue() +
")";
599 atCheckboxPanel.addElement(dispName, icon, entry.getKey());
603 GeoFilterPanel.this.firePropertyChange(INITPROPERTY,
false,
true);
Map< ARTIFACT_TYPE, Long > getGPSDataSources(SleuthkitCase sleuthkitCase, DataSource dataSource)
long getGPSDataCount(SleuthkitCase sleuthkitCase, DataSource dataSource, BlackboardArtifact.ARTIFACT_TYPE artifactType)
Sources(List< Pair< String, DataSource >> dataSources, Map< ARTIFACT_TYPE, Long > artifactTypes)
SleuthkitCase getSleuthkitCase()
static Case getCurrentCase()
ImageIcon getImageIcon(int artifactTypeId)