mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
Merge remote-tracking branch 'upstream/cvt-contacts-view' into cvt-contacts-view-merge-to-develop
This commit is contained in:
commit
0477de37e6
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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,9 +63,10 @@ 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
|
||||
* the messages table.
|
||||
@ -79,19 +87,28 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
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(),
|
||||
proxyLookup = new ProxyLookup(relationshipBrowser.getLookup(),
|
||||
ExplorerUtils.createLookup(accountsTableEM, getActionMap()));
|
||||
}
|
||||
|
||||
|
@ -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=
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -162,6 +155,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;
|
||||
|
||||
@NbBundle.Messages("VisalizationPanel.paintingError=Problem painting visualization.")
|
||||
@ -226,12 +221,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
||||
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());
|
||||
@ -258,11 +249,6 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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:
|
@ -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
|
@ -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, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="org.openide.explorer.propertysheet.PropertySheet" name="propertySheet">
|
||||
<Properties>
|
||||
<Property name="descriptionAreaVisible" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -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
|
||||
}
|
161
Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java
Executable file
161
Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java
Executable 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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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>
|
186
Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java
Executable file
186
Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java
Executable 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
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
68
Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.form
Executable file
68
Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.form
Executable 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>
|
233
Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java
Executable file
233
Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java
Executable 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
|
||||
|
||||
}
|
@ -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;
|
@ -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 "";
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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>
|
194
Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.java
Executable file
194
Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.java
Executable 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
|
||||
}
|
@ -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, "{key}")"/>
|
||||
</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>
|
@ -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
|
||||
|
||||
}
|
@ -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>
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
185
Core/src/org/sleuthkit/autopsy/communications/relationships/SelectionInfo.java
Executable file
185
Core/src/org/sleuthkit/autopsy/communications/relationships/SelectionInfo.java
Executable 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
215
Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form
Executable file
215
Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form
Executable 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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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>
|
313
Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java
Executable file
313
Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java
Executable 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
|
||||
|
||||
}
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -126,6 +126,8 @@ 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;
|
||||
|
||||
/**
|
||||
@ -134,6 +136,17 @@ public class DataResultFilterNode extends FilterNode {
|
||||
* 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
|
||||
* 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.
|
||||
* @param em The ExplorerManager for the component that is creating the
|
||||
* node.
|
||||
*/
|
||||
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user