Merge remote-tracking branch 'upstream/cvt-contacts-view' into cvt-contacts-view-merge-to-develop

This commit is contained in:
Richard Cordovano 2019-05-09 11:14:06 -04:00
commit 0477de37e6
46 changed files with 3210 additions and 794 deletions

View File

@ -1,88 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.python.google.common.collect.Iterables;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* 'Root' Node for the Account/Messages area. Has children which are all the
* relationships of all the accounts in this node.
*
*/
final class AccountDetailsNode extends AbstractNode {
private final static Logger logger = Logger.getLogger(AccountDetailsNode.class.getName());
AccountDetailsNode(Set<AccountDeviceInstance> accountDeviceInstances, CommunicationsFilter filter, CommunicationsManager commsManager) {
super(Children.create(new AccountRelationshipChildren(accountDeviceInstances, commsManager, filter), true));
String displayName = (accountDeviceInstances.size() == 1)
? Iterables.getOnlyElement(accountDeviceInstances).getAccount().getTypeSpecificID()
: accountDeviceInstances.size() + " accounts";
setDisplayName(displayName);
}
/**
* Children object for the relationships that the accounts are part of.
*/
private static class AccountRelationshipChildren extends ChildFactory<Content> {
private final Set<AccountDeviceInstance> accountDeviceInstances;
private final CommunicationsManager commsManager;
private final CommunicationsFilter filter;
private AccountRelationshipChildren(Set<AccountDeviceInstance> accountDeviceInstances, CommunicationsManager commsManager, CommunicationsFilter filter) {
this.accountDeviceInstances = accountDeviceInstances;
this.commsManager = commsManager;
this.filter = filter;
}
@Override
protected boolean createKeys(List<Content> list) {
try {
list.addAll(commsManager.getRelationshipSources(accountDeviceInstances, filter));
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting communications", ex);
}
return true;
}
@Override
protected Node createNodeForKey(Content t) {
if (t instanceof BlackboardArtifact) {
return new RelationshipNode((BlackboardArtifact) t);
} else {
throw new UnsupportedOperationException("Cannot create a RelationshipNode for non BlackboardArtifact content.");
}
}
}
}

View File

@ -20,6 +20,8 @@ package org.sleuthkit.autopsy.communications;
import com.google.common.eventbus.Subscribe;
import java.awt.Component;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
@ -31,11 +33,16 @@ import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.lookup.ProxyLookup;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.communications.relationships.RelationshipBrowser;
import org.sleuthkit.autopsy.communications.relationships.SelectionInfo;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.TskCoreException;
@ -56,8 +63,9 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
private final Outline outline;
private final ExplorerManager messageBrowserEM = new ExplorerManager();
private final ExplorerManager accountsTableEM = new ExplorerManager();
final RelationshipBrowser relationshipBrowser;
/*
* This lookup proxies the selection lookup of both he accounts table and
@ -78,21 +86,30 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName());
outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
outline.setColumnSorted(3, false, 1); //it would be nice if the column index wasn't hardcoded
relationshipBrowser = new RelationshipBrowser();
jSplitPane1.setRightComponent(relationshipBrowser);
accountsTableEM.addPropertyChangeListener(evt -> {
if (ExplorerManager.PROP_ROOT_CONTEXT.equals(evt.getPropertyName())) {
SwingUtilities.invokeLater(this::setColumnWidths);
} else if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) {
SwingUtilities.invokeLater(this::setColumnWidths);
} else if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
final Node[] selectedNodes = accountsTableEM.getSelectedNodes();
final Set<AccountDeviceInstance> accountDeviceInstances = new HashSet<>();
CommunicationsFilter filter = null;
for (final Node node : selectedNodes) {
accountDeviceInstances.add(((AccountDeviceInstanceNode) node).getAccountDeviceInstance());
filter = ((AccountDeviceInstanceNode)node).getFilter();
}
relationshipBrowser.setSelectionInfo(new SelectionInfo(accountDeviceInstances, filter));
}
});
final MessageBrowser messageBrowser = new MessageBrowser(accountsTableEM, messageBrowserEM);
jSplitPane1.setRightComponent(messageBrowser);
proxyLookup = new ProxyLookup(
messageBrowser.getLookup(),
ExplorerUtils.createLookup(accountsTableEM, getActionMap()));
proxyLookup = new ProxyLookup(relationshipBrowser.getLookup(),
ExplorerUtils.createLookup(accountsTableEM, getActionMap()));
}
private void setColumnWidths() {

View File

@ -32,21 +32,16 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in
VisualizationPanel.zoomInButton.text=
VisualizationPanel.zoomOutButton.toolTipText=Zoom out
VisualizationPanel.zoomOutButton.text=
<<<<<<< HEAD
VisualizationPanel.fastOrganicLayoutButton.text=Redraw
VisualizationPanel.clearVizButton.text_1=Clear
VisualizationPanel.fastOrganicLayoutButton.text=
VisualizationPanel.backButton.text_1=
VisualizationPanel.forwardButton.text=
=======
VisualizationPanel.circleLayoutButton.text=Circle
VisualizationPanel.organicLayoutButton.text=Organic
VisualizationPanel.fastOrganicLayoutButton.text=
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
VisualizationPanel.clearVizButton.text_1=
VisualizationPanel.snapshotButton.text_1=Snapshot Report
>>>>>>> develop
VisualizationPanel.clearVizButton.actionCommand=
VisualizationPanel.backButton.toolTipText=Click to go back
VisualizationPanel.forwardButton.toolTipText=Click to go forward
VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart
VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart
VisualizationPanel.forwardButton.text=

View File

@ -22,7 +22,6 @@ FiltersPanel.refreshButton.text=Refresh
FiltersPanel.deviceRequiredLabel.text=Select at least one.
FiltersPanel.accountTypeRequiredLabel.text=Select at least one.
FiltersPanel.needsRefreshLabel.text=Displayed data is out of date. Press Refresh.
MessageBrowser.DataResultViewerTable.title=Messages
OpenCVTAction.displayName=Communications
PinAccountsAction.pluralText=Add Selected Accounts to Visualization
PinAccountsAction.singularText=Add Selected Account to Visualization
@ -76,24 +75,19 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in
VisualizationPanel.zoomInButton.text=
VisualizationPanel.zoomOutButton.toolTipText=Zoom out
VisualizationPanel.zoomOutButton.text=
<<<<<<< HEAD
VisualizationPanel.fastOrganicLayoutButton.text=Redraw
VisualizationPanel.clearVizButton.text_1=Clear
VisualizationPanel.fastOrganicLayoutButton.text=
VisualizationPanel.backButton.text_1=
VisualizationPanel.forwardButton.text=
=======
VisualizationPanel.circleLayoutButton.text=Circle
VisualizationPanel.organicLayoutButton.text=Organic
VisualizationPanel.fastOrganicLayoutButton.text=
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
VisualizationPanel.clearVizButton.text_1=
VisualizationPanel.snapshotButton.text_1=Snapshot Report
>>>>>>> develop
VisualizationPanel.clearVizButton.actionCommand=
VisualizationPanel.backButton.toolTipText=Click to go back
VisualizationPanel.forwardButton.toolTipText=Click to go forward
VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart
VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart
VisualizationPanel.forwardButton.text=
VisualizationPanel_action_dialogs_title=Communications
VisualizationPanel_action_name_text=Snapshot Report
VisualizationPanel_module_name=Communications

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.communications;
import com.google.common.eventbus.Subscribe;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.util.List;
@ -61,8 +62,11 @@ public final class CVTTopComponent extends TopComponent {
associateLookup(proxyLookup);
// Make sure the Global Actions Context is proxying the selection of the active tab.
browseVisualizeTabPane.addChangeListener(changeEvent -> {
Lookup.Provider selectedComponent = (Lookup.Provider) browseVisualizeTabPane.getSelectedComponent();
proxyLookup.setNewLookups(selectedComponent.getLookup());
Component selectedComponent = browseVisualizeTabPane.getSelectedComponent();
if(selectedComponent instanceof Lookup.Provider) {
Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup();
proxyLookup.setNewLookups(lookup);
}
filtersPane.setDeviceAccountTypeEnabled(browseVisualizeTabPane.getSelectedIndex() != 0);
});

View File

@ -52,6 +52,7 @@ import org.sleuthkit.datamodel.CommunicationsFilter.DateRangeFilter;
import org.sleuthkit.datamodel.CommunicationsFilter.DeviceFilter;
import org.sleuthkit.datamodel.DataSource;
import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG;
import static org.sleuthkit.datamodel.Relationship.Type.CONTACT;
import static org.sleuthkit.datamodel.Relationship.Type.MESSAGE;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
@ -598,7 +599,7 @@ final public class FiltersPanel extends JPanel {
commsFilter.addAndFilter(getAccountTypeFilter());
commsFilter.addAndFilter(getDateRangeFilter());
commsFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter(
ImmutableSet.of(CALL_LOG, MESSAGE)));
ImmutableSet.of(CALL_LOG, MESSAGE, CONTACT)));
return commsFilter;
}

View File

@ -1,231 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JPanel;
import static javax.swing.SwingUtilities.isDescendingFrom;
import org.openide.explorer.ExplorerManager;
import static org.openide.explorer.ExplorerUtils.createLookup;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
/**
* The right hand side of the CVT. Has a DataResultPanel to show a listing of
* messages and other account details, and a ContentViewer to show individual
* messages.
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class MessageBrowser extends JPanel implements ExplorerManager.Provider, Lookup.Provider {
private static final long serialVersionUID = 1L;
private final ExplorerManager tableEM;
private final ExplorerManager gacExplorerManager;
private final DataResultPanel messagesResultPanel;
/* lookup that will be exposed through the (Global Actions Context) */
private final ModifiableProxyLookup proxyLookup = new ModifiableProxyLookup();
private final PropertyChangeListener focusPropertyListener = new PropertyChangeListener() {
/**
* Listener that keeps the proxyLookup in sync with the focused area of
* the UI.
*
* Since the embedded MessageContentViewer (attachments panel) is not in
* its own TopComponenet, its selection does not get proxied into the
* Global Actions Context (GAC), and many of the available actions don't
* work on it. Further, we can't put the selection from both the
* Messages table and the Attachments table in the GAC because they
* could both include AbstractFiles, muddling the selection seen by the
* actions. Instead, depending on where the focus is in the window, we
* want to put different Content in the Global Actions Context to be
* picked up by, e.g., the tagging actions. The best way I could figure
* to do this was to listen to all focus events and swap out what is in
* the lookup appropriately. An alternative to this would be to
* investigate using the ContextAwareAction interface.
*
* @see org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a
* similar situation and a similar solution.
*
* @param focusEvent The focus change event.
*/
@Override
public void propertyChange(final PropertyChangeEvent focusEvent) {
if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) {
final Component newFocusOwner = (Component) focusEvent.getNewValue();
if (newFocusOwner == null) {
return;
}
if (isDescendingFrom(newFocusOwner, messageDataContent)) {
//if the focus owner is within the MessageContentViewer ( the attachments table)
proxyLookup.setNewLookups(createLookup(messageDataContent.getExplorerManager(), getActionMap()));
} else if (isDescendingFrom(newFocusOwner, messagesResultPanel)) {
//... or if it is within the Messages table.
proxyLookup.setNewLookups(createLookup(gacExplorerManager, getActionMap()));
}
}
}
};
/**
* Constructs the right hand side of the Communications Visualization Tool
* (CVT).
*
* @param tableEM An explorer manager to listen to as the driver
* of the Message Table.
* @param gacExplorerManager An explorer manager associated with the
* GlobalActionsContext (GAC) so that selections
* in the messages browser can be exposed to
* context-sensitive actions.
*/
@NbBundle.Messages({"MessageBrowser.DataResultViewerTable.title=Messages"})
MessageBrowser(final ExplorerManager tableEM, final ExplorerManager gacExplorerManager) {
this.tableEM = tableEM;
this.gacExplorerManager = gacExplorerManager;
initComponents();
//create an uninitialized DataResultPanel so we can control the ResultViewers that get added.
messagesResultPanel = DataResultPanel.createInstanceUninitialized("Account", "", Node.EMPTY, 0, messageDataContent);
splitPane.setTopComponent(messagesResultPanel);
splitPane.setBottomComponent(messageDataContent);
messagesResultPanel.addResultViewer(new DataResultViewerTable(gacExplorerManager,
Bundle.MessageBrowser_DataResultViewerTable_title()));
messagesResultPanel.open();
this.tableEM.addPropertyChangeListener(new PropertyChangeListener() {
/**
* Listener that pushes selections in the tableEM (the Accounts
* table) into the Messages table.
*
* @param pce The ExplorerManager event.
*/
@Override
public void propertyChange(PropertyChangeEvent pce) {
if (pce.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
final Node[] selectedNodes = MessageBrowser.this.tableEM.getSelectedNodes();
messagesResultPanel.setNumberOfChildNodes(0);
messagesResultPanel.setNode(null);
messagesResultPanel.setPath("");
if (selectedNodes.length > 0) {
Node rootNode;
final Node selectedNode = selectedNodes[0];
if (selectedNode instanceof AccountDeviceInstanceNode) {
rootNode = makeRootNodeFromAccountDeviceInstanceNodes(selectedNodes);
} else {
rootNode = selectedNode;
}
messagesResultPanel.setPath(rootNode.getDisplayName());
messagesResultPanel.setNode(new TableFilterNode(new DataResultFilterNode(rootNode, gacExplorerManager), true));
}
}
}
private Node makeRootNodeFromAccountDeviceInstanceNodes(final Node[] selectedNodes) {
//Use lookup here?
final AccountDeviceInstanceNode adiNode = (AccountDeviceInstanceNode) selectedNodes[0];
final Set<AccountDeviceInstanceKey> accountDeviceInstances = new HashSet<>();
for (final Node n : selectedNodes) {
//Use lookup here?
accountDeviceInstances.add(((AccountDeviceInstanceNode) n).getAccountDeviceInstanceKey());
}
return SelectionNode.createFromAccounts(accountDeviceInstances, adiNode.getFilter(), adiNode.getCommsManager());
}
}
);
}
@Override
public ExplorerManager getExplorerManager() {
return gacExplorerManager;
}
@Override
public Lookup getLookup() {
return proxyLookup;
}
@Override
public void addNotify() {
super.addNotify();
//add listener that maintains correct selection in the Global Actions Context
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("focusOwner", focusPropertyListener);
}
@Override
public void removeNotify() {
super.removeNotify();
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.removePropertyChangeListener("focusOwner", focusPropertyListener);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
splitPane = new javax.swing.JSplitPane();
messageDataContent = new org.sleuthkit.autopsy.communications.MessageDataContent();
splitPane.setDividerLocation(400);
splitPane.setDividerSize(10);
splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
splitPane.setResizeWeight(0.5);
splitPane.setBottomComponent(messageDataContent);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(splitPane))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(splitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1083, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private org.sleuthkit.autopsy.communications.MessageDataContent messageDataContent;
private javax.swing.JSplitPane splitPane;
// End of variables declaration//GEN-END:variables
}

