diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 8358dd7d34..15bc46a8da 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -75,6 +75,7 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; +import org.sleuthkit.autopsy.datamodel.utils.IconsUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR; import org.sleuthkit.autopsy.texttranslation.TextTranslationService; @@ -270,7 +271,7 @@ public class BlackboardArtifactNode extends AbstractContentNode 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.datamodel.utils; + +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; + +/** + * Utility methods for handling icons + */ +public final class IconsUtil { + private IconsUtil() { + + } + + @SuppressWarnings("deprecation") + public static String getIconFilePath(int typeID) { + String imageFile; + if (typeID == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()) { + imageFile = "bookmarks.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()) { + imageFile = "cookies.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) { + imageFile = "history.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) { + imageFile = "downloads.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID()) { + imageFile = "recent_docs.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID()) { + imageFile = "gps_trackpoint.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) { + imageFile = "programs.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) { + imageFile = "usb_devices.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) { + imageFile = "mail-icon-16.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_EXTRACTED_TEXT.getTypeID()) { + imageFile = "text-file.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { + imageFile = "searchquery.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) { + imageFile = "camera-icon-16.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_OS_INFO.getTypeID()) { + imageFile = "computer.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID()) { + imageFile = "account-icon-16.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) { + imageFile = "contact.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { + imageFile = "message.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) { + imageFile = "calllog.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_CALENDAR_ENTRY.getTypeID()) { + imageFile = "calendar.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY.getTypeID()) { + imageFile = "speeddialentry.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID()) { + imageFile = "bluetooth.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID()) { + imageFile = "gpsfav.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID()) { + imageFile = "gps-lastlocation.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID()) { + imageFile = "gps-search.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID()) { + imageFile = "installed.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() + || typeID == ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED.getTypeID()) { + imageFile = "encrypted-file.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) { + imageFile = "mismatch-16.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID()) { + imageFile = "gps_trackpoint.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_REMOTE_DRIVE.getTypeID()) { + imageFile = "drive_network.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_FACE_DETECTED.getTypeID()) { + imageFile = "face.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) { + imageFile = "network-wifi.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID()) { + imageFile = "network-wifi.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()) { + imageFile = "sim_card.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID()) { + imageFile = "Bluetooth.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID()) { + imageFile = "devices.png"; //NON-NLS + } else if (typeID == ARTIFACT_TYPE.TSK_VERIFICATION_FAILED.getTypeID()) { + imageFile = "validationFailed.png"; //NON-NLS + } else { + imageFile = "artifact-icon.png"; //NON-NLS + } + return "/org/sleuthkit/autopsy/images/" + imageFile; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java index 590b0f40a0..bc56968f99 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java @@ -28,6 +28,7 @@ import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.autopsy.geolocation.datamodel.Track; import org.sleuthkit.autopsy.geolocation.datamodel.Waypoint; import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; /** * The business logic for filtering waypoints. @@ -60,6 +61,7 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter Case currentCase = Case.getCurrentCase(); WaypointBuilder.getAllWaypoints(currentCase.getSleuthkitCase(), filters.getDataSources(), + filters.getArtifactTypes(), filters.showAllWaypoints(), filters.getMostRecentNumDays(), filters.showWaypointsWithoutTimeStamp(), @@ -77,12 +79,13 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter @Override public void process(List waypoints) { - List tracks = null; - try { - tracks = Track.getTracks(Case.getCurrentCase().getSleuthkitCase(), filters.getDataSources()); - } catch (GeoLocationDataException ex) { - logger.log(Level.WARNING, "Exception thrown while retrieving list of Tracks", ex); + if (filters.getArtifactTypes().contains(ARTIFACT_TYPE.TSK_GPS_TRACK)) { + try { + tracks = Track.getTracks(Case.getCurrentCase().getSleuthkitCase(), filters.getDataSources()); + } catch (GeoLocationDataException ex) { + logger.log(Level.WARNING, "Exception thrown while retrieving list of Tracks", ex); + } } List completeList = createWaypointList(waypoints, tracks); diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties index 338a91cdb1..1ee80973b3 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties @@ -7,15 +7,15 @@ RefreshPanel.closeButton.text= WaypointDetailPanel.closeButton.text= WaypointDetailPanel.imageLabel.text= GeoFilterPanel.waypointSettings.border.title= -GeoFilterPanel.allButton.text=Show All -GeoFilterPanel.mostRecentButton.text=Show only last +GeoFilterPanel.allButton.text=All +GeoFilterPanel.mostRecentButton.text=Only last GeoFilterPanel.applyButton.text=Apply GeoFilterPanel.showWaypointsWOTSCheckBox.text=Include waypoints with no time stamps GeoFilterPanel.daysLabel.text=days of activity CheckBoxListPanel.titleLabel.text=jLabel1 CheckBoxListPanel.checkButton.text=Check All CheckBoxListPanel.uncheckButton.text=Uncheck All -GeoFilterPanel.optionsLabel.text=Waypoints +GeoFilterPanel.optionsLabel.text=Dates OptionsCategory_Name_Geolocation=Geolocation OptionsCategory_Keywords_Geolocation=Geolocation Settings GeolocationSettingsPanel.tilePane.border.title=Map Tile Data Source @@ -37,3 +37,5 @@ GeolocationTopComponent.reportButton.text=KML Report GeolocationTopComponent.coordLabel.text= MapPanel.zoomInBtn.text= MapPanel.zoomOutBtn.text= +GeoFilterPanel.showLabel.text=Show: +GeoFilterPanel.showLabel.toolTipText=Show: diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED index e5bf351edb..a27f92c887 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED @@ -1,8 +1,10 @@ CTL_OpenGeolocation=Geolocation CTL_GeolocationTopComponentAction=GeolocationTopComponent CTL_GeolocationTopComponent=Geolocation +GeoFilterPanel_ArtifactType_List_Title=Types GeoFilterPanel_DataSource_List_Title=Data Sources -GeoFilterPanel_empty_dataSource=Data Source list is empty. +GeoFilterPanel_empty_artifactType=Unable to apply filter, please select one or more artifact types. +GeoFilterPanel_empty_dataSource=Unable to apply filter, please select one or more data sources. GeolocationSettings_mbtile_does_not_exist_message=The file supplied does not exist.\nPlease verify that the file exists and try again. GeolocationSettings_mbtile_does_not_exist_title=File Not Found GeolocationSettings_mbtile_not_valid_message=The supplied file is not a raster tile file. @@ -44,15 +46,15 @@ RefreshPanel.closeButton.text= WaypointDetailPanel.closeButton.text= WaypointDetailPanel.imageLabel.text= GeoFilterPanel.waypointSettings.border.title= -GeoFilterPanel.allButton.text=Show All -GeoFilterPanel.mostRecentButton.text=Show only last +GeoFilterPanel.allButton.text=All +GeoFilterPanel.mostRecentButton.text=Only last GeoFilterPanel.applyButton.text=Apply GeoFilterPanel.showWaypointsWOTSCheckBox.text=Include waypoints with no time stamps GeoFilterPanel.daysLabel.text=days of activity CheckBoxListPanel.titleLabel.text=jLabel1 CheckBoxListPanel.checkButton.text=Check All CheckBoxListPanel.uncheckButton.text=Uncheck All -GeoFilterPanel.optionsLabel.text=Waypoints +GeoFilterPanel.optionsLabel.text=Dates OptionsCategory_Name_Geolocation=Geolocation OptionsCategory_Keywords_Geolocation=Geolocation Settings GeolocationSettingsPanel.tilePane.border.title=Map Tile Data Source @@ -74,4 +76,6 @@ GeolocationTopComponent.reportButton.text=KML Report GeolocationTopComponent.coordLabel.text= MapPanel.zoomInBtn.text= MapPanel.zoomOutBtn.text= +GeoFilterPanel.showLabel.text=Show: +GeoFilterPanel.showLabel.toolTipText=Show: WaypointExtractAction_label=Extract Files(s) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxJList.java b/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxJList.java index 2f4247f3e6..7763d1a19a 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxJList.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxJList.java @@ -18,11 +18,15 @@ */ package org.sleuthkit.autopsy.geolocation; +import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import javax.swing.Icon; import javax.swing.JCheckBox; +import javax.swing.JLabel; import javax.swing.JList; +import javax.swing.JPanel; import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; @@ -60,6 +64,20 @@ final class CheckBoxJList extends JLis * @return */ String getDisplayName(); + + /** + * Returns whether an icon has been configured for this item + * + * @return + */ + boolean hasIcon(); + + /** + * Returns Icon to display next to the checkbox + * + * @return + */ + Icon getIcon(); } /** @@ -73,7 +91,9 @@ final class CheckBoxJList extends JLis * Do all of the UI initialization. */ private void initalize() { - setCellRenderer(new CellRenderer()); + CellRenderer cellRenderer = new CellRenderer(); + cellRenderer.init(); + setCellRenderer(cellRenderer); addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { @@ -91,18 +111,35 @@ final class CheckBoxJList extends JLis /** * A ListCellRenderer that renders list elements as check boxes. */ - class CellRenderer extends JCheckBox implements ListCellRenderer { + class CellRenderer extends JPanel implements ListCellRenderer { private static final long serialVersionUID = 1L; + private final JCheckBox checkbox = new JCheckBox(); + private final JLabel label = new JLabel(); + + public void init() { + setLayout(new BorderLayout(2, 0)); + add(checkbox, BorderLayout.WEST); + add(label, BorderLayout.CENTER); + } + @Override public Component getListCellRendererComponent( JList list, CheckBoxJList.CheckboxListItem value, int index, boolean isSelected, boolean cellHasFocus) { setBackground(list.getBackground()); - setSelected(value.isChecked()); - setText(value.getDisplayName()); + + checkbox.setSelected(value.isChecked()); + checkbox.setBackground(list.getBackground()); + checkbox.setEnabled(list.isEnabled()); + label.setText(value.getDisplayName()); + label.setEnabled(list.isEnabled()); + if (value.hasIcon()) { + label.setIcon(value.getIcon()); + } + setEnabled(list.isEnabled()); return this; } diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java index 49dfadaacb..bf74ba1a56 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/CheckBoxListPanel.java @@ -52,8 +52,8 @@ final class CheckBoxListPanel extends javax.swing.JPanel { * @param displayName display name for the checkbox * @param obj Object that the checkbox represents */ - void addElement(String displayName, T obj) { - ObjectCheckBox newCheckBox = new ObjectCheckBox<>(displayName, true, obj); + void addElement(String displayName, Icon icon, T obj) { + ObjectCheckBox newCheckBox = new ObjectCheckBox<>(displayName, icon, true, obj); if(!model.contains(newCheckBox)) { model.addElement(newCheckBox); @@ -220,17 +220,20 @@ final class CheckBoxListPanel extends javax.swing.JPanel { private final T object; private final String displayName; + private final Icon icon; private boolean checked; /** * Constructs a new ObjectCheckBox * * @param displayName String to show as the check box label + * @param icon Icon to show before the check box (may be null) * @param initialState Sets the initial state of the check box * @param object Object that the check box represents. */ - ObjectCheckBox(String displayName, boolean initialState, T object) { + ObjectCheckBox(String displayName, Icon icon, boolean initialState, T object) { this.displayName = displayName; + this.icon = icon; this.object = object; this.checked = initialState; } @@ -254,6 +257,16 @@ final class CheckBoxListPanel extends javax.swing.JPanel { return displayName; } + @Override + public boolean hasIcon() { + return icon != null; + } + + @Override + public Icon getIcon() { + return icon; + } + @Override public boolean equals(Object obj) { if(obj instanceof ObjectCheckBox) { diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.form b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.form index 843676578e..f19020d8c6 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.form +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.form @@ -61,7 +61,7 @@ - + @@ -79,7 +79,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -108,7 +108,7 @@ - + @@ -120,7 +120,22 @@ - + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java index cca9382e51..213f7fe188 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java @@ -22,17 +22,22 @@ import java.awt.GridBagConstraints; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javafx.util.Pair; +import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.SpinnerNumberModel; import javax.swing.SwingWorker; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.utils.IconsUtil; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -49,24 +54,27 @@ class GeoFilterPanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(GeoFilterPanel.class.getName()); private final SpinnerNumberModel numberModel; - private final CheckBoxListPanel checkboxPanel; + private final CheckBoxListPanel dsCheckboxPanel; + private final CheckBoxListPanel atCheckboxPanel; - // Make sure to update if + // Make sure to update if other GPS artifacts are added @SuppressWarnings("deprecation") - private static final BlackboardArtifact.ARTIFACT_TYPE[] GPS_ARTIFACT_TYPES = { - BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK, - BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION, - BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE, - BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH, - BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK, - BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT + private static final ARTIFACT_TYPE[] GPS_ARTIFACT_TYPES = { + ARTIFACT_TYPE.TSK_GPS_BOOKMARK, + ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION, + ARTIFACT_TYPE.TSK_GPS_ROUTE, + ARTIFACT_TYPE.TSK_GPS_SEARCH, + ARTIFACT_TYPE.TSK_GPS_TRACK, + ARTIFACT_TYPE.TSK_GPS_TRACKPOINT, + ARTIFACT_TYPE.TSK_METADATA_EXIF }; /** * Creates new GeoFilterPanel */ @Messages({ - "GeoFilterPanel_DataSource_List_Title=Data Sources" + "GeoFilterPanel_DataSource_List_Title=Data Sources", + "GeoFilterPanel_ArtifactType_List_Title=Types" }) GeoFilterPanel() { // numberModel is used in initComponents @@ -76,10 +84,15 @@ class GeoFilterPanel extends javax.swing.JPanel { // The gui builder cannot handle using CheckBoxListPanel due to its // use of generics so we will initalize it here. - checkboxPanel = new CheckBoxListPanel<>(); - checkboxPanel.setPanelTitle(Bundle.GeoFilterPanel_DataSource_List_Title()); - checkboxPanel.setPanelTitleIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/image.png"))); - checkboxPanel.setSetAllSelected(true); + dsCheckboxPanel = new CheckBoxListPanel<>(); + dsCheckboxPanel.setPanelTitle(Bundle.GeoFilterPanel_DataSource_List_Title()); + dsCheckboxPanel.setPanelTitleIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/image.png"))); + dsCheckboxPanel.setSetAllSelected(true); + + atCheckboxPanel = new CheckBoxListPanel<>(); + atCheckboxPanel.setPanelTitle(Bundle.GeoFilterPanel_ArtifactType_List_Title()); + atCheckboxPanel.setPanelTitleIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/extracted_content.png"))); + atCheckboxPanel.setSetAllSelected(true); GridBagConstraints gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -89,7 +102,17 @@ class GeoFilterPanel extends javax.swing.JPanel { gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 15); - add(checkboxPanel, gridBagConstraints); + add(dsCheckboxPanel, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 15); + add(atCheckboxPanel, gridBagConstraints); } @Override @@ -98,7 +121,8 @@ class GeoFilterPanel extends javax.swing.JPanel { mostRecentButton.setEnabled(enabled); allButton.setEnabled(enabled); showWaypointsWOTSCheckBox.setEnabled(enabled && mostRecentButton.isSelected()); - checkboxPanel.setEnabled(enabled); + dsCheckboxPanel.setEnabled(enabled); + atCheckboxPanel.setEnabled(enabled); daysLabel.setEnabled(enabled); daysSpinner.setEnabled(enabled); } @@ -115,11 +139,12 @@ class GeoFilterPanel extends javax.swing.JPanel { * Clears the data source list. */ void clearDataSourceList() { - checkboxPanel.clearList(); + dsCheckboxPanel.clearList(); + atCheckboxPanel.clearList(); } boolean hasDataSources() { - return !checkboxPanel.isEmpty(); + return !dsCheckboxPanel.isEmpty(); } /** @@ -139,18 +164,24 @@ class GeoFilterPanel extends javax.swing.JPanel { * @throws GeoLocationUIException */ @Messages({ - "GeoFilterPanel_empty_dataSource=Data Source list is empty." + "GeoFilterPanel_empty_dataSource=Unable to apply filter, please select one or more data sources.", + "GeoFilterPanel_empty_artifactType=Unable to apply filter, please select one or more artifact types." }) GeoFilter getFilterState() throws GeoLocationUIException { - List dataSources = checkboxPanel.getSelectedElements(); - + List dataSources = dsCheckboxPanel.getSelectedElements(); if (dataSources.isEmpty()) { throw new GeoLocationUIException(Bundle.GeoFilterPanel_empty_dataSource()); } + + List artifactTypes = atCheckboxPanel.getSelectedElements(); + if (artifactTypes.isEmpty()) { + throw new GeoLocationUIException(Bundle.GeoFilterPanel_empty_artifactType()); + } return new GeoFilter(allButton.isSelected(), showWaypointsWOTSCheckBox.isSelected(), numberModel.getNumber().intValue(), - dataSources); + dataSources, + artifactTypes); } /** @@ -180,6 +211,7 @@ class GeoFilterPanel extends javax.swing.JPanel { showWaypointsWOTSCheckBox = new javax.swing.JCheckBox(); daysSpinner = new javax.swing.JSpinner(numberModel); daysLabel = new javax.swing.JLabel(); + showLabel = new javax.swing.JLabel(); javax.swing.JPanel buttonPanel = new javax.swing.JPanel(); applyButton = new javax.swing.JButton(); javax.swing.JLabel optionsLabel = new javax.swing.JLabel(); @@ -199,7 +231,7 @@ class GeoFilterPanel extends javax.swing.JPanel { }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; + gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; @@ -214,40 +246,46 @@ class GeoFilterPanel extends javax.swing.JPanel { }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; + gridBagConstraints.gridy = 2; gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0); waypointSettings.add(mostRecentButton, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(showWaypointsWOTSCheckBox, org.openide.util.NbBundle.getMessage(GeoFilterPanel.class, "GeoFilterPanel.showWaypointsWOTSCheckBox.text")); // NOI18N showWaypointsWOTSCheckBox.setEnabled(false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; + gridBagConstraints.gridy = 3; gridBagConstraints.gridwidth = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(0, 30, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(0, -20, 0, 5); waypointSettings.add(showWaypointsWOTSCheckBox, gridBagConstraints); daysSpinner.setEnabled(false); daysSpinner.setPreferredSize(new java.awt.Dimension(75, 26)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; + gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0); waypointSettings.add(daysSpinner, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(daysLabel, org.openide.util.NbBundle.getMessage(GeoFilterPanel.class, "GeoFilterPanel.daysLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 3; - gridBagConstraints.gridy = 1; + gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(9, 5, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5); waypointSettings.add(daysLabel, gridBagConstraints); + org.openide.awt.Mnemonics.setLocalizedText(showLabel, org.openide.util.NbBundle.getMessage(GeoFilterPanel.class, "GeoFilterPanel.showLabel.text")); // NOI18N + showLabel.setToolTipText(org.openide.util.NbBundle.getMessage(GeoFilterPanel.class, "GeoFilterPanel.showLabel.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + waypointSettings.add(showLabel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; @@ -300,6 +338,7 @@ class GeoFilterPanel extends javax.swing.JPanel { private javax.swing.JLabel daysLabel; private javax.swing.JSpinner daysSpinner; private javax.swing.JRadioButton mostRecentButton; + private javax.swing.JLabel showLabel; private javax.swing.JCheckBox showWaypointsWOTSCheckBox; // End of variables declaration//GEN-END:variables @@ -312,6 +351,7 @@ class GeoFilterPanel extends javax.swing.JPanel { private final boolean showWithoutTimeStamp; private final int mostRecentNumDays; private final List dataSources; + private final List artifactTypes; /** * Construct a Geolocation filter. showAll and mostRecentNumDays are @@ -332,12 +372,17 @@ class GeoFilterPanel extends javax.swing.JPanel { * showAll is true. * @param dataSources A list of dataSources to filter waypoint * for. + * @param artifactTypes A list of artifactTypes to filter waypoint + * for. */ - GeoFilter(boolean showAll, boolean withoutTimeStamp, int mostRecentNumDays, List dataSources) { + GeoFilter(boolean showAll, boolean withoutTimeStamp, + int mostRecentNumDays, List dataSources, + List artifactTypes) { this.showAll = showAll; this.showWithoutTimeStamp = withoutTimeStamp; this.mostRecentNumDays = mostRecentNumDays; this.dataSources = dataSources; + this.artifactTypes = artifactTypes; } /** @@ -380,6 +425,31 @@ class GeoFilterPanel extends javax.swing.JPanel { List getDataSources() { return Collections.unmodifiableList(dataSources); } + + /** + * Returns a list of artifact types to filter the waypoints by, or null + * if all types should be include. + * + * @return A list of artifactTypes or null if all artifactTypes should + * be included. + */ + List getArtifactTypes() { + return Collections.unmodifiableList(artifactTypes); + } + } + + /** + * Container for data sources and artifact types to be given as filter options + */ + final private class Sources { + final List> dataSources; + final Map artifactTypes; + + private Sources(List> dataSources, + Map artifactTypes) { + this.dataSources = dataSources; + this.artifactTypes = artifactTypes; + } } /** @@ -388,25 +458,32 @@ class GeoFilterPanel extends javax.swing.JPanel { * doInBackground creates a list of Pair objects that contain the * display name of the data source and the data source object. */ - final private class DataSourceUpdater extends SwingWorker>, Void> { + final private class DataSourceUpdater extends SwingWorker { @Override - protected List> doInBackground() throws Exception { + protected Sources doInBackground() throws Exception { SleuthkitCase sleuthkitCase = Case.getCurrentCase().getSleuthkitCase(); List> validSources = new ArrayList<>(); + HashMap atCountsTotal = new HashMap<>(); + for (DataSource dataSource : sleuthkitCase.getDataSources()) { - if (isGPSDataSource(sleuthkitCase, dataSource)) { + Map atCounts = getGPSDataSources(sleuthkitCase, dataSource); + if (!atCounts.isEmpty()) { + for (Map.Entry entry : atCounts.entrySet()) { + atCountsTotal.putIfAbsent(entry.getKey(), 0L); + atCountsTotal.put(entry.getKey(), atCountsTotal.get(entry.getKey()) + entry.getValue()); + } String dsName = sleuthkitCase.getContentById(dataSource.getId()).getName(); Pair pair = new Pair<>(dsName, dataSource); validSources.add(pair); } } - - return validSources; + return new Sources(validSources, atCountsTotal); } /** - * Returns whether or not the given data source has GPS artifacts. + * Returns a Map representing the number of sources found for each + * artifact type. If no data was found, an empty map is returned. * * @param sleuthkitCase The current sleuthkitCase * @param dataSource @@ -415,19 +492,20 @@ class GeoFilterPanel extends javax.swing.JPanel { * * @throws TskCoreException */ - private boolean isGPSDataSource(SleuthkitCase sleuthkitCase, DataSource dataSource) throws TskCoreException { + private Map getGPSDataSources(SleuthkitCase sleuthkitCase, DataSource dataSource) throws TskCoreException { + HashMap ret = new HashMap<>(); for (BlackboardArtifact.ARTIFACT_TYPE type : GPS_ARTIFACT_TYPES) { - if (sleuthkitCase.getBlackboardArtifactsTypeCount(type.getTypeID(), dataSource.getId()) > 0) { - return true; + long count = sleuthkitCase.getBlackboardArtifactsTypeCount(type.getTypeID(), dataSource.getId()); + if (count > 0) { + ret.put(type, count); } } - - return false; + return ret; } @Override public void done() { - List> sources = null; + Sources sources = null; try { sources = get(); } catch (InterruptedException | ExecutionException ex) { @@ -440,8 +518,14 @@ class GeoFilterPanel extends javax.swing.JPanel { } if (sources != null) { - for (Pair source : sources) { - checkboxPanel.addElement(source.getKey(), source.getValue()); + for (Pair source : sources.dataSources) { + dsCheckboxPanel.addElement(source.getKey(), null, source.getValue()); + } + for (Map.Entry entry : sources.artifactTypes.entrySet()) { + String dispName = entry.getKey().getDisplayName() + " (" + entry.getValue() + ")"; + String iconPath = IconsUtil.getIconFilePath(entry.getKey().getTypeID()); + Icon icon = new ImageIcon(getClass().getResource(iconPath)); + atCheckboxPanel.addElement(dispName, icon, entry.getKey()); } } diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java index 3406e188ef..da8e14a65b 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeolocationTopComponent.java @@ -166,7 +166,6 @@ public final class GeolocationTopComponent extends TopComponent { Bundle.GLTopComponent_No_dataSource_message(), Bundle.GLTopComponent_No_dataSource_Title(), JOptionPane.ERROR_MESSAGE); - } } @@ -290,7 +289,7 @@ public final class GeolocationTopComponent extends TopComponent { filters = geoFilterPanel.getFilterState(); } catch (GeoLocationUIException ex) { JOptionPane.showMessageDialog(this, - Bundle.GeoTopComponent_filer_data_invalid_msg(), + ex.getMessage(), Bundle.GeoTopComponent_filer_data_invalid_Title(), JOptionPane.INFORMATION_MESSAGE); return; diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java index 15fd1f764e..1f8f25452e 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.CaseDbAccessManager; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; @@ -189,7 +190,7 @@ public final class WaypointBuilder { public static List getTrackpointWaypoints(SleuthkitCase skCase) throws GeoLocationDataException { List artifacts = null; try { - artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); + artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); } catch (TskCoreException ex) { throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_TRACKPOINT", ex);//NON-NLS } @@ -237,7 +238,7 @@ public final class WaypointBuilder { static public List getEXIFWaypoints(SleuthkitCase skCase) throws GeoLocationDataException { List artifacts = null; try { - artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF); + artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_METADATA_EXIF); } catch (TskCoreException ex) { throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);//NON-NLS } @@ -289,7 +290,7 @@ public final class WaypointBuilder { public static List getSearchWaypoints(SleuthkitCase skCase) throws GeoLocationDataException { List artifacts = null; try { - artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH); + artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_SEARCH); } catch (TskCoreException ex) { throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_SEARCH", ex);//NON-NLS } @@ -339,7 +340,7 @@ public final class WaypointBuilder { public static List getLastKnownWaypoints(SleuthkitCase skCase) throws GeoLocationDataException { List artifacts = null; try { - artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION); + artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION); } catch (TskCoreException ex) { throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);//NON-NLS } @@ -390,7 +391,7 @@ public final class WaypointBuilder { public static List getBookmarkWaypoints(SleuthkitCase skCase) throws GeoLocationDataException { List artifacts = null; try { - artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK); + artifacts = skCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_GPS_BOOKMARK); } catch (TskCoreException ex) { throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_BOOKMARK", ex);//NON-NLS } @@ -444,6 +445,9 @@ public final class WaypointBuilder { * Pass a null or empty list to show way points for * all dataSources. * + * @param artifactTypes List of types from which we want to get + * waypoints. + * * @param showAll True to get all waypoints. * * @param cntDaysFromRecent Number of days from the most recent time stamp @@ -459,7 +463,7 @@ public final class WaypointBuilder { * * @throws GeoLocationDataException */ - static public void getAllWaypoints(SleuthkitCase skCase, List dataSources, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp, WaypointFilterQueryCallBack queryCallBack) throws GeoLocationDataException { + static public void getAllWaypoints(SleuthkitCase skCase, List dataSources, List artifactTypes, boolean showAll, int cntDaysFromRecent, boolean noTimeStamp, WaypointFilterQueryCallBack queryCallBack) throws GeoLocationDataException { String query = buildQuery(dataSources, showAll, cntDaysFromRecent, noTimeStamp); logger.log(Level.INFO, query); @@ -480,9 +484,10 @@ public final class WaypointBuilder { int artifact_type_id = rs.getInt("artifact_type_id"); //NON-NLS long artifact_id = rs.getLong("artifact_id"); //NON-NLS - BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact_type_id); - - waypoints.addAll(getWaypointForArtifact(skCase.getBlackboardArtifact(artifact_id), type)); + ARTIFACT_TYPE type = ARTIFACT_TYPE.fromID(artifact_type_id); + if (artifactTypes.contains(type)) { + waypoints.addAll(getWaypointForArtifact(skCase.getBlackboardArtifact(artifact_id), type)); + } } queryCallBack.process(waypoints); @@ -624,7 +629,7 @@ public final class WaypointBuilder { * * @throws GeoLocationDataException */ - static private List getWaypointForArtifact(BlackboardArtifact artifact, BlackboardArtifact.ARTIFACT_TYPE type) throws GeoLocationDataException { + static private List getWaypointForArtifact(BlackboardArtifact artifact, ARTIFACT_TYPE type) throws GeoLocationDataException { List waypoints = new ArrayList<>(); switch (type) { case TSK_METADATA_EXIF: diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties index 2b63032682..24292e702c 100644 --- a/nbproject/genfiles.properties +++ b/nbproject/genfiles.properties @@ -5,7 +5,7 @@ build.xml.stylesheet.CRC32=eaf9f76a@1.42.2 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=2e7964b0 nbproject/build-impl.xml.script.CRC32=b72261eb -nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.47.1 +nbproject/build-impl.xml.stylesheet.CRC32=473dc988@2.76.1 nbproject/platform.xml.data.CRC32=2e7964b0 nbproject/platform.xml.script.CRC32=6dcbd131 -nbproject/platform.xml.stylesheet.CRC32=45ddf0e0@2.72.1 +nbproject/platform.xml.stylesheet.CRC32=ae64f0b6@2.76.1