mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into CloudSolrClient
This commit is contained in:
commit
9adbea8f9e
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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++);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
@ -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 *
|
||||||
|
Loading…
x
Reference in New Issue
Block a user