View File

@ -26,9 +26,9 @@ import org.openide.util.lookup.ProxyLookup;
* delegated to.
*
*/
final class ModifiableProxyLookup extends ProxyLookup {
final public class ModifiableProxyLookup extends ProxyLookup {
ModifiableProxyLookup(final Lookup... lookups) {
public ModifiableProxyLookup(final Lookup... lookups) {
super(lookups);
}

View File

@ -1,35 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.communications;
import java.util.Collection;
import java.util.List;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.datamodel.BlackboardArtifact;
/**
*
*/
public class RelaionshipSetNodeFactory extends ChildFactory<BlackboardArtifact> {
private final Collection<BlackboardArtifact> artifacts;
public RelaionshipSetNodeFactory(Collection<BlackboardArtifact> artifacts) {
this.artifacts = artifacts;
}
@Override
protected boolean createKeys(List<BlackboardArtifact> list) {
list.addAll(artifacts);
return true;
}
@Override
protected Node createNodeForKey(BlackboardArtifact key) {
return new RelationshipNode(key);
}
}

View File

@ -1,140 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* 'Root' Node for the Account/Messages area. Represents all the relationships
* that are selected in the AccountsBrowser or the VisualizationPanel. Can be
* populated with AccountDeviceInstance and/or directly with relationships
* (Content).
*/
final class SelectionNode extends AbstractNode {
private SelectionNode(Children children, Lookup lookup) {
super(children, lookup);
}
static SelectionNode createFromAccountsAndRelationships(
Set<Content> edgeRelationshipArtifacts,
Set<AccountDeviceInstanceKey> accountDeviceInstanceKeys,
CommunicationsFilter filter,
CommunicationsManager commsManager) {
Set<AccountDeviceInstance> accountDeviceInstances = accountDeviceInstanceKeys.stream()
.map(AccountDeviceInstanceKey::getAccountDeviceInstance)
.collect(Collectors.toSet());
SelectionNode node = new SelectionNode(Children.create(
new RelationshipChildren(
edgeRelationshipArtifacts,
accountDeviceInstances,
commsManager,
filter),
true), Lookups.fixed(accountDeviceInstanceKeys.toArray()));
//This is not good for internationalization!!!
String name = "";
final int accounts = accountDeviceInstances.size();
if (accounts > 1) {
name = accounts + " accounts";
} else if (accounts == 1) {
name = Iterables.getOnlyElement(accountDeviceInstances).getAccount().getTypeSpecificID();
}
final int edges = edgeRelationshipArtifacts.size();
if (edges > 0) {
name = name + (name.isEmpty() ? "" : " and ") + edges + " relationship" + (edges > 1 ? "s" : "");
}
node.setDisplayName(name);
return node;
}
static SelectionNode createFromAccounts(
Set<AccountDeviceInstanceKey> accountDeviceInstances,
CommunicationsFilter filter,
CommunicationsManager commsManager) {
return createFromAccountsAndRelationships(Collections.emptySet(), accountDeviceInstances, filter, commsManager);
}
/**
* Children object for the relationships that the accounts are part of.
*/
private static class RelationshipChildren extends ChildFactory<Content> {
static final private Logger logger = Logger.getLogger(RelationshipChildren.class.getName());
private final Set<Content> edgeRelationshipArtifacts;
private final Set<AccountDeviceInstance> accountDeviceInstances;
private final CommunicationsManager commsManager;
private final CommunicationsFilter filter;
private RelationshipChildren(Set<Content> selectedEdgeRelationshipSources, Set<AccountDeviceInstance> selecedAccountDeviceInstances, CommunicationsManager commsManager, CommunicationsFilter filter) {
this.edgeRelationshipArtifacts = selectedEdgeRelationshipSources;
this.accountDeviceInstances = selecedAccountDeviceInstances;
this.commsManager = commsManager;
this.filter = filter;
}
@Override
protected boolean createKeys(List<Content> list) {
try {
final Set<Content> relationshipSources = commsManager.getRelationshipSources(accountDeviceInstances, filter);
list.addAll(Sets.union(relationshipSources, edgeRelationshipArtifacts));
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting communications", ex);
}
return true;
}
@Override
protected Node createNodeForKey(Content content) {
if (content instanceof BlackboardArtifact) {
return new RelationshipNode((BlackboardArtifact) content);
} else {
throw new UnsupportedOperationException("Cannot create a RelationshipNode for non BlackboardArtifact content.");
}
}
}
}

View File

@ -28,12 +28,12 @@ import org.sleuthkit.datamodel.Account;
/**
* Utility class with helpers for dealing with accounts.
*/
class Utils {
public final class Utils {
private Utils() {
}
static ZoneId getUserPreferredZoneId() {
static public ZoneId getUserPreferredZoneId() {
ZoneId zone = UserPreferences.displayTimesInLocalTime() ?
ZoneOffset.systemDefault() : TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()).toZoneId();
return zone;
@ -44,7 +44,7 @@ class Utils {
*
* @return The path of the icon for the given Account Type.
*/
static final String getIconFilePath(Account.Type type) {
static public final String getIconFilePath(Account.Type type) {
return Accounts.getIconFilePath(type);
}

View File

@ -54,7 +54,6 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@ -62,11 +61,11 @@ import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@ -98,23 +97,20 @@ import org.apache.commons.lang3.StringUtils;
import org.controlsfx.control.Notifications;
import org.jdesktop.layout.GroupLayout;
import org.jdesktop.layout.LayoutStyle;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ProxyLookup;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.communications.relationships.RelationshipBrowser;
import org.sleuthkit.autopsy.communications.relationships.SelectionInfo;
import org.sleuthkit.autopsy.communications.snapshot.CommSnapShotReportWriter;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A panel that goes in the Visualize tab of the Communications Visualization
@ -127,7 +123,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* actions to work correctly.
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final public class VisualizationPanel extends JPanel implements Lookup.Provider {
final public class VisualizationPanel extends JPanel {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(VisualizationPanel.class.getName());
@ -140,9 +136,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
@NbBundle.Messages("VisualizationPanel.cancelButton.text=Cancel")
private static final String CANCEL = Bundle.VisualizationPanel_cancelButton_text();
private final ExplorerManager vizEM = new ExplorerManager();
private final ExplorerManager gacEM = new ExplorerManager();
private final ProxyLookup proxyLookup;
private Frame windowAncestor;
private CommunicationsManager commsManager;
@ -161,6 +154,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
private final Map<NamedGraphLayout, JButton> layoutButtons = new HashMap<>();
private NamedGraphLayout currentLayout;
private final RelationshipBrowser relationshipBrowser;
private final StateManager stateManager;
@ -225,13 +220,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
final GraphMouseListener graphMouseListener = new GraphMouseListener();
graphComponent.getGraphControl().addMouseWheelListener(graphMouseListener);
graphComponent.getGraphControl().addMouseListener(graphMouseListener);
final MessageBrowser messageBrowser = new MessageBrowser(vizEM, gacEM);
splitPane.setRightComponent(messageBrowser);
proxyLookup = new ProxyLookup(
ExplorerUtils.createLookup(vizEM, getActionMap()),
messageBrowser.getLookup()
);
relationshipBrowser = new RelationshipBrowser();
splitPane.setRightComponent(relationshipBrowser);
//feed selection to explorermanager
graph.getSelectionModel().addListener(mxEvent.CHANGE, new SelectionListener());
@ -257,12 +248,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
setStateButtonsEnabled();
}
@Override
public Lookup getLookup() {
return proxyLookup;
}
@Subscribe
void handle(LockedVertexModel.VertexLockEvent event) {
final Set<mxCell> vertices = event.getVertices();
@ -387,219 +373,223 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
splitPane = new JSplitPane();
borderLayoutPanel = new JPanel();
placeHolderPanel = new JPanel();
jTextArea1 = new JTextArea();
toolbar = new JPanel();
fastOrganicLayoutButton = new JButton();
zoomOutButton = new JButton();
zoomInButton = new JButton();
zoomActualButton = new JButton();
fitZoomButton = new JButton();
jLabel2 = new JLabel();
zoomLabel = new JLabel();
clearVizButton = new JButton();
jSeparator2 = new JToolBar.Separator();
backButton = new JButton();
forwardButton = new JButton();
snapshotButton = new JButton();
jSeparator3 = new JToolBar.Separator();
jSeparator4 = new JToolBar.Separator();
notificationsJFXPanel = new JFXPanel();
splitPane = new javax.swing.JSplitPane();
borderLayoutPanel = new javax.swing.JPanel();
placeHolderPanel = new javax.swing.JPanel();
jTextArea1 = new javax.swing.JTextArea();
toolbar = new javax.swing.JPanel();
fastOrganicLayoutButton = new javax.swing.JButton();
zoomOutButton = new javax.swing.JButton();
zoomInButton = new javax.swing.JButton();
zoomActualButton = new javax.swing.JButton();
fitZoomButton = new javax.swing.JButton();
jLabel2 = new javax.swing.JLabel();
zoomLabel = new javax.swing.JLabel();
clearVizButton = new javax.swing.JButton();
jSeparator2 = new javax.swing.JToolBar.Separator();
backButton = new javax.swing.JButton();
forwardButton = new javax.swing.JButton();
snapshotButton = new javax.swing.JButton();
jSeparator3 = new javax.swing.JToolBar.Separator();
jSeparator4 = new javax.swing.JToolBar.Separator();
notificationsJFXPanel = new javafx.embed.swing.JFXPanel();
setLayout(new BorderLayout());
setLayout(new java.awt.BorderLayout());
splitPane.setDividerLocation(800);
splitPane.setResizeWeight(0.5);
borderLayoutPanel.setLayout(new BorderLayout());
borderLayoutPanel.setLayout(new java.awt.BorderLayout());
jTextArea1.setBackground(new Color(240, 240, 240));
jTextArea1.setBackground(new java.awt.Color(240, 240, 240));
jTextArea1.setColumns(20);
jTextArea1.setLineWrap(true);
jTextArea1.setRows(5);
jTextArea1.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jTextArea1.text")); // NOI18N
jTextArea1.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jTextArea1.text")); // NOI18N
GroupLayout placeHolderPanelLayout = new GroupLayout(placeHolderPanel);
org.jdesktop.layout.GroupLayout placeHolderPanelLayout = new org.jdesktop.layout.GroupLayout(placeHolderPanel);
placeHolderPanel.setLayout(placeHolderPanelLayout);
placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
placeHolderPanelLayout.setHorizontalGroup(
placeHolderPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(placeHolderPanelLayout.createSequentialGroup()
.addContainerGap(250, Short.MAX_VALUE)
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 424, GroupLayout.PREFERRED_SIZE)
.add(jTextArea1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 424, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(423, Short.MAX_VALUE))
);
placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
placeHolderPanelLayout.setVerticalGroup(
placeHolderPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(placeHolderPanelLayout.createSequentialGroup()
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 47, GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(jTextArea1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 47, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
borderLayoutPanel.add(placeHolderPanel, java.awt.BorderLayout.CENTER);
fastOrganicLayoutButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N
fastOrganicLayoutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.text")); // NOI18N
fastOrganicLayoutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.toolTipText")); // NOI18N
fastOrganicLayoutButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N
fastOrganicLayoutButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.text")); // NOI18N
fastOrganicLayoutButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.toolTipText")); // NOI18N
fastOrganicLayoutButton.setFocusable(false);
fastOrganicLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
fastOrganicLayoutButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
zoomOutButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-out-red.png"))); // NOI18N
zoomOutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.text")); // NOI18N
zoomOutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N
zoomOutButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-out-red.png"))); // NOI18N
zoomOutButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.text")); // NOI18N
zoomOutButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N
zoomOutButton.setFocusable(false);
zoomOutButton.setHorizontalTextPosition(SwingConstants.CENTER);
zoomOutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
zoomOutButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomOutButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
zoomOutButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
zoomOutButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
zoomOutButtonActionPerformed(evt);
}
});
zoomInButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png"))); // NOI18N
zoomInButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.text")); // NOI18N
zoomInButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N
zoomInButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png"))); // NOI18N
zoomInButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.text")); // NOI18N
zoomInButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N
zoomInButton.setFocusable(false);
zoomInButton.setHorizontalTextPosition(SwingConstants.CENTER);
zoomInButton.setVerticalTextPosition(SwingConstants.BOTTOM);
zoomInButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomInButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
zoomInButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
zoomInButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
zoomInButtonActionPerformed(evt);
}
});
zoomActualButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); // NOI18N
zoomActualButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.text")); // NOI18N
zoomActualButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N
zoomActualButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); // NOI18N
zoomActualButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.text")); // NOI18N
zoomActualButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N
zoomActualButton.setFocusable(false);
zoomActualButton.setHorizontalTextPosition(SwingConstants.CENTER);
zoomActualButton.setVerticalTextPosition(SwingConstants.BOTTOM);
zoomActualButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomActualButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
zoomActualButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
zoomActualButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
zoomActualButtonActionPerformed(evt);
}
});
fitZoomButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); // NOI18N
fitZoomButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.text")); // NOI18N
fitZoomButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N
fitZoomButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); // NOI18N
fitZoomButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.text")); // NOI18N
fitZoomButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N
fitZoomButton.setFocusable(false);
fitZoomButton.setHorizontalTextPosition(SwingConstants.CENTER);
fitZoomButton.setVerticalTextPosition(SwingConstants.BOTTOM);
fitZoomButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
fitZoomButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
fitZoomButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
fitZoomButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fitZoomButtonActionPerformed(evt);
}
});
jLabel2.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jLabel2.text")); // NOI18N
jLabel2.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jLabel2.text")); // NOI18N
zoomLabel.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomLabel.text")); // NOI18N
zoomLabel.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomLabel.text")); // NOI18N
clearVizButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/broom.png"))); // NOI18N
clearVizButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.text_1")); // NOI18N
clearVizButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.toolTipText")); // NOI18N
clearVizButton.setActionCommand(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.actionCommand")); // NOI18N
clearVizButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
clearVizButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/broom.png"))); // NOI18N
clearVizButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.text_1")); // NOI18N
clearVizButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.toolTipText")); // NOI18N
clearVizButton.setActionCommand(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.actionCommand")); // NOI18N
clearVizButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
clearVizButtonActionPerformed(evt);
}
});
jSeparator2.setOrientation(SwingConstants.VERTICAL);
jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);
backButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_previous.png"))); // NOI18N
backButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N
backButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.toolTipText")); // NOI18N
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
backButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_previous.png"))); // NOI18N
backButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N
backButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.toolTipText")); // NOI18N
backButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
backButtonActionPerformed(evt);
}
});
forwardButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_next.png"))); // NOI18N
forwardButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N
forwardButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.toolTipText")); // NOI18N
forwardButton.setHorizontalTextPosition(SwingConstants.LEADING);
forwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
forwardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_next.png"))); // NOI18N
forwardButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N
forwardButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.toolTipText")); // NOI18N
forwardButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
forwardButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
forwardButtonActionPerformed(evt);
}
});
snapshotButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/report/images/image.png"))); // NOI18N
snapshotButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapshotButton.text_1")); // NOI18N
snapshotButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
snapshotButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/report/images/image.png"))); // NOI18N
snapshotButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapshotButton.text_1")); // NOI18N
snapshotButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
snapshotButtonActionPerformed(evt);
}
});
jSeparator3.setOrientation(SwingConstants.VERTICAL);
jSeparator3.setOrientation(javax.swing.SwingConstants.VERTICAL);
jSeparator4.setOrientation(SwingConstants.VERTICAL);
jSeparator4.setOrientation(javax.swing.SwingConstants.VERTICAL);
GroupLayout toolbarLayout = new GroupLayout(toolbar);
org.jdesktop.layout.GroupLayout toolbarLayout = new org.jdesktop.layout.GroupLayout(toolbar);
toolbar.setLayout(toolbarLayout);
toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING)
toolbarLayout.setHorizontalGroup(
toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(toolbarLayout.createSequentialGroup()
.addContainerGap()
.add(backButton)
.addPreferredGap(LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(forwardButton)
.addPreferredGap(LayoutStyle.RELATED)
.add(jSeparator4, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jSeparator4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(fastOrganicLayoutButton)
.addPreferredGap(LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(clearVizButton)
.addPreferredGap(LayoutStyle.RELATED)
.add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jSeparator2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jLabel2)
.addPreferredGap(LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(zoomLabel)
.addPreferredGap(LayoutStyle.RELATED)
.add(zoomOutButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED)
.add(zoomInButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED)
.add(zoomActualButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED)
.add(fitZoomButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED)
.add(jSeparator3, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(zoomOutButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(zoomInButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(zoomActualButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 33, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(fitZoomButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jSeparator3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(snapshotButton)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
toolbarLayout.setVerticalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING)
toolbarLayout.setVerticalGroup(
toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(toolbarLayout.createSequentialGroup()
.add(3, 3, 3)
.add(toolbarLayout.createParallelGroup(GroupLayout.CENTER)
.add(toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.CENTER)
.add(fastOrganicLayoutButton)
.add(zoomOutButton)
.add(zoomInButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(zoomActualButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(fitZoomButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(zoomInButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(zoomActualButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(fitZoomButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(jLabel2)
.add(zoomLabel)
.add(clearVizButton)
.add(jSeparator2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(jSeparator2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(backButton)
.add(forwardButton)
.add(snapshotButton)
.add(jSeparator3, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(jSeparator4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.add(jSeparator3, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(jSeparator4, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.add(3, 3, 3))
);
borderLayoutPanel.add(toolbar, BorderLayout.PAGE_START);
borderLayoutPanel.add(notificationsJFXPanel, BorderLayout.PAGE_END);
borderLayoutPanel.add(toolbar, java.awt.BorderLayout.PAGE_START);
borderLayoutPanel.add(notificationsJFXPanel, java.awt.BorderLayout.PAGE_END);
splitPane.setLeftComponent(borderLayoutPanel);
add(splitPane, BorderLayout.CENTER);
add(splitPane, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents
private void fitZoomButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_fitZoomButtonActionPerformed
@ -890,26 +880,26 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private JButton backButton;
private JPanel borderLayoutPanel;
private JButton clearVizButton;
private JButton fastOrganicLayoutButton;
private JButton fitZoomButton;
private JButton forwardButton;
private JLabel jLabel2;
private JToolBar.Separator jSeparator2;
private JToolBar.Separator jSeparator3;
private JToolBar.Separator jSeparator4;
private JTextArea jTextArea1;
private JFXPanel notificationsJFXPanel;
private JPanel placeHolderPanel;
private JButton snapshotButton;
private JSplitPane splitPane;
private JPanel toolbar;
private JButton zoomActualButton;
private JButton zoomInButton;
private JLabel zoomLabel;
private JButton zoomOutButton;
private javax.swing.JButton backButton;
private javax.swing.JPanel borderLayoutPanel;
private javax.swing.JButton clearVizButton;
private javax.swing.JButton fastOrganicLayoutButton;
private javax.swing.JButton fitZoomButton;
private javax.swing.JButton forwardButton;
private javax.swing.JLabel jLabel2;
private javax.swing.JToolBar.Separator jSeparator2;
private javax.swing.JToolBar.Separator jSeparator3;
private javax.swing.JToolBar.Separator jSeparator4;
private javax.swing.JTextArea jTextArea1;
private javafx.embed.swing.JFXPanel notificationsJFXPanel;
private javax.swing.JPanel placeHolderPanel;
private javax.swing.JButton snapshotButton;
private javax.swing.JSplitPane splitPane;
private javax.swing.JPanel toolbar;
private javax.swing.JButton zoomActualButton;
private javax.swing.JButton zoomInButton;
private javax.swing.JLabel zoomLabel;
private javax.swing.JButton zoomOutButton;
// End of variables declaration//GEN-END:variables
/**
@ -922,40 +912,25 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
@Override
public void invoke(Object sender, mxEventObject evt) {
Object[] selectionCells = graph.getSelectionCells();
Node rootNode = Node.EMPTY;
Node[] selectedNodes = new Node[0];
if (selectionCells.length > 0) {
mxICell[] selectedCells = Arrays.asList(selectionCells).toArray(new mxCell[selectionCells.length]);
HashSet<Content> relationshipSources = new HashSet<>();
HashSet<AccountDeviceInstanceKey> adis = new HashSet<>();
HashSet<AccountDeviceInstance> deviceInstances = new HashSet<>();
for (mxICell cell : selectedCells) {
if (cell.isEdge()) {
mxICell source = (mxICell) graph.getModel().getTerminal(cell, true);
AccountDeviceInstanceKey account1 = (AccountDeviceInstanceKey) source.getValue();
mxICell target = (mxICell) graph.getModel().getTerminal(cell, false);
AccountDeviceInstanceKey account2 = (AccountDeviceInstanceKey) target.getValue();
try {
final List<Content> relationshipSources1 = commsManager.getRelationshipSources(
account1.getAccountDeviceInstance(),
account2.getAccountDeviceInstance(),
currentFilter);
relationshipSources.addAll(relationshipSources1);
} catch (TskCoreException tskCoreException) {
logger.log(Level.SEVERE, " Error getting relationsips....", tskCoreException);
}
deviceInstances.add(((AccountDeviceInstanceKey) source.getValue()).getAccountDeviceInstance());
deviceInstances.add(((AccountDeviceInstanceKey) target.getValue()).getAccountDeviceInstance());
} else if (cell.isVertex()) {
adis.add((AccountDeviceInstanceKey) cell.getValue());
deviceInstances.add(((AccountDeviceInstanceKey) cell.getValue()).getAccountDeviceInstance());
}
}
rootNode = SelectionNode.createFromAccountsAndRelationships(relationshipSources, adis, currentFilter, commsManager);
selectedNodes = new Node[]{rootNode};
}
vizEM.setRootContext(rootNode);
try {
vizEM.setSelectedNodes(selectedNodes);
} catch (PropertyVetoException ex) {
logger.log(Level.SEVERE, "Selection vetoed.", ex);
relationshipBrowser.setSelectionInfo(new SelectionInfo(deviceInstances, currentFilter));
} else {
relationshipBrowser.setSelectionInfo(new SelectionInfo(Collections.EMPTY_SET, currentFilter));
}
}
}

View File

@ -0,0 +1,108 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountFileInstance;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* ChildFactory that creates ContentNode representing the files that reference
* the given list of accounts.
*/
final class AccountSourceContentChildNodeFactory extends ChildFactory<Content> {
private static final Logger logger = Logger.getLogger(AccountSourceContentChildNodeFactory.class.getName());
private final Set<Account> accounts;
AccountSourceContentChildNodeFactory(Set<Account> accounts) {
this.accounts = accounts;
}
@Override
protected boolean createKeys(List<Content> list) {
if (accounts == null || accounts.isEmpty()) {
return true;
}
CommunicationsManager communicationManager;
try {
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.WARNING, "Failed to get communications manager from case.", ex); //NON-NLS
return false;
}
accounts.forEach((account) -> {
try {
List<AccountFileInstance> accountFileInstanceList = communicationManager.getAccountFileInstances(account);
for (AccountFileInstance fileInstance : accountFileInstanceList) {
list.add(fileInstance.getFile());
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Failed to getAccountFileInstances for account: %d", account.getAccountID()), ex); //NON-NLS
}
});
return true;
}
@Override
protected Node createNodeForKey(Content content) {
return new ContentNode(content);
}
/**
* Simple AbstractNode for a Content (file) object.
*/
final class ContentNode extends AbstractNode {
private final Content content;
ContentNode(Content content) {
super(Children.LEAF);
this.content = content;
try {
setDisplayName(content.getUniquePath());
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Unable to getUniquePath for Content: %d", content.getId()), ex); //NON-NLS
setDisplayName(content.getName());
}
setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon.png"); //NON-NLS
}
}
}

View File

@ -0,0 +1,127 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Factory for creating thumbnail children nodes.
*/
final class AttachmentsChildren extends Children.Keys<AbstractFile> {
private static final Logger logger = Logger.getLogger(AttachmentsChildren.class.getName());
private final Set<BlackboardArtifact> artifacts;
/*
* Creates the list of thumbnails from the given list of
* BlackboardArtifacts.
*
* The thumbnails will be initialls sorted by size, then name so that they
* appear sorted by size by default.
*/
AttachmentsChildren(Set<BlackboardArtifact> artifacts) {
super(false);
this.artifacts = artifacts;
}
@Override
protected Node[] createNodes(AbstractFile t) {
return new Node[]{new AttachementNode(t)};
}
@Override
protected void addNotify() {
super.addNotify();
Set<AbstractFile> thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> {
int result = Long.compare(file1.getSize(), file2.getSize());
if (result == 0) {
result = file1.getName().compareTo(file2.getName());
}
return result;
});
artifacts.forEach((bba) -> {
try {
for (Content childContent : bba.getChildren()) {
if (childContent instanceof AbstractFile) {
thumbnails.add((AbstractFile) childContent);
}
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS
}
});
setKeys(thumbnails);
}
/**
* A node for representing a thumbnail.
*/
static class AttachementNode extends FileNode {
AttachementNode(AbstractFile file) {
super(file, false);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Set<String> keepProps = new HashSet<>(Arrays.asList(
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
//Remove all other props except for the ones above
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
for (Node.Property<?> p : sheetSet.getProperties()) {
if (!keepProps.contains(p.getName())) {
sheetSet.remove(p.getName());
}
}
return sheet;
}
}
}

View File

@ -0,0 +1,15 @@
ContactDetailsPane.nameLabel.text=Placeholder
SummaryViewer.countsPanel.border.title=Counts
SummaryViewer.emailLabel.text=Emails:
SummaryViewer.contactsLabel.text=Contacts:
SummaryViewer.attachmentsLabel.text=Attachments:
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
OutlineViewPanel.messageLabel.text=<Control Disabled>
SummaryViewer.messagesDataLabel.text=messages
SummaryViewer.callLogsDataLabel.text=callLogs
SummaryViewer.contactsDataLabel.text=contacts
SummaryViewer.emailDataLabel.text=emails
SummaryViewer.attachmentsDataLabel.text=attachments
SummaryViewer.messagesLabel.text=Messages:
SummaryViewer.callLogsLabel.text=Call Logs:

View File

@ -0,0 +1,44 @@
ContactDetailsPane.nameLabel.text=Placeholder
ContactNode_Email=Email Address
ContactNode_Home_Number=Home Number
ContactNode_Mobile_Number=Mobile Number
ContactNode_Name=Name
ContactNode_Office_Number=Office Number
ContactNode_Phone=Phone Number
ContactNode_URL=URL
ContactsViewer_columnHeader_Email=Email
ContactsViewer_columnHeader_Name=Name
ContactsViewer_columnHeader_Phone=Phone
ContactsViewer_tabTitle=Contacts
MediaViewer_Name=Media
MessageNode_Node_Property_Attms=Attachments
MessageNode_Node_Property_Date=Date
MessageNode_Node_Property_From=From
MessageNode_Node_Property_Subject=Subject
MessageNode_Node_Property_To=To
MessageNode_Node_Property_Type=Type
MessageViewer_columnHeader_Attms=Attachments
MessageViewer_columnHeader_Date=Date
MessageViewer_columnHeader_From=From
MessageViewer_columnHeader_Subject=Subject
MessageViewer_columnHeader_To=To
MessageViewer_tabTitle=Messages
SummaryViewer.countsPanel.border.title=Counts
SummaryViewer.emailLabel.text=Emails:
SummaryViewer.contactsLabel.text=Contacts:
SummaryViewer.attachmentsLabel.text=Attachments:
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
OutlineViewPanel.messageLabel.text=<Control Disabled>
SummaryViewer.messagesDataLabel.text=messages
SummaryViewer.callLogsDataLabel.text=callLogs
SummaryViewer.contactsDataLabel.text=contacts
SummaryViewer.emailDataLabel.text=emails
SummaryViewer.attachmentsDataLabel.text=attachments
SummaryViewer.messagesLabel.text=Messages:
SummaryViewer.callLogsLabel.text=Call Logs:
SummaryViewer_CaseRefNameColumn_Title=Case Name
SummaryViewer_CentralRepository_Message=<Enable Central Resposity to see Case References>
SummaryViewer_Creation_Date_Title=Creation Date
SummaryViewer_FileRefNameColumn_Title=Path
SummaryViewer_TabTitle=Summary

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="messageContentViewer1">
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="propertySheet" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="propertySheet" pref="283" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="nameLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="ContactDetailsPane.nameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="org.openide.explorer.propertysheet.PropertySheet" name="propertySheet">
<Properties>
<Property name="descriptionAreaVisible" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,116 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.Node;
/**
* Displays the propertied of a ContactNode in a PropertySheet.
*/
public final class ContactDetailsPane extends javax.swing.JPanel implements ExplorerManager.Provider {
final private ExplorerManager explorerManager = new ExplorerManager();
/**
* Displays the propertied of a ContactNode in a PropertySheet.
*/
public ContactDetailsPane() {
initComponents();
this.setEnabled(false);
nameLabel.setText("");
}
/**
* Sets the list of nodes for the property sheet.
*
* @param nodes List of nodes to set
*/
public void setNode(Node[] nodes) {
if (nodes != null && nodes.length == 1) {
nameLabel.setText(nodes[0].getDisplayName());
propertySheet.setNodes(nodes);
} else {
nameLabel.setText("");
propertySheet.setNodes(null);
}
}
@Override
public ExplorerManager getExplorerManager() {
return explorerManager;
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
nameLabel.setEnabled(enabled);
propertySheet.setEnabled(enabled);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
messageContentViewer1 = new org.sleuthkit.autopsy.contentviewers.MessageContentViewer();
nameLabel = new javax.swing.JLabel();
propertySheet = new org.openide.explorer.propertysheet.PropertySheet();
nameLabel.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(ContactDetailsPane.class, "ContactDetailsPane.nameLabel.text")); // NOI18N
propertySheet.setDescriptionAreaVisible(false);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(propertySheet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(nameLabel)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(nameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(propertySheet, javax.swing.GroupLayout.DEFAULT_SIZE, 283, Short.MAX_VALUE)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer messageContentViewer1;
private javax.swing.JLabel nameLabel;
private org.openide.explorer.propertysheet.PropertySheet propertySheet;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,161 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.logging.Level;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON;
import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME;
import org.sleuthkit.datamodel.TimeUtilities;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.communications.Utils;
/**
* Extends BlackboardArtifactNode to override createSheet to create a contact
* artifact specific sheet.
*/
final class ContactNode extends BlackboardArtifactNode {
private static final Logger logger = Logger.getLogger(ContactNode.class.getName());
@Messages({
"ContactNode_Name=Name",
"ContactNode_Phone=Phone Number",
"ContactNode_Email=Email Address",
"ContactNode_Mobile_Number=Mobile Number",
"ContactNode_Office_Number=Office Number",
"ContactNode_URL=URL",
"ContactNode_Home_Number=Home Number",})
ContactNode(BlackboardArtifact artifact) {
super(artifact);
String name = getAttributeDisplayString(artifact, TSK_NAME);
if (name == null || name.trim().isEmpty()) {
// VCards use TSK_NAME_PERSON instead of TSK_NAME
name = getAttributeDisplayString(artifact, TSK_NAME_PERSON);
}
setDisplayName(name);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
final BlackboardArtifact artifact = getArtifact();
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
if (fromID != TSK_CONTACT) {
return sheet;
}
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
// Sorting the attributes by type so that the duplicates can be removed
// and they can be grouped by type for display. The attribute prefixes
// are used so that all attributed of that type are found, including
// ones that are not predefined as part of BlackboardAttributes
try {
HashMap<String, BlackboardAttribute> phoneNumMap = new HashMap<>();
HashMap<String, BlackboardAttribute> emailMap = new HashMap<>();
HashMap<String, BlackboardAttribute> nameMap = new HashMap<>();
HashMap<String, BlackboardAttribute> otherMap = new HashMap<>();
for (BlackboardAttribute bba : artifact.getAttributes()) {
if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) {
phoneNumMap.put(bba.getDisplayString(), bba);
} else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) {
emailMap.put(bba.getDisplayString(), bba);
} else if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) {
nameMap.put(bba.getDisplayString(), bba);
} else {
otherMap.put(bba.getDisplayString(), bba);
}
}
addPropertiesToSheet(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getLabel(),
sheetSet, nameMap);
addPropertiesToSheet(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getLabel(),
sheetSet, phoneNumMap);
addPropertiesToSheet(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getLabel(),
sheetSet, emailMap);
for (BlackboardAttribute bba : otherMap.values()) {
sheetSet.put(new NodeProperty<>(bba.getAttributeType().getTypeName(), bba.getAttributeType().getDisplayName(), "", bba.getDisplayString()));
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error getting attribute values.", ex); //NON-NLS
}
return sheet;
}
private void addPropertiesToSheet(String propertyID, Sheet.Set sheetSet, Map<String, BlackboardAttribute> attributeMap) {
int count = 0;
for (BlackboardAttribute bba : attributeMap.values()) {
if (count++ > 0) {
sheetSet.put(new NodeProperty<>(propertyID + "_" + count, bba.getAttributeType().getDisplayName(), "", bba.getDisplayString()));
} else {
sheetSet.put(new NodeProperty<>(propertyID, bba.getAttributeType().getDisplayName(), "", bba.getDisplayString()));
}
}
}
private static String getAttributeDisplayString(final BlackboardArtifact artifact, final BlackboardAttribute.ATTRIBUTE_TYPE attributeType) {
try {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attributeType.getTypeID())));
if (attribute == null) {
return "";
} else if (attributeType.getValueType() == DATETIME) {
return TimeUtilities.epochToTime(attribute.getValueLong(),
TimeZone.getTimeZone(Utils.getUserPreferredZoneId()));
} else {
return attribute.getDisplayString();
}
} catch (TskCoreException tskCoreException) {
logger.log(Level.WARNING, "Error getting attribute value.", tskCoreException); //NON-NLS
return "";
}
}
/**
* Circumvent DataResultFilterNode's slightly odd delegation to
* BlackboardArtifactNode.getSourceName().
*
* @return the displayName of this Node, which is the type.
*/
@Override
public String getSourceName() {
return getDisplayName();
}
}

View File

@ -0,0 +1,109 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* ChildFactory for ContactNodes.
*/
final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName());
private SelectionInfo selectionInfo;
/**
* Construct a new ContactsChildNodeFactory from the currently selectionInfo
*
* @param selectionInfo SelectionInfo object for the currently selected
* accounts
*/
ContactsChildNodeFactory(SelectionInfo selectionInfo) {
this.selectionInfo = selectionInfo;
}
/**
* Updates the current instance of selectionInfo and calls the refresh method.
*
* @param selectionInfo New instance of the currently selected accounts
*/
public void refresh(SelectionInfo selectionInfo) {
this.selectionInfo = selectionInfo;
refresh(true);
}
/**
* Creates a list of Keys (BlackboardArtifact) for only contacts of the
* currently selected accounts
* @param list List of BlackboardArtifact to populate
* @return True on success
*/
@Override
protected boolean createKeys(List<BlackboardArtifact> list) {
CommunicationsManager communicationManager;
try {
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS
return false;
}
if(selectionInfo == null) {
return true;
}
final Set<Content> relationshipSources;
try {
relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter());
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
BlackboardArtifact bba = (BlackboardArtifact) content;
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
if (fromID == TSK_CONTACT) {
list.add(bba);
}
});
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
}
return true;
}
@Override
protected Node createNodeForKey(BlackboardArtifact key) {
return new ContactNode(key);
}
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="outlineView" max="32767" attributes="0"/>
<Component id="contactPane" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="outlineView" pref="350" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
<Component id="contactPane" pref="400" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.openide.explorer.view.OutlineView()"/>
</AuxValues>
</Component>
<Component class="org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane" name="contactPane">
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,186 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import static javax.swing.SwingUtilities.isDescendingFrom;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.openide.explorer.ExplorerManager;
import static org.openide.explorer.ExplorerUtils.createLookup;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
import org.sleuthkit.datamodel.BlackboardAttribute;
/**
* Visualization for contact nodes.
*
*/
@ServiceProvider(service = RelationshipsViewer.class)
public final class ContactsViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider {
private final ExplorerManager tableEM;
private final Outline outline;
private final ModifiableProxyLookup proxyLookup;
private final PropertyChangeListener focusPropertyListener;
private final ContactsChildNodeFactory nodeFactory;
@NbBundle.Messages({
"ContactsViewer_tabTitle=Contacts",
"ContactsViewer_columnHeader_Name=Name",
"ContactsViewer_columnHeader_Phone=Phone",
"ContactsViewer_columnHeader_Email=Email",})
/**
* Visualization for contact nodes.
*/
public ContactsViewer() {
tableEM = new ExplorerManager();
proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap()));
nodeFactory = new ContactsChildNodeFactory(null);
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
// explaination of focusPropertyListener
focusPropertyListener = (final PropertyChangeEvent focusEvent) -> {
if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) {
final Component newFocusOwner = (Component) focusEvent.getNewValue();
if (newFocusOwner == null) {
return;
}
if (isDescendingFrom(newFocusOwner, contactPane)) {
//if the focus owner is within the MessageContentViewer (the attachments table)
proxyLookup.setNewLookups(createLookup(contactPane.getExplorerManager(), getActionMap()));
} else if (isDescendingFrom(newFocusOwner, ContactsViewer.this)) {
//... or if it is within the Results table.
proxyLookup.setNewLookups(createLookup(tableEM, getActionMap()));
}
}
};
initComponents();
outline = outlineView.getOutline();
outlineView.setPropertyColumns(
"TSK_EMAIL", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getDisplayName(),
"TSK_PHONE_NUMBER", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getDisplayName()
);
outline.setRootVisible(false);
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.ContactsViewer_columnHeader_Name());
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
final Node[] nodes = tableEM.getSelectedNodes();
contactPane.setNode(nodes);
}
});
tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(nodeFactory, true)), getExplorerManager()), true));
}
@Override
public String getDisplayName() {
return Bundle.ContactsViewer_tabTitle();
}
@Override
public JPanel getPanel() {
return this;
}
@Override
public void setSelectionInfo(SelectionInfo info) {
contactPane.setNode(new Node[]{new AbstractNode(Children.LEAF)});
contactPane.setEnabled(false);
nodeFactory.refresh(info);
}
@Override
public ExplorerManager getExplorerManager() {
return tableEM;
}
@Override
public Lookup getLookup() {
return proxyLookup;
}
@Override
public void addNotify() {
super.addNotify();
//add listener that maintains correct selection in the Global Actions Context
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("focusOwner", focusPropertyListener);
}
@Override
public void removeNotify() {
super.removeNotify();
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.removePropertyChangeListener("focusOwner", focusPropertyListener);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
outlineView = new org.openide.explorer.view.OutlineView();
contactPane = new org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane();
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(contactPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE)
.addGap(1, 1, 1)
.addComponent(contactPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane contactPane;
private org.openide.explorer.view.OutlineView outlineView;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,169 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.Account;
/**
* ChildFactory for CorrelationCases. Finds the cases that reference the given
* list of accounts.
*/
final class CorrelationCaseChildNodeFactory extends ChildFactory<CorrelationCase> {
private static final Logger logger = Logger.getLogger(CorrelationCaseChildNodeFactory.class.getName());
private Map<Integer, CorrelationAttributeInstance.Type> correlationTypeMap;
private final Set<Account> accounts;
/**
* ChildFactory for CorrelationCases.
*
* @param accounts List of Account objects
*/
CorrelationCaseChildNodeFactory(Set<Account> accounts) {
this.accounts = accounts;
}
@Override
protected boolean createKeys(List<CorrelationCase> list) {
if (!EamDb.isEnabled()) {
return true;
}
EamDb dbInstance;
try {
dbInstance = EamDb.getInstance();
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Unable to connect to the Central Repository database.", ex); //NON-NLS
return false;
}
Map<String, CorrelationCase> uniqueCaseMap = new HashMap<>();
accounts.forEach((account) -> {
try {
CorrelationAttributeInstance.Type correlationType = getCorrelationType(account.getAccountType());
if (correlationType != null) {
List<CorrelationAttributeInstance> correlationInstances = dbInstance.getArtifactInstancesByTypeValue(correlationType, account.getTypeSpecificID());
correlationInstances.forEach((correlationInstance) -> {
CorrelationCase correlationCase = correlationInstance.getCorrelationCase();
uniqueCaseMap.put(correlationCase.getCaseUUID(), correlationCase);
});
}
} catch (EamDbException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, String.format("Unable to getArtifactInstance for accountID: %d", account.getAccountID()), ex); //NON-NLS
}
});
list.addAll(uniqueCaseMap.values());
return true;
}
@Override
protected Node createNodeForKey(CorrelationCase correlationCase) {
return new CaseNode(correlationCase);
}
/**
* Find the CorrelationAttributeInstance.Type for the given Account.Type.
*
* @param accountType Account type
*
* @return CorrelationAttributeInstance.Type for given account or null if
* there is no match
*
* @throws EamDbException
*/
private CorrelationAttributeInstance.Type getCorrelationType(Account.Type accountType) throws EamDbException {
if (correlationTypeMap == null) {
correlationTypeMap = new HashMap<>();
List<CorrelationAttributeInstance.Type> correcationTypeList = CorrelationAttributeInstance.getDefaultCorrelationTypes();
correcationTypeList.forEach((type) -> {
correlationTypeMap.put(type.getId(), type);
});
}
if (Account.Type.EMAIL.equals(accountType)) {
return correlationTypeMap.get(CorrelationAttributeInstance.EMAIL_TYPE_ID);
} else if (Account.Type.PHONE.equals(accountType)) {
return correlationTypeMap.get(CorrelationAttributeInstance.PHONE_TYPE_ID);
} else {
return null;
}
}
/**
* Simple AbstractNode for a CorrelationCase. The property sheet only
* contains the creation date.
*/
final class CaseNode extends AbstractNode {
private final CorrelationCase correlationCase;
/**
* Construct the object, set the display name and icon.
*
* @param correlationCase
*/
CaseNode(CorrelationCase correlationCase) {
super(Children.LEAF);
this.correlationCase = correlationCase;
setDisplayName(correlationCase.getDisplayName());
setIconBaseWithExtension("org/sleuthkit/autopsy/images/briefcase.png"); //NON-NLS
}
@Override
protected Sheet createSheet() {
super.createSheet();
Sheet sheet = new Sheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>("creationDate", //NON-NLS
correlationCase.getTitleCreationDate(),
correlationCase.getTitleCreationDate(),
correlationCase.getCreationDate()));
return sheet;
}
}
}

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="thumbnailViewer" alignment="1" max="32767" attributes="0"/>
<Component id="contentViewer" alignment="1" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="separator" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="thumbnailViewer" pref="350" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="separator" min="-2" pref="2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="contentViewer" min="-2" pref="450" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail" name="thumbnailViewer">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[350, 102]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[450, 400]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM)"/>
</AuxValues>
</Component>
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[450, 400]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
</AuxValues>
</Component>
<Component class="javax.swing.JSeparator" name="separator">
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,233 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JPanel;
import static javax.swing.SwingUtilities.isDescendingFrom;
import org.openide.explorer.ExplorerManager;
import static org.openide.explorer.ExplorerUtils.createLookup;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
import org.sleuthkit.datamodel.AbstractContent;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A Panel that shows the media (thumbnails) for the selected account.
*/
final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider {
private static final Logger logger = Logger.getLogger(MediaViewer.class.getName());
private final ExplorerManager tableEM = new ExplorerManager();
private final PropertyChangeListener focusPropertyListener;
private final ModifiableProxyLookup proxyLookup;
@Messages({
"MediaViewer_Name=Media"
})
/**
* Creates new form ThumbnailViewer
*/
public MediaViewer() {
proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap()));
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
// explaination of focusPropertyListener
focusPropertyListener = (final PropertyChangeEvent focusEvent) -> {
if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) {
final Component newFocusOwner = (Component) focusEvent.getNewValue();
if (newFocusOwner == null) {
return;
}
if (isDescendingFrom(newFocusOwner, contentViewer)) {
//if the focus owner is within the MessageContentViewer (the attachments table)
proxyLookup.setNewLookups(createLookup(((MessageDataContent) contentViewer).getExplorerManager(), getActionMap()));
} else if (isDescendingFrom(newFocusOwner, MediaViewer.this)) {
//... or if it is within the Results table.
proxyLookup.setNewLookups(createLookup(tableEM, getActionMap()));
}
}
};
initComponents();
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
handleNodeSelectionChange();
}
});
thumbnailViewer.resetComponent();
}
@Override
public String getDisplayName() {
return Bundle.MediaViewer_Name();
}
@Override
public JPanel getPanel() {
return this;
}
@Override
public void setSelectionInfo(SelectionInfo info) {
final Set<Content> relationshipSources;
CommunicationsManager communicationManager;
Set<BlackboardArtifact> artifactList = new HashSet<>();
try {
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
relationshipSources = communicationManager.getRelationshipSources(info.getAccountDevicesInstances(), info.getCommunicationsFilter());
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
artifactList.add((BlackboardArtifact) content);
});
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to update selection." , ex);
}
if(artifactList.size() == 0) {
thumbnailViewer.resetComponent();
}
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentsChildren(artifactList)), tableEM), true, this.getClass().getName()));
}
@Override
public ExplorerManager getExplorerManager() {
return tableEM;
}
@Override
public Lookup getLookup() {
return proxyLookup;
}
@Override
public void addNotify() {
super.addNotify();
//add listener that maintains correct selection in the Global Actions Context
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("focusOwner", focusPropertyListener);
}
@Override
public void removeNotify() {
super.removeNotify();
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.removePropertyChangeListener("focusOwner", focusPropertyListener);
}
/**
* Handle the change in thumbnail node selection.
*/
private void handleNodeSelectionChange() {
final Node[] nodes = tableEM.getSelectedNodes();
if (nodes != null && nodes.length == 1) {
AbstractContent thumbnail = nodes[0].getLookup().lookup(AbstractContent.class);
if (thumbnail != null) {
try {
Content parentContent = thumbnail.getParent();
if (parentContent != null && parentContent instanceof BlackboardArtifact) {
contentViewer.setNode(new BlackboardArtifactNode((BlackboardArtifact) parentContent));
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get parent Content from AbstraceContent instance.", ex); //NON-NLS
}
}
} else {
contentViewer.setNode(null);
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
thumbnailViewer = new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM);
contentViewer = new MessageDataContent();
separator = new javax.swing.JSeparator();
thumbnailViewer.setMinimumSize(new java.awt.Dimension(350, 102));
thumbnailViewer.setPreferredSize(new java.awt.Dimension(450, 400));
contentViewer.setPreferredSize(new java.awt.Dimension(450, 400));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(thumbnailViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(contentViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(separator)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(thumbnailViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(contentViewer, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(3, 3, 3))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer;
private javax.swing.JSeparator separator;
private org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail thumbnailViewer;
// End of variables declaration//GEN-END:variables
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
package org.sleuthkit.autopsy.communications.relationships;
import java.beans.PropertyChangeEvent;
import org.openide.explorer.ExplorerManager;

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017-2018 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
package org.sleuthkit.autopsy.communications.relationships;
import java.util.List;
import java.util.TimeZone;
@ -25,12 +25,12 @@ import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.Sheet;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START;
@ -43,24 +43,35 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBU
import org.sleuthkit.datamodel.Tag;
import org.sleuthkit.datamodel.TimeUtilities;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.communications.Utils;
/**
* Node for a relationship, as represented by a BlackboardArtifact.
* Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView
*/
final class RelationshipNode extends BlackboardArtifactNode {
final class MessageNode extends BlackboardArtifactNode {
private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName());
private static final Logger logger = Logger.getLogger(MessageNode.class.getName());
RelationshipNode(BlackboardArtifact artifact) {
MessageNode(BlackboardArtifact artifact) {
super(artifact);
final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s");
String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message");
final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS
String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS
setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase);
}
@Messages({
"MessageNode_Node_Property_Type=Type",
"MessageNode_Node_Property_From=From",
"MessageNode_Node_Property_To=To",
"MessageNode_Node_Property_Date=Date",
"MessageNode_Node_Property_Subject=Subject",
"MessageNode_Node_Property_Attms=Attachments"
})
@Override
protected Sheet createSheet() {
Sheet sheet = new Sheet();
Sheet sheet = super.createSheet();
List<Tag> tags = getAllTagsFromDatabase();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
@ -68,62 +79,63 @@ final class RelationshipNode extends BlackboardArtifactNode {
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>("Type", "Type", "Type", getDisplayName()));
sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS
addScoreProperty(sheetSet, tags);
CorrelationAttributeInstance correlationAttribute = null;
if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
correlationAttribute = getCorrelationAttributeInstance();
}
addCommentProperty(sheetSet, tags, correlationAttribute);
if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
addCountProperty(sheetSet, correlationAttribute);
}
final BlackboardArtifact artifact = getArtifact();
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(getArtifact().getArtifactTypeID());
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
if (null != fromID) {
//Consider refactoring this to reduce boilerplate
switch (fromID) {
case TSK_EMAIL_MSG:
sheetSet.put(new NodeProperty<>("From", "From", "From",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;")));
sheetSet.put(new NodeProperty<>("To", "To", "To",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;")));
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
getAttributeDisplayString(artifact, TSK_DATETIME_SENT)));
sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject",
getAttributeDisplayString(artifact, TSK_SUBJECT)));
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
try {
sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount()));
sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", artifact.getChildrenCount())); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex);
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS
}
break;
case TSK_MESSAGE:
sheetSet.put(new NodeProperty<>("From", "From", "From",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM)));
sheetSet.put(new NodeProperty<>("To", "To", "To",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO)));
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
getAttributeDisplayString(artifact, TSK_DATETIME)));
sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject",
getAttributeDisplayString(artifact, TSK_SUBJECT)));
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
try {
sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount()));
sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", artifact.getChildrenCount())); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex);
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS
}
break;
case TSK_CALLLOG:
sheetSet.put(new NodeProperty<>("From", "From", "From",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM)));
sheetSet.put(new NodeProperty<>("To", "To", "To",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO)));
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
getAttributeDisplayString(artifact, TSK_DATETIME_START)));
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
getAttributeDisplayString(artifact, TSK_DATETIME_START))); //NON-NLS
break;
default:
break;
@ -144,7 +156,7 @@ final class RelationshipNode extends BlackboardArtifactNode {
* @return The display string, or an empty string if there is no such
* attribute or an an error.
*/
private static String getAttributeDisplayString(final BlackboardArtifact artifact, final ATTRIBUTE_TYPE attributeType) {
private static String getAttributeDisplayString(final BlackboardArtifact artifact, final BlackboardAttribute.ATTRIBUTE_TYPE attributeType) {
try {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attributeType.getTypeID())));
if (attribute == null) {
@ -156,7 +168,7 @@ final class RelationshipNode extends BlackboardArtifactNode {
return attribute.getDisplayString();
}
} catch (TskCoreException tskCoreException) {
logger.log(Level.WARNING, "Error getting attribute value.", tskCoreException);
logger.log(Level.WARNING, "Error getting attribute value.", tskCoreException); //NON-NLS
return "";
}
}

