Merge branch 'develop' of github.com:sleuthkit/autopsy into CloudSolrClient

This commit is contained in:
Eugene Livis 2020-04-24 13:45:48 -04:00
commit 9adbea8f9e
9 changed files with 157 additions and 69 deletions

View File

@ -19,11 +19,13 @@
package org.sleuthkit.autopsy.communications; package org.sleuthkit.autopsy.communications;
import java.util.Collection; import java.util.Collection;
import java.util.stream.Collectors;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import org.openide.util.Utilities; import org.openide.util.Utilities;
import org.openide.util.actions.Presenter; import org.openide.util.actions.Presenter;
import org.sleuthkit.datamodel.AccountDeviceInstance;
/** /**
* Base class for actions that act on the selected AccountDeviceInstanceKeys. * Base class for actions that act on the selected AccountDeviceInstanceKeys.
@ -37,8 +39,11 @@ abstract class AbstractCVTAction extends AbstractAction implements Presenter.Pop
* *
* @return The selected accounts * @return The selected accounts
*/ */
Collection<? extends AccountDeviceInstanceKey> getSelectedAccounts() { Collection<? extends AccountDeviceInstance> getSelectedAccounts() {
return Utilities.actionsGlobalContext().lookupAll(AccountDeviceInstanceKey.class); return Utilities.actionsGlobalContext().lookupAll(AccountDeviceInstanceKey.class)
.stream()
.map((adiKey -> adiKey.getAccountDeviceInstance()))
.collect(Collectors.toSet());
} }
@Override @Override

View File