View File

@ -0,0 +1,115 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* ChildFactory that creates createKeys and nodes from a given selectionInfo for
* only emails, call logs and messages.
*
*/
final class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact> {
private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName());
private SelectionInfo selectionInfo;
/**
* Construct a new MessageChildNodeFactory from the currently selectionInfo
*
* @param selectionInfo SelectionInfo object for the currently selected
* accounts
*/
MessagesChildNodeFactory(SelectionInfo selectionInfo) {
this.selectionInfo = selectionInfo;
}
/**
* Updates the current instance of selectionInfo and calls the refresh method.
*
* @param selectionInfo New instance of the currently selected accounts
*/
public void refresh(SelectionInfo selectionInfo) {
this.selectionInfo = selectionInfo;
refresh(true);
}
/**
* Creates a list of Keys (BlackboardArtifact) for only messages for the
* currently selected accounts
*
* @param list List of BlackboardArtifact to populate
*
* @return True on success
*/
@Override
protected boolean createKeys(List<BlackboardArtifact> list) {
CommunicationsManager communicationManager;
try {
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS
return false;
}
if(selectionInfo == null) {
return true;
}
final Set<Content> relationshipSources;
try {
relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter());
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
BlackboardArtifact bba = (BlackboardArtifact) content;
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
list.add(bba);
}
});
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
}
return true;
}
@Override
protected Node createNodeForKey(BlackboardArtifact key) {
return new MessageNode(key);
}
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="outlineView" alignment="0" max="32767" attributes="0"/>
<Component id="contentViewer" alignment="1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="outlineView" pref="300" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="contentViewer" pref="500" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
</Component>
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
</AuxValues>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,194 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import static javax.swing.SwingUtilities.isDescendingFrom;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.openide.explorer.ExplorerManager;
import static org.openide.explorer.ExplorerUtils.createLookup;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
/**
* Visualation for the messages of the currently selected accounts.
*/
@ServiceProvider(service = RelationshipsViewer.class)
public final class MessagesViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider {
private final ExplorerManager tableEM;
private final Outline outline;
private final ModifiableProxyLookup proxyLookup;
private final PropertyChangeListener focusPropertyListener;
private final MessagesChildNodeFactory nodeFactory;
@Messages({
"MessageViewer_tabTitle=Messages",
"MessageViewer_columnHeader_From=From",
"MessageViewer_columnHeader_To=To",
"MessageViewer_columnHeader_Date=Date",
"MessageViewer_columnHeader_Subject=Subject",
"MessageViewer_columnHeader_Attms=Attachments"
})
/**
* Visualation for the messages of the currently selected accounts.
*/
public MessagesViewer() {
tableEM = new ExplorerManager();
proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap()));
nodeFactory = new MessagesChildNodeFactory(null);
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
// explaination of focusPropertyListener
focusPropertyListener = (final PropertyChangeEvent focusEvent) -> {
if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) {
final Component newFocusOwner = (Component) focusEvent.getNewValue();
if (newFocusOwner == null) {
return;
}
if (isDescendingFrom(newFocusOwner, contentViewer)) {
//if the focus owner is within the MessageContentViewer (the attachments table)
proxyLookup.setNewLookups(createLookup(((MessageDataContent) contentViewer).getExplorerManager(), getActionMap()));
} else if (isDescendingFrom(newFocusOwner, MessagesViewer.this)) {
//... or if it is within the Results table.
proxyLookup.setNewLookups(createLookup(tableEM, getActionMap()));
}
}
};
initComponents();
outline = outlineView.getOutline();
outlineView.setPropertyColumns(
"From", Bundle.MessageViewer_columnHeader_From(),
"To", Bundle.MessageViewer_columnHeader_To(),
"Date", Bundle.MessageViewer_columnHeader_Date(),
"Subject", Bundle.MessageViewer_columnHeader_Subject(),
"Attms", Bundle.MessageViewer_columnHeader_Attms(),
"Type", "Type"
);
outline.setRootVisible(false);
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel("Type");
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
final Node[] nodes = tableEM.getSelectedNodes();
if (nodes != null && nodes.length == 1) {
contentViewer.setNode(nodes[0]);
}
else {
contentViewer.setNode(null);
}
}
});
tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(nodeFactory, true)), getExplorerManager()), true));
}
@Override
public String getDisplayName() {
return Bundle.MessageViewer_tabTitle();
}
@Override
public JPanel getPanel() {
return this;
}
@Override
public void setSelectionInfo(SelectionInfo info) {
nodeFactory.refresh(info);
}
@Override
public ExplorerManager getExplorerManager() {
return tableEM;
}
@Override
public Lookup getLookup() {
return proxyLookup;
}
@Override
public void addNotify() {
super.addNotify();
//add listener that maintains correct selection in the Global Actions Context
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("focusOwner", focusPropertyListener);
}
@Override
public void removeNotify() {
super.removeNotify();
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.removePropertyChangeListener("focusOwner", focusPropertyListener);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
outlineView = new org.openide.explorer.view.OutlineView();
contentViewer = new MessageDataContent();
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(contentViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer;
private org.openide.explorer.view.OutlineView outlineView;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-45,0,0,1,-32"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout">
<Property name="horizontalGap" type="int" value="5"/>
<Property name="verticalGap" type="int" value="5"/>
</Layout>
<SubComponents>
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 400]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="outlineCard"/>
</Constraint>
</Constraints>
</Component>
<Container class="javax.swing.JPanel" name="messagePanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="messageCard"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="messageLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="OutlineViewPanel.messageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,132 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.awt.CardLayout;
import org.openide.explorer.ExplorerManager;
import static org.openide.explorer.ExplorerUtils.createLookup;
import org.openide.explorer.view.OutlineView;
import org.openide.nodes.Node;;
import org.openide.util.Lookup;
/**
* This class is a simple wrapper around a OutlineView with its own ExplorerManager.
*
* This panel has the added feature of being able to hide the OutlineView and show
* a message.
*
*/
public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerManager.Provider, Lookup.Provider{
private final ExplorerManager tableEm;
private final Lookup lookup;
/**
* Creates new form OutlineViewPanel
*/
public OutlineViewPanel() {
tableEm = new ExplorerManager();
lookup = createLookup(tableEm, getActionMap());
initComponents();
}
@Override
public ExplorerManager getExplorerManager() {
return tableEm;
}
@Override
public Lookup getLookup() {
return lookup;
}
/**
* Hide the OutlineView and replace with a panel with the given message.
*
* @param message String message to show on the panel.
*/
public void hideOutlineView(String message) {
CardLayout layout = (CardLayout)this.getLayout();
layout.show(this, "messageCard"); //NON-NLS
messageLabel.setText(message);
}
/**
* Hides the message panel and shows the OutlineView.
*/
public void showOutlineView() {
CardLayout layout = (CardLayout)this.getLayout();
layout.show(this, "outlineCard"); //NON-NLS
}
/**
* Returns the OutlineView instance for ease of customization.
*
* @return Returns the OutlineView
*/
public OutlineView getOutlineView() {
return outlineView;
}
public void setNode(Node node) {
tableEm.setRootContext(node);
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
outlineView.setEnabled(enabled);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
outlineView = new org.openide.explorer.view.OutlineView();
messagePanel = new javax.swing.JPanel();
messageLabel = new javax.swing.JLabel();
setLayout(new java.awt.CardLayout(5, 5));
outlineView.setPreferredSize(new java.awt.Dimension(300, 400));
add(outlineView, "outlineCard");
messagePanel.setLayout(new java.awt.BorderLayout());
messageLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
org.openide.awt.Mnemonics.setLocalizedText(messageLabel, org.openide.util.NbBundle.getMessage(OutlineViewPanel.class, "OutlineViewPanel.messageLabel.text")); // NOI18N
messageLabel.setEnabled(false);
messagePanel.add(messageLabel, java.awt.BorderLayout.CENTER);
add(messagePanel, "messageCard");
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel messageLabel;
private javax.swing.JPanel messagePanel;
private org.openide.explorer.view.OutlineView outlineView;
// End of variables declaration//GEN-END:variables
}

View File

@ -5,7 +5,7 @@
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
@ -16,40 +16,36 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="splitPane" max="32767" attributes="0"/>
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Component id="scrollPane" alignment="1" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="splitPane" pref="1083" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Component id="scrollPane" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JSplitPane" name="splitPane">
<Container class="javax.swing.JScrollPane" name="scrollPane">
<Properties>
<Property name="dividerLocation" type="int" value="400"/>
<Property name="dividerSize" type="int" value="10"/>
<Property name="orientation" type="int" value="0"/>
<Property name="resizeWeight" type="double" value="0.5"/>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="org.sleuthkit.autopsy.communications.MessageDataContent" name="messageDataContent">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="bottom"/>
</Constraint>
</Constraints>
</Component>
<Container class="javax.swing.JTabbedPane" name="tabPane">
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabPaneStateChanged"/>
</Events>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container>
</SubComponents>
</Container>
</SubComponents>

View File

@ -0,0 +1,132 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.awt.Component;
import javax.swing.JPanel;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
/**
* Displays the Relationship information for the currently selected accounts.
*
*/
public final class RelationshipBrowser extends JPanel implements Lookup.Provider {
private SelectionInfo currentSelection;
private final MessagesViewer messagesViewer;
private final ContactsViewer contactsViewer;
private final SummaryViewer summaryViewer;
private final MediaViewer mediaViewer;
private final ModifiableProxyLookup proxyLookup;
/**
* Creates new form RelationshipBrowser
*/
public RelationshipBrowser() {
messagesViewer = new MessagesViewer();
contactsViewer = new ContactsViewer();
summaryViewer = new SummaryViewer();
mediaViewer = new MediaViewer();
proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup());
initComponents();
tabPane.add(summaryViewer.getDisplayName(), summaryViewer);
tabPane.add(messagesViewer.getDisplayName(), messagesViewer);
tabPane.add(contactsViewer.getDisplayName(), contactsViewer);
tabPane.add(mediaViewer.getDisplayName(), mediaViewer);
}
/**
* Sets the value of currentSelection and passes the SelectionInfo onto the
* currently selected\visible tab.
*
* @param info Currently selected account nodes
*/
public void setSelectionInfo(SelectionInfo info) {
currentSelection = info;
((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(info);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
scrollPane = new javax.swing.JScrollPane();
tabPane = new javax.swing.JTabbedPane();
scrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
tabPane.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
tabPaneStateChanged(evt);
}
});
scrollPane.setViewportView(tabPane);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollPane, javax.swing.GroupLayout.Alignment.TRAILING))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollPane))
);
}// </editor-fold>//GEN-END:initComponents
private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged
if(currentSelection != null) {
((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection);
}
Component selectedComponent = tabPane.getSelectedComponent();
if(selectedComponent instanceof Lookup.Provider) {
Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup();
proxyLookup.setNewLookups(lookup);
}
}//GEN-LAST:event_tabPaneStateChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane scrollPane;
private javax.swing.JTabbedPane tabPane;
// End of variables declaration//GEN-END:variables
@Override
public Lookup getLookup() {
return proxyLookup;
}
}

View File

@ -0,0 +1,50 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import javax.swing.JPanel;
import org.openide.util.Lookup;
/**
* Interface for Controls wishing to appear in the RelationshipBrowser tabPane.
*/
public interface RelationshipsViewer extends Lookup.Provider {
/**
* Returns the value to be displayed on the "tab"
*
* @return String display name
*/
public String getDisplayName();
/**
* Returns the JPanel to be displayed in the RelationshipBrowser.
*
* @return JPanel to be displayed
*/
public JPanel getPanel();
/**
* Sets current SelectionInfo allowing the panel to update accordingly.
*
* @param info SelectionInfo instance representing the currently selected
* accounts
*/
public void setSelectionInfo(SelectionInfo info);
}

View File

@ -0,0 +1,185 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Class to wrap the details of the current selection from the AccountBrowser or
* VisualizationPane
*/
public final class SelectionInfo {
private static final Logger logger = Logger.getLogger(SelectionInfo.class.getName());
private final Set<AccountDeviceInstance> accountDeviceInstances;
private final CommunicationsFilter communicationFilter;
private final Set<Account> accounts;
private Set<BlackboardArtifact> accountArtifacts = null;
private SelectionSummary summary = null;
/**
* Wraps the details of the currently selected accounts.
*
* @param accountDeviceInstances Selected accountDecivedInstances
* @param communicationFilter Currently selected communications filters
*/
public SelectionInfo(Set<AccountDeviceInstance> accountDeviceInstances, CommunicationsFilter communicationFilter) {
this.accountDeviceInstances = accountDeviceInstances;
this.communicationFilter = communicationFilter;
accounts = new HashSet<>();
accountDeviceInstances.forEach((instance) -> {
accounts.add(instance.getAccount());
});
}
/**
* Returns the currently selected accountDeviceInstances
*
* @return Set of AccountDeviceInstance
*/
public Set<AccountDeviceInstance> getAccountDevicesInstances() {
return accountDeviceInstances;
}
/**
* Returns the currently selected communications filters.
*
* @return Instance of CommunicationsFilter
*/
public CommunicationsFilter getCommunicationsFilter() {
return communicationFilter;
}
public Set<Account> getAccounts() {
return accounts;
}
public Set<BlackboardArtifact> getArtifacts() {
if(accountArtifacts == null) {
accountArtifacts = new HashSet<>();
CommunicationsManager communicationManager;
try {
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS
return null;
}
final Set<Content> relationshipSources;
try {
relationshipSources = communicationManager.getRelationshipSources(getAccountDevicesInstances(), getCommunicationsFilter());
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
accountArtifacts.add((BlackboardArtifact) content);
});
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
}
}
return accountArtifacts;
}
public SelectionSummary getSummary() {
if(summary == null) {
summary = new SelectionSummary();
}
return summary;
}
final class SelectionSummary{
int attachmentCnt;
int messagesCnt;
int emailCnt;
int callLogCnt;
int contactsCnt;
SelectionSummary() {
getCounts();
}
private void getCounts(){
for(BlackboardArtifact artifact: getArtifacts()) {
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
if(null != fromID) switch (fromID) {
case TSK_EMAIL_MSG:
emailCnt++;
break;
case TSK_CALLLOG:
callLogCnt++;
break;
case TSK_MESSAGE:
messagesCnt++;
break;
case TSK_CONTACT:
contactsCnt++;
break;
default:
break;
}
try{
attachmentCnt+= artifact.getChildrenCount();
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Exception thrown "
+ "from getChildrenCount artifactID: %d",
artifact.getArtifactID()), ex); //NON-NLS
}
}
}
public int getAttachmentCnt() {
return attachmentCnt;
}
public int getMessagesCnt() {
return messagesCnt;
}
public int getEmailCnt() {
return emailCnt;
}
public int getCallLogCnt() {
return callLogCnt;
}
public int getContactsCnt() {
return contactsCnt;
}
}
}