@ -24,6 +24,7 @@ import java.util.Collection;
import org.sleuthkit.autopsy.communications.FiltersPanel.DateControlState; import org.sleuthkit.autopsy.communications.FiltersPanel.DateControlState;
import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.autopsy.communications.StateManager.CommunicationsState; import org.sleuthkit.autopsy.communications.StateManager.CommunicationsState;
import org.sleuthkit.datamodel.AccountDeviceInstance;
/** /**
* Provide the singleton EventBus. * Provide the singleton EventBus.
@ -73,19 +74,19 @@ final class CVTEvents {
*/ */
static final class PinAccountsEvent { static final class PinAccountsEvent {
private final ImmutableSet<AccountDeviceInstanceKey> accountDeviceInstances; private final ImmutableSet<AccountDeviceInstance> accounInstances;
private final boolean replace; private final boolean replace;
public boolean isReplace() { public boolean isReplace() {
return replace; return replace;
} }
ImmutableSet<AccountDeviceInstanceKey> getAccountDeviceInstances() { ImmutableSet<AccountDeviceInstance> getAccountDeviceInstances() {
return accountDeviceInstances; return accounInstances;
} }
PinAccountsEvent(Collection<? extends AccountDeviceInstanceKey> accountDeviceInstances, boolean replace) { PinAccountsEvent(Collection<? extends AccountDeviceInstance> accountDeviceInstances, boolean replace) {
this.accountDeviceInstances = ImmutableSet.copyOf(accountDeviceInstances); this.accounInstances = ImmutableSet.copyOf(accountDeviceInstances);
this.replace = replace; this.replace = replace;
} }
} }
@ -95,14 +96,14 @@ final class CVTEvents {
*/ */
static final class UnpinAccountsEvent { static final class UnpinAccountsEvent {
private final ImmutableSet<AccountDeviceInstanceKey> accountDeviceInstances; private final ImmutableSet<AccountDeviceInstance> accountInstances;
public ImmutableSet<AccountDeviceInstanceKey> getAccountDeviceInstances() { public ImmutableSet<AccountDeviceInstance> getAccountDeviceInstances() {
return accountDeviceInstances; return accountInstances;
} }
UnpinAccountsEvent(Collection<? extends AccountDeviceInstanceKey> accountDeviceInstances) { UnpinAccountsEvent(Collection<? extends AccountDeviceInstance> accountDeviceInstances) {
this.accountDeviceInstances = ImmutableSet.copyOf(accountDeviceInstances); this.accountInstances = ImmutableSet.copyOf(accountDeviceInstances);
} }
} }

View File

@ -32,6 +32,7 @@ import java.io.InputStreamReader;
import java.io.StringWriter; import java.io.StringWriter;
import java.net.URL; import java.net.URL;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -147,7 +148,7 @@ final class CommunicationsGraph extends mxGraph {
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID()); scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
scopes.put("size", Math.round(Math.log(adiKey.getMessageCount()) + 5)); scopes.put("size", Math.round(Math.log(adiKey.getMessageCount()) + 5));
scopes.put("iconFileName", CommunicationsGraph.class.getResource(Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType()))); scopes.put("iconFileName", CommunicationsGraph.class.getResource(Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey)); scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey.getAccountDeviceInstance()));
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL); scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell)); scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell));
scopes.put("LOCK_URL", LOCK_URL); scopes.put("LOCK_URL", LOCK_URL);
@ -172,7 +173,7 @@ final class CommunicationsGraph extends mxGraph {
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID()); scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
scopes.put("relationships", 12);// Math.round(Math.log(adiKey.getMessageCount()) + 5)); scopes.put("relationships", 12);// Math.round(Math.log(adiKey.getMessageCount()) + 5));
scopes.put("iconFileName", CommunicationsGraph.class.getResource(Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType()))); scopes.put("iconFileName", CommunicationsGraph.class.getResource(Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey)); scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey.getAccountDeviceInstance()));
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL); scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell)); scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell));
scopes.put("LOCK_URL", LOCK_URL); scopes.put("LOCK_URL", LOCK_URL);
@ -199,16 +200,24 @@ final class CommunicationsGraph extends mxGraph {
lockedVertexModel.clear(); lockedVertexModel.clear();
} }
private mxCell getOrCreateVertex(AccountDeviceInstanceKey accountDeviceInstanceKey) { private mxCell getOrCreateVertex(AccountDeviceInstance adi, CommunicationsManager commsManager, CommunicationsFilter currentFilter) {
final AccountDeviceInstance accountDeviceInstance = accountDeviceInstanceKey.getAccountDeviceInstance(); final AccountDeviceInstance accountDeviceInstance = adi;
final String name = accountDeviceInstance.getAccount().getTypeSpecificID(); final String name = accountDeviceInstance.getAccount().getTypeSpecificID();
final mxCell vertex = nodeMap.computeIfAbsent(name + accountDeviceInstance.getDeviceId(), vertexName -> { final mxCell vertex = nodeMap.computeIfAbsent(name + accountDeviceInstance.getDeviceId(), vertexName -> {
double size = Math.sqrt(accountDeviceInstanceKey.getMessageCount()) + 10; long adiRelationshipsCount = 1;
try {
adiRelationshipsCount = commsManager.getRelationshipSourcesCount(accountDeviceInstance, currentFilter);
} catch (TskCoreException tskCoreException) {
logger.log(Level.SEVERE, "There was an error fetching relationships for the node: " + accountDeviceInstance, tskCoreException);
}
double size = Math.sqrt(adiRelationshipsCount) + 10;
AccountDeviceInstanceKey adiKey = new AccountDeviceInstanceKey(adi, currentFilter, adiRelationshipsCount);
mxCell newVertex = (mxCell) insertVertex( mxCell newVertex = (mxCell) insertVertex(
getDefaultParent(), getDefaultParent(),
name, accountDeviceInstanceKey, name, adiKey,
Math.random() * 400, Math.random() * 400,
Math.random() * 400, Math.random() * 400,
size, size,
@ -219,9 +228,11 @@ final class CommunicationsGraph extends mxGraph {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private mxCell addOrUpdateEdge(long relSources, AccountDeviceInstanceKey account1, AccountDeviceInstanceKey account2) { private mxCell addOrUpdateEdge(long relSources,
mxCell vertex1 = getOrCreateVertex(account1); AccountDeviceInstance account1, AccountDeviceInstance account2,
mxCell vertex2 = getOrCreateVertex(account2); CommunicationsManager commsManager, CommunicationsFilter currentFilter) {
mxCell vertex1 = getOrCreateVertex(account1, commsManager, currentFilter);
mxCell vertex2 = getOrCreateVertex(account2, commsManager, currentFilter);
Object[] edgesBetween = getEdgesBetween(vertex1, vertex2); Object[] edgesBetween = getEdgesBetween(vertex1, vertex2);
mxCell edge; mxCell edge;
if (edgesBetween.length == 0) { if (edgesBetween.length == 0) {
@ -260,28 +271,24 @@ final class CommunicationsGraph extends mxGraph {
/** /**
* set to keep track of accounts related to pinned accounts * set to keep track of accounts related to pinned accounts
*/ */
final Map<AccountDeviceInstance, AccountDeviceInstanceKey> relatedAccounts = new HashMap<>(); final Set<AccountDeviceInstance> relatedAccounts = new HashSet<>();
for (final AccountDeviceInstanceKey adiKey : pinnedAccountModel.getPinnedAccounts()) { for (final AccountDeviceInstance adi : pinnedAccountModel.getPinnedAccounts()) {
if (isCancelled()) { if (isCancelled()) {
break; break;
} }
//get accounts related to pinned account //get accounts related to pinned account
final List<AccountDeviceInstance> relatedAccountDeviceInstances final List<AccountDeviceInstance> relatedAccountDeviceInstances
= commsManager.getRelatedAccountDeviceInstances(adiKey.getAccountDeviceInstance(), currentFilter); = commsManager.getRelatedAccountDeviceInstances(adi, currentFilter);
relatedAccounts.put(adiKey.getAccountDeviceInstance(), adiKey); relatedAccounts.add(adi);
getOrCreateVertex(adiKey); getOrCreateVertex(adi, commsManager, currentFilter);
for (final AccountDeviceInstance relatedADI : relatedAccountDeviceInstances)
relatedAccounts.add(relatedADI);
for (final AccountDeviceInstance relatedADI : relatedAccountDeviceInstances) {
final long adiRelationshipsCount = commsManager.getRelationshipSourcesCount(relatedADI, currentFilter);
final AccountDeviceInstanceKey relatedADIKey = new AccountDeviceInstanceKey(relatedADI, currentFilter, adiRelationshipsCount);
relatedAccounts.put(relatedADI, relatedADIKey); //store related accounts
}
progressIndicator.progress(++progressCounter); progressIndicator.progress(++progressCounter);
} }
Set<AccountDeviceInstance> accounts = relatedAccounts.keySet(); Map<AccountPair, Long> relationshipCounts = commsManager.getRelationshipCountsPairwise(relatedAccounts, currentFilter);
Map<AccountPair, Long> relationshipCounts = commsManager.getRelationshipCountsPairwise(accounts, currentFilter);
int total = relationshipCounts.size(); int total = relationshipCounts.size();
int progress = 0; int progress = 0;
@ -290,12 +297,12 @@ final class CommunicationsGraph extends mxGraph {
for (Map.Entry<AccountPair, Long> entry : relationshipCounts.entrySet()) { for (Map.Entry<AccountPair, Long> entry : relationshipCounts.entrySet()) {
Long count = entry.getValue(); Long count = entry.getValue();
AccountPair relationshipKey = entry.getKey(); AccountPair relationshipKey = entry.getKey();
AccountDeviceInstanceKey account1 = relatedAccounts.get(relationshipKey.getFirst()); AccountDeviceInstance account1 = relationshipKey.getFirst();
AccountDeviceInstanceKey account2 = relatedAccounts.get(relationshipKey.getSecond()); AccountDeviceInstance account2 = relationshipKey.getSecond();
if (pinnedAccountModel.isAccountPinned(account1) if (pinnedAccountModel.isAccountPinned(account1)
|| pinnedAccountModel.isAccountPinned(account2)) { || pinnedAccountModel.isAccountPinned(account2)) {
mxCell addEdge = addOrUpdateEdge(count, account1, account2); mxCell addEdge = addOrUpdateEdge(count, account1, account2, commsManager, currentFilter);
progressText = addEdge.getId(); progressText = addEdge.getId();
} }
progressIndicator.progress(progressText, progress++); progressIndicator.progress(progressText, progress++);

View File

@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.EventBus; import com.google.common.eventbus.EventBus;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.sleuthkit.datamodel.AccountDeviceInstance;
/** /**
* Model of what accounts are pinned to a visualization. * Model of what accounts are pinned to a visualization.
@ -34,7 +35,7 @@ class PinnedAccountModel {
* to pinned accounts and pass the filters are show. Pinning accounts is the * to pinned accounts and pass the filters are show. Pinning accounts is the
* primary way to populate the graph. * primary way to populate the graph.
*/ */
private final Set<AccountDeviceInstanceKey> pinnedAccountDevices = new HashSet<>(); private final Set<AccountDeviceInstance> pinnedAccountDevices = new HashSet<>();
private final EventBus eventBus = new EventBus(); private final EventBus eventBus = new EventBus();
@ -46,7 +47,7 @@ class PinnedAccountModel {
eventBus.unregister(handler); eventBus.unregister(handler);
} }
boolean isAccountPinned(AccountDeviceInstanceKey account) { boolean isAccountPinned(AccountDeviceInstance account) {
return pinnedAccountDevices.contains(account); return pinnedAccountDevices.contains(account);
} }
@ -57,7 +58,7 @@ class PinnedAccountModel {
* *
* @param accountDeviceInstances The accounts to unpin. * @param accountDeviceInstances The accounts to unpin.
*/ */
void unpinAccount(Set<AccountDeviceInstanceKey> accountDeviceInstances) { void unpinAccount(Set<AccountDeviceInstance> accountDeviceInstances) {
pinnedAccountDevices.removeAll(accountDeviceInstances); pinnedAccountDevices.removeAll(accountDeviceInstances);
} }
@ -68,7 +69,7 @@ class PinnedAccountModel {
* *
* @param accountDeviceInstances The accounts to pin. * @param accountDeviceInstances The accounts to pin.
*/ */
void pinAccount(Set<AccountDeviceInstanceKey> accountDeviceInstances) { void pinAccount(Set<AccountDeviceInstance> accountDeviceInstances) {
pinnedAccountDevices.addAll(accountDeviceInstances); pinnedAccountDevices.addAll(accountDeviceInstances);
} }
@ -86,7 +87,7 @@ class PinnedAccountModel {
pinnedAccountDevices.clear(); pinnedAccountDevices.clear();
} }
ImmutableSet<AccountDeviceInstanceKey> getPinnedAccounts() { ImmutableSet<AccountDeviceInstance> getPinnedAccounts() {
return ImmutableSet.copyOf(pinnedAccountDevices); return ImmutableSet.copyOf(pinnedAccountDevices);
} }

View File

@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.sleuthkit.autopsy.communications.FiltersPanel.DateControlState; import org.sleuthkit.autopsy.communications.FiltersPanel.DateControlState;
import org.sleuthkit.autopsy.coreutils.History; import org.sleuthkit.autopsy.coreutils.History;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.datamodel.CommunicationsFilter;
/** /**
@ -51,11 +52,11 @@ final class StateManager {
@Subscribe @Subscribe
void pinAccount(CVTEvents.PinAccountsEvent pinEvent) { void pinAccount(CVTEvents.PinAccountsEvent pinEvent) {
if(pinEvent.isReplace()){ if(pinEvent.isReplace()){
HashSet<AccountDeviceInstanceKey> pinnedList = new HashSet<>(); HashSet<AccountDeviceInstance> pinnedList = new HashSet<>();
pinnedList.addAll(pinEvent.getAccountDeviceInstances()); pinnedList.addAll(pinEvent.getAccountDeviceInstances());
historyManager.advance(new CommunicationsState(comFilter, pinnedList, -1, currentStartState, currentEndState)); historyManager.advance(new CommunicationsState(comFilter, pinnedList, -1, currentStartState, currentEndState));
} else { } else {
HashSet<AccountDeviceInstanceKey> pinnedList = new HashSet<>(); HashSet<AccountDeviceInstance> pinnedList = new HashSet<>();
pinnedList.addAll(pinEvent.getAccountDeviceInstances()); pinnedList.addAll(pinEvent.getAccountDeviceInstances());
pinnedList.addAll(pinModel.getPinnedAccounts()); pinnedList.addAll(pinModel.getPinnedAccounts());
@ -74,7 +75,7 @@ final class StateManager {
@Subscribe @Subscribe
void unpinAccounts(CVTEvents.UnpinAccountsEvent pinEvent) { void unpinAccounts(CVTEvents.UnpinAccountsEvent pinEvent) {
HashSet<AccountDeviceInstanceKey> pinnedList = new HashSet<>(); HashSet<AccountDeviceInstance> pinnedList = new HashSet<>();
pinnedList.addAll(pinModel.getPinnedAccounts()); pinnedList.addAll(pinModel.getPinnedAccounts());
pinnedList.removeAll(pinEvent.getAccountDeviceInstances()); pinnedList.removeAll(pinEvent.getAccountDeviceInstances());
@ -135,7 +136,7 @@ final class StateManager {
*/ */
final class CommunicationsState{ final class CommunicationsState{
private final CommunicationsFilter communcationFilter; private final CommunicationsFilter communcationFilter;
private final Set<AccountDeviceInstanceKey> pinnedList; private final Set<AccountDeviceInstance> pinnedList;
private final double zoomValue; private final double zoomValue;
private final DateControlState startDateState; private final DateControlState startDateState;
private final DateControlState endDateState; private final DateControlState endDateState;
@ -149,7 +150,7 @@ final class StateManager {
* @param zoomValue Double value of the current graph scale * @param zoomValue Double value of the current graph scale
*/ */
protected CommunicationsState(CommunicationsFilter communcationFilter, protected CommunicationsState(CommunicationsFilter communcationFilter,
Set<AccountDeviceInstanceKey> pinnedList, double zoomValue, Set<AccountDeviceInstance> pinnedList, double zoomValue,
DateControlState startDateState, DateControlState endDateState){ DateControlState startDateState, DateControlState endDateState){
this.pinnedList = pinnedList; this.pinnedList = pinnedList;
this.communcationFilter = communcationFilter; this.communcationFilter = communcationFilter;
@ -172,7 +173,7 @@ final class StateManager {
* *
* @return Set of AccountDeviceInstanceKey * @return Set of AccountDeviceInstanceKey
*/ */
public Set<AccountDeviceInstanceKey> getPinnedList(){ public Set<AccountDeviceInstance> getPinnedList(){
return pinnedList; return pinnedList;
} }

View File

@ -1100,7 +1100,7 @@ final public class VisualizationPanel extends JPanel {
} else { } else {
jPopupMenu.add(new JMenuItem(new LockAction(selectedVertices))); jPopupMenu.add(new JMenuItem(new LockAction(selectedVertices)));
} }
if (pinnedAccountModel.isAccountPinned(adiKey)) { if (pinnedAccountModel.isAccountPinned(adiKey.getAccountDeviceInstance())) {
jPopupMenu.add(UnpinAccountsAction.getInstance().getPopupPresenter()); jPopupMenu.add(UnpinAccountsAction.getInstance().getPopupPresenter());
} else { } else {
jPopupMenu.add(PinAccountsAction.getInstance().getPopupPresenter()); jPopupMenu.add(PinAccountsAction.getInstance().getPopupPresenter());

View File

@ -23,6 +23,8 @@ import java.awt.Graphics;
import java.awt.GridBagConstraints; import java.awt.GridBagConstraints;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -38,9 +40,9 @@ import javax.swing.SwingWorker;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.utils.IconsUtil;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -482,6 +484,54 @@ class GeoFilterPanel extends javax.swing.JPanel {
return new Sources(validSources, atCountsTotal); return new Sources(validSources, atCountsTotal);
} }
/**
* Get a count of artifacts of the given type containing GPS data for
* the given data case and source. Does not include rejected artifacts.
*
* @param sleuthkitCase
* @param dataSource
* @param artifactType
*
* @return The artifacts count that match the criteria
*
* @throws TskCoreException
*/
private long getGPSDataCount(SleuthkitCase sleuthkitCase,
DataSource dataSource, BlackboardArtifact.ARTIFACT_TYPE artifactType) throws TskCoreException {
long count = 0;
String queryStr
= "SELECT count(DISTINCT artifact_id) AS count FROM"
+ " ("
+ " SELECT * FROM blackboard_artifacts as arts"
+ " INNER JOIN blackboard_attributes as attrs"
+ " ON attrs.artifact_id = arts.artifact_id"
+ " WHERE arts.artifact_type_id = " + artifactType.getTypeID()
+ " AND arts.data_source_obj_id = " + dataSource.getId()
+ " AND arts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()
+ " AND"
+ " ("
+ "attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()
+ " or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()
+ " or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS.getTypeID()
+ " or attrs.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS.getTypeID()
+ " )"
+ " )";
try (SleuthkitCase.CaseDbQuery queryResult = sleuthkitCase.executeQuery(queryStr);
ResultSet resultSet = queryResult.getResultSet()) {
if (resultSet.next()) {
count = resultSet.getLong("count");
}
} catch (SQLException ex) {
Throwable cause = ex.getCause();
if (cause != null) {
logger.log(Level.SEVERE, cause.getMessage(), cause);
} else {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
return count;
}
/** /**
* Returns a Map representing the number of sources found for each * Returns a Map representing the number of sources found for each
* artifact type. If no data was found, an empty map is returned. * artifact type. If no data was found, an empty map is returned.
@ -496,7 +546,7 @@ class GeoFilterPanel extends javax.swing.JPanel {
private Map<ARTIFACT_TYPE, Long> getGPSDataSources(SleuthkitCase sleuthkitCase, DataSource dataSource) throws TskCoreException { private Map<ARTIFACT_TYPE, Long> getGPSDataSources(SleuthkitCase sleuthkitCase, DataSource dataSource) throws TskCoreException {
HashMap<ARTIFACT_TYPE, Long> ret = new HashMap<>(); HashMap<ARTIFACT_TYPE, Long> ret = new HashMap<>();
for (BlackboardArtifact.ARTIFACT_TYPE type : GPS_ARTIFACT_TYPES) { for (BlackboardArtifact.ARTIFACT_TYPE type : GPS_ARTIFACT_TYPES) {
long count = sleuthkitCase.getBlackboardArtifactsTypeCount(type.getTypeID(), dataSource.getId()); long count = getGPSDataCount(sleuthkitCase, dataSource, type);
if (count > 0) { if (count > 0) {
ret.put(type, count); ret.put(type, count);
} }

View File

@ -39,6 +39,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -83,9 +84,13 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
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"; 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;
private static final Set<Integer> DOT_WAYPOINT_TYPES = new HashSet<>();
private static final int DOT_SIZE = 12;
private boolean zoomChanging; private boolean zoomChanging;
private KdTree<MapWaypoint> waypointTree; private KdTree<MapWaypoint> waypointTree;
private Set<MapWaypoint> waypointSet; private Set<MapWaypoint> waypointSet;
@ -104,6 +109,12 @@ final public class MapPanel extends javax.swing.JPanel {
private MapWaypoint currentlySelectedWaypoint; private MapWaypoint currentlySelectedWaypoint;
private Set<MapWaypoint> currentlySelectedTrack; private Set<MapWaypoint> currentlySelectedTrack;
static {
DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID());
DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID());
DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID());
}
/** /**
* Creates new form MapPanel * Creates new form MapPanel
*/ */
@ -486,14 +497,30 @@ final public class MapPanel extends javax.swing.JPanel {
Iterator<MapWaypoint> iterator = waypoints.iterator(); Iterator<MapWaypoint> iterator = waypoints.iterator();
// These maybe the points closest to lat/log was clicked but // These may be the points closest to the lat/lon location that was
// that doesn't mean they are close in terms of pixles. // clicked, but that doesn't mean they are close in terms of pixles.
List<MapWaypoint> closestPoints = new ArrayList<>(); List<MapWaypoint> closestPoints = new ArrayList<>();
while (iterator.hasNext()) { while (iterator.hasNext()) {
MapWaypoint nextWaypoint = iterator.next(); MapWaypoint nextWaypoint = iterator.next();
Point2D point = mapViewer.convertGeoPositionToPoint(nextWaypoint.getPosition()); Point2D point = mapViewer.convertGeoPositionToPoint(nextWaypoint.getPosition());
Rectangle rect = new Rectangle((int) point.getX() - (whiteWaypointImage.getWidth() / 2), (int) point.getY() - whiteWaypointImage.getHeight(), whiteWaypointImage.getWidth(), whiteWaypointImage.getHeight()); int pointX = (int) point.getX();
int pointY = (int) point.getY();
Rectangle rect;
if (DOT_WAYPOINT_TYPES.contains(nextWaypoint.getArtifactTypeID())) {
rect = new Rectangle(
pointX - (DOT_SIZE / 2),
pointY - (DOT_SIZE / 2),
DOT_SIZE,
DOT_SIZE
);
} else {
rect = new Rectangle(
pointX - (whiteWaypointImage.getWidth() / 2),
pointY - whiteWaypointImage.getHeight(),
whiteWaypointImage.getWidth(),
whiteWaypointImage.getHeight()
);
}
if (rect.contains(clickPoint)) { if (rect.contains(clickPoint)) {
closestPoints.add(nextWaypoint); closestPoints.add(nextWaypoint);
@ -689,6 +716,7 @@ final public class MapPanel extends javax.swing.JPanel {
if (waypoints.size() > 0) { if (waypoints.size() > 0) {
MapWaypoint selection = waypoints.get(0); MapWaypoint selection = waypoints.get(0);
currentlySelectedWaypoint = selection; currentlySelectedWaypoint = selection;
currentlySelectedTrack = null;
for (Set<MapWaypoint> track : tracks) { for (Set<MapWaypoint> track : tracks) {
if (track.contains(selection)) { if (track.contains(selection)) {
currentlySelectedTrack = track; currentlySelectedTrack = track;
@ -751,17 +779,16 @@ final public class MapPanel extends javax.swing.JPanel {
* @return the new dot image * @return the new dot image
*/ */
private BufferedImage createTrackDotImage(Color color) { private BufferedImage createTrackDotImage(Color color) {
int w = 10; int s = DOT_SIZE;
int h = 10;
BufferedImage ret = new BufferedImage(w + 2, h + 2, BufferedImage.TYPE_INT_ARGB); BufferedImage ret = new BufferedImage(s, s, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = ret.createGraphics(); Graphics2D g = ret.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color); g.setColor(color);
g.fillOval(1, 1, w, h); g.fillOval(1, 1, s - 2, s - 2);
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(1)); g.setStroke(new BasicStroke(1));
g.drawOval(1, 1, w, h); g.drawOval(1, 1, s - 2, s - 2);
g.dispose(); g.dispose();
return ret; return ret;
} }
@ -794,14 +821,11 @@ final public class MapPanel extends javax.swing.JPanel {
public void paintWaypoint(Graphics2D g, JXMapViewer map, MapWaypoint waypoint) { public void paintWaypoint(Graphics2D g, JXMapViewer map, MapWaypoint waypoint) {
Color color = getColor(waypoint); Color color = getColor(waypoint);
BufferedImage image; BufferedImage image;
int artifactType = waypoint.getArtifactTypeID();
Point2D point = map.getTileFactory().geoToPixel(waypoint.getPosition(), map.getZoom()); Point2D point = map.getTileFactory().geoToPixel(waypoint.getPosition(), map.getZoom());
int x = (int) point.getX(); int x = (int) point.getX();
int y = (int) point.getY(); int y = (int) point.getY();
if (artifactType == ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID() if (DOT_WAYPOINT_TYPES.contains(waypoint.getArtifactTypeID())) {
|| artifactType == ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID()
|| artifactType == ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID()) {
image = dotImageCache.computeIfAbsent(color, k -> { image = dotImageCache.computeIfAbsent(color, k -> {
return createTrackDotImage(color); return createTrackDotImage(color);
}); });

View File

@ -42,11 +42,10 @@ The following need to be done at least once. They do not need to be repeated for
Autopsy depends on a specific version of The Sleuth Kit. You need the Java libraries of The Sleuth Kit installed, which is not part of all packages. Autopsy depends on a specific version of The Sleuth Kit. You need the Java libraries of The Sleuth Kit installed, which is not part of all packages.
- Linux: Install the sleuthkit-java.deb file that you can download from github.com/sleuthkit/sleuthkit/releases. This will install libewf, etc. - Linux: Install the sleuthkit-java.deb file that you can download from github.com/sleuthkit/sleuthkit/releases. This will install libewf, etc. For example:
-- % sudo apt install ./sleuthkit-java_4.7.0-1_amd64.deb -- % sudo apt install ./sleuthkit-java_4.8.0-1_amd64.deb
- OS X: Install The Sleuth Kit from brew. - OS X: Build The Sleuth Kit from source. See https://github.com/sleuthkit/sleuthkit/blob/develop/INSTALL.txt for details.
-- % brew install sleuthkit
* Install Autopsy * * Install Autopsy *