View File

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="countsPanel" max="32767" attributes="0"/>
<Component id="fileReferencesPanel" alignment="0" pref="485" max="32767" attributes="0"/>
<Component id="caseReferencesPanel" alignment="1" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="countsPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="fileReferencesPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="caseReferencesPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="countsPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Counts">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.countsPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="attachmentsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="messagesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="callLogsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="contactsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="emailLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="emailDataLabel" min="-2" max="-2" attributes="0"/>
<Component id="contactsDataLabel" min="-2" max="-2" attributes="0"/>
<Component id="callLogsDataLabel" min="-2" max="-2" attributes="0"/>
<Component id="messagesDataLabel" min="-2" max="-2" attributes="0"/>
<Component id="attachmentsDataLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="attachmentsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="attachmentsDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="messagesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="messagesDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="callLogsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="callLogsDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="contactsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="contactsDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="emailLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="emailDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="emailLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.emailLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="contactsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="SummaryViewer.contactsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="messagesLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.messagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="callLogsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.callLogsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="attachmentsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.attachmentsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="attachmentsDataLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.attachmentsDataLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="messagesDataLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.messagesDataLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="callLogsDataLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.callLogsDataLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="contactsDataLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.contactsDataLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="emailDataLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.emailDataLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="org.sleuthkit.autopsy.communications.OutlineViewPanel" name="fileReferencesPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="File References in Current Case">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.fileReferencesPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[472, 300]"/>
</Property>
</Properties>
</Component>
<Component class="org.sleuthkit.autopsy.communications.OutlineViewPanel" name="caseReferencesPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Other Occurrences">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.caseReferencesPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[472, 300]"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,313 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain 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.communications.relationships;
import java.util.Set;
import javax.swing.JPanel;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.openide.explorer.view.OutlineView;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.communications.relationships.SelectionInfo.SelectionSummary;
import org.sleuthkit.datamodel.Account;
/**
* Account Summary View Panel. This panel shows a list of various counts related
* to the currently selected account. As well has a panel showing a list of
* cases and files that reference the account.
*
*/
public class SummaryViewer extends javax.swing.JPanel implements RelationshipsViewer {
private final Lookup lookup;
@Messages({
"SummaryViewer_TabTitle=Summary",
"SummaryViewer_FileRefNameColumn_Title=Path",
"SummaryViewer_CaseRefNameColumn_Title=Case Name",
"SummaryViewer_CentralRepository_Message=<Enable Central Resposity to see Case References>",
"SummaryViewer_Creation_Date_Title=Creation Date"
})
/**
* Creates new form SummaryViewer
*/
public SummaryViewer() {
lookup = Lookup.getDefault();
initComponents();
OutlineView outlineView = fileReferencesPanel.getOutlineView();
Outline outline = outlineView.getOutline();
outline.setRootVisible(false);
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.SummaryViewer_FileRefNameColumn_Title());
outlineView = caseReferencesPanel.getOutlineView();
outline = outlineView.getOutline();
outlineView.setPropertyColumns("creationDate", Bundle.SummaryViewer_Creation_Date_Title()); //NON-NLS
outline.setRootVisible(false);
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.SummaryViewer_CaseRefNameColumn_Title());
clearControls();
}
@Override
public String getDisplayName() {
return Bundle.SummaryViewer_TabTitle();
}
@Override
public JPanel getPanel() {
return this;
}
@Override
public void setSelectionInfo(SelectionInfo info) {
if (!EamDb.isEnabled()) {
caseReferencesPanel.hideOutlineView(Bundle.SummaryViewer_CentralRepository_Message());
} else {
caseReferencesPanel.showOutlineView();
}
// Request is that the SummaryViewer only show information if one
// account is selected
if (info.getAccounts().size() != 1) {
setEnabled(false);
clearControls();
} else {
SelectionSummary summaryDetails = info.getSummary();
attachmentsDataLabel.setText(Integer.toString(summaryDetails.getAttachmentCnt()));
callLogsDataLabel.setText(Integer.toString(summaryDetails.getCallLogCnt()));
contactsDataLabel.setText(Integer.toString(summaryDetails.getContactsCnt()));
emailDataLabel.setText(Integer.toString(summaryDetails.getEmailCnt()));
messagesDataLabel.setText(Integer.toString(summaryDetails.getMessagesCnt()));
fileReferencesPanel.setNode(new AbstractNode(Children.create(new AccountSourceContentChildNodeFactory(info.getAccounts()), true)));
caseReferencesPanel.setNode(new AbstractNode(Children.create(new CorrelationCaseChildNodeFactory(info.getAccounts()), true)));
setEnabled(true);
}
}
@Override
public Lookup getLookup() {
return lookup;
}
/**
* Sets whether or not the text fields are enabled.
*
* @param enabled true if this component should be enabled, false otherwise
*/
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
attachmentsLabel.setEnabled(enabled);
callLogsLabel.setEnabled(enabled);
contactsLabel.setEnabled(enabled);
emailLabel.setEnabled(enabled);
messagesLabel.setEnabled(enabled);
caseReferencesPanel.setEnabled(enabled);
fileReferencesPanel.setEnabled(enabled);
countsPanel.setEnabled(enabled);
}
/**
* Clears the text fields and OutlookViews.
*/
private void clearControls() {
attachmentsDataLabel.setText("");
callLogsDataLabel.setText("");
contactsDataLabel.setText("");
emailDataLabel.setText("");
messagesDataLabel.setText("");
fileReferencesPanel.setNode(new AbstractNode(Children.LEAF));
caseReferencesPanel.setNode(new AbstractNode(Children.LEAF));
}
/**
* For the given accounts create a comma separated string of all of the
* names (TypeSpecificID).
*
* @param accounts Set of selected accounts
*
* @return String listing the account names
*/
private String createAccountLabel(Set<Account> accounts) {
StringBuilder buffer = new StringBuilder();
accounts.stream().map((account) -> {
buffer.append(account.getTypeSpecificID());
return account;
}).forEachOrdered((_item) -> {
buffer.append(", ");
});
return buffer.toString().substring(0, buffer.length() - 2);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
countsPanel = new javax.swing.JPanel();
emailLabel = new javax.swing.JLabel();
contactsLabel = new javax.swing.JLabel();
messagesLabel = new javax.swing.JLabel();
callLogsLabel = new javax.swing.JLabel();
attachmentsLabel = new javax.swing.JLabel();
attachmentsDataLabel = new javax.swing.JLabel();
messagesDataLabel = new javax.swing.JLabel();
callLogsDataLabel = new javax.swing.JLabel();
contactsDataLabel = new javax.swing.JLabel();
emailDataLabel = new javax.swing.JLabel();
fileReferencesPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
caseReferencesPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
countsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.countsPanel.border.title"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(emailLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.emailLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(contactsLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.contactsLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(messagesLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.messagesLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(callLogsLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.callLogsLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(attachmentsLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.attachmentsLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(attachmentsDataLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.attachmentsDataLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(messagesDataLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.messagesDataLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(callLogsDataLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.callLogsDataLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(contactsDataLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.contactsDataLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(emailDataLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.emailDataLabel.text")); // NOI18N
javax.swing.GroupLayout countsPanelLayout = new javax.swing.GroupLayout(countsPanel);
countsPanel.setLayout(countsPanelLayout);
countsPanelLayout.setHorizontalGroup(
countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(countsPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(attachmentsLabel)
.addComponent(messagesLabel)
.addComponent(callLogsLabel)
.addComponent(contactsLabel)
.addComponent(emailLabel))
.addGap(18, 18, 18)
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(emailDataLabel)
.addComponent(contactsDataLabel)
.addComponent(callLogsDataLabel)
.addComponent(messagesDataLabel)
.addComponent(attachmentsDataLabel))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
countsPanelLayout.setVerticalGroup(
countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(countsPanelLayout.createSequentialGroup()
.addGap(7, 7, 7)
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(attachmentsLabel)
.addComponent(attachmentsDataLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(messagesLabel)
.addComponent(messagesDataLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(callLogsLabel)
.addComponent(callLogsDataLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(contactsLabel)
.addComponent(contactsDataLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(emailLabel)
.addComponent(emailDataLabel))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
fileReferencesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.fileReferencesPanel.border.title"))); // NOI18N
fileReferencesPanel.setPreferredSize(new java.awt.Dimension(472, 300));
caseReferencesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.caseReferencesPanel.border.title"))); // NOI18N
caseReferencesPanel.setPreferredSize(new java.awt.Dimension(472, 300));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(countsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(fileReferencesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 485, Short.MAX_VALUE)
.addComponent(caseReferencesPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(countsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileReferencesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(caseReferencesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel attachmentsDataLabel;
private javax.swing.JLabel attachmentsLabel;
private javax.swing.JLabel callLogsDataLabel;
private javax.swing.JLabel callLogsLabel;
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel caseReferencesPanel;
private javax.swing.JLabel contactsDataLabel;
private javax.swing.JLabel contactsLabel;
private javax.swing.JPanel countsPanel;
private javax.swing.JLabel emailDataLabel;
private javax.swing.JLabel emailLabel;
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel fileReferencesPanel;
private javax.swing.JLabel messagesDataLabel;
private javax.swing.JLabel messagesLabel;
// End of variables declaration//GEN-END:variables
}

View File

@ -467,6 +467,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
htmlPanel.reset();
textbodyTextArea.setText("");
msgbodyTabbedPane.setEnabled(false);
drp.setNode(null);
}
@Override
@ -561,7 +562,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")");
drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(
new AttachmentsChildren(attachments)), null), true));
new AttachmentsChildren(attachments))), true));
}
private static String wrapInHtmlBody(String htmlText) {

View File

@ -386,7 +386,13 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
rootNodeChildren.cancelLoadingThumbnails();
}
try {
if (givenNode != null) {
// There is an issue with ThumbnailViewChildren
// addNotify, that it's call to getChildren.getNodes() does not cause the
// children nodes to be created. Adding a call to getChildren.getNodesCount()
// here will assure that the children nodes are created particularly in the
// case where the DataResultViewerThumbnail stands along from the
// DataResultViewer. See DataResultViewer setNode for more information.
if (givenNode != null && givenNode.getChildren().getNodesCount() > 0) {
rootNode = (TableFilterNode) givenNode;
/*
* Wrap the given node in a ThumbnailViewChildren that will

View File

@ -126,7 +126,20 @@ public class DataResultFilterNode extends FilterNode {
static private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
// Assumptions are made in GetPreferredActionsDisplayableItemNodeVisitor that
// sourceEm is the directory tree explorer manager.
private final ExplorerManager sourceEm;
/**
* Constructs a node used to wrap another node before passing it to the
* result viewers. The wrapper node defines the actions associated with the
* wrapped node and may filter out some of its children.
*
* @param node The node to wrap.
*/
public DataResultFilterNode(Node node) {
this(node, null);
}
/**
* Constructs a node used to wrap another node before passing it to the
@ -635,6 +648,9 @@ public class DataResultFilterNode extends FilterNode {
// is a DirectoryTreeFilterNode that wraps the dataModelNode. We need
// to set that wrapped node as the selection and root context of the
// directory tree explorer manager (sourceEm)
if(sourceEm == null) {
return null;
}
final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0];
return new AbstractAction() {
@ -675,6 +691,9 @@ public class DataResultFilterNode extends FilterNode {
* @return
*/
private AbstractAction openParent(AbstractNode node) {
if(sourceEm == null) {
return null;
}
// @@@ Why do we ignore node?
Node[] selectedFilterNodes = sourceEm.getSelectedNodes();
Node selectedFilterNode = selectedFilterNodes[0];

View File

@ -163,6 +163,8 @@ final class ContactAnalyzer {
data1 = resultSet.getString("data1"); //NON-NLS
mimetype = resultSet.getString("mimetype"); //NON-NLS
if (name.equals(oldName) == false) {
bba = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
attributes = new ArrayList<>();
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name));
}
if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS
@ -170,6 +172,12 @@ final class ContactAnalyzer {
} else {
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1));
}
// TODO: If this code comes back to life, add code to create the account
// and relationship between the phone numbers & emails. Also
// investigate if the mimetype "vnd.android.cursor.item/phone_v2"
// makes sense in an ios word
oldName = name;
bba.addAttributes(attributes);

View File

@ -141,6 +141,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer):
name = resultSet.getString("display_name")
data1 = resultSet.getString("data1") # the phone number or email
mimetype = resultSet.getString("mimetype") # either phone or email
attributes = ArrayList()
if name != oldName:
artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT)
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name))

View File

@ -1,5 +1,5 @@
#Updated by build script
#Tue, 26 Feb 2019 14:37:44 -0500
#Wed, 08 May 2019 21:37:02 -0400
LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314
SPLASH_WIDTH=538
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
SplashRunningTextColor=0x0
SplashRunningTextFontSize=19
currentVersion=Autopsy 4.10.0
currentVersion=Autopsy 4.11.0

View File

@ -1,4 +1,4 @@
#Updated by build script
#Tue, 26 Feb 2019 14:37:44 -0500
CTL_MainWindow_Title=Autopsy 4.10.0
CTL_MainWindow_Title_No_Project=Autopsy 4.10.0
#Wed, 08 May 2019 21:37:02 -0400
CTL_MainWindow_Title=Autopsy 4.11.0
CTL_MainWindow_Title_No_Project=Autopsy 4.11.0

View File

@ -193,7 +193,7 @@ final class VcardParser {
}
}
}
ThunderbirdMboxFileIngestModule.addArtifactAttribute(name, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON, attributes);
ThunderbirdMboxFileIngestModule.addArtifactAttribute(name, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, attributes);
for (Telephone telephone : vcard.getTelephoneNumbers()) {
addPhoneAttributes(telephone, abstractFile, attributes);
@ -412,7 +412,7 @@ final class VcardParser {
type.getValue().toUpperCase().replaceAll("\\s+","").split(","));
for (String splitType : splitTelephoneTypes) {
String attributeTypeName = "TSK_PHONE_" + splitType;
String attributeTypeName = "TSK_PHONE_NUMBER_" + splitType;
try {
BlackboardAttribute.Type attributeType = tskCase.getAttributeType(attributeTypeName);
if (attributeType == null) {