mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 17:27:43 +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 com.google.common.eventbus.Subscribe;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
@ -31,11 +33,16 @@ import org.openide.explorer.ExplorerManager;
|
|||||||
import org.openide.explorer.ExplorerUtils;
|
import org.openide.explorer.ExplorerUtils;
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
import org.openide.util.lookup.ProxyLookup;
|
import org.openide.util.lookup.ProxyLookup;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
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.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
||||||
|
import org.sleuthkit.datamodel.CommunicationsFilter;
|
||||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
@ -56,8 +63,9 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
|||||||
|
|
||||||
private final Outline outline;
|
private final Outline outline;
|
||||||
|
|
||||||
private final ExplorerManager messageBrowserEM = new ExplorerManager();
|
|
||||||
private final ExplorerManager accountsTableEM = new ExplorerManager();
|
private final ExplorerManager accountsTableEM = new ExplorerManager();
|
||||||
|
|
||||||
|
final RelationshipBrowser relationshipBrowser;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This lookup proxies the selection lookup of both he accounts table and
|
* This lookup proxies the selection lookup of both he accounts table and
|
||||||
@ -78,21 +86,30 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
|||||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName());
|
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName());
|
||||||
outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
outline.setColumnSorted(3, false, 1); //it would be nice if the column index wasn't hardcoded
|
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 -> {
|
accountsTableEM.addPropertyChangeListener(evt -> {
|
||||||
if (ExplorerManager.PROP_ROOT_CONTEXT.equals(evt.getPropertyName())) {
|
if (ExplorerManager.PROP_ROOT_CONTEXT.equals(evt.getPropertyName())) {
|
||||||
SwingUtilities.invokeLater(this::setColumnWidths);
|
SwingUtilities.invokeLater(this::setColumnWidths);
|
||||||
} else if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) {
|
} else if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) {
|
||||||
SwingUtilities.invokeLater(this::setColumnWidths);
|
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);
|
|
||||||
|
proxyLookup = new ProxyLookup(relationshipBrowser.getLookup(),
|
||||||
jSplitPane1.setRightComponent(messageBrowser);
|
ExplorerUtils.createLookup(accountsTableEM, getActionMap()));
|
||||||
|
|
||||||
proxyLookup = new ProxyLookup(
|
|
||||||
messageBrowser.getLookup(),
|
|
||||||
ExplorerUtils.createLookup(accountsTableEM, getActionMap()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setColumnWidths() {
|
private void setColumnWidths() {
|
||||||
|
@ -32,21 +32,16 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in
|
|||||||
VisualizationPanel.zoomInButton.text=
|
VisualizationPanel.zoomInButton.text=
|
||||||
VisualizationPanel.zoomOutButton.toolTipText=Zoom out
|
VisualizationPanel.zoomOutButton.toolTipText=Zoom out
|
||||||
VisualizationPanel.zoomOutButton.text=
|
VisualizationPanel.zoomOutButton.text=
|
||||||
<<<<<<< HEAD
|
VisualizationPanel.fastOrganicLayoutButton.text=
|
||||||
VisualizationPanel.fastOrganicLayoutButton.text=Redraw
|
|
||||||
VisualizationPanel.clearVizButton.text_1=Clear
|
|
||||||
VisualizationPanel.backButton.text_1=
|
VisualizationPanel.backButton.text_1=
|
||||||
VisualizationPanel.forwardButton.text=
|
|
||||||
=======
|
|
||||||
VisualizationPanel.circleLayoutButton.text=Circle
|
VisualizationPanel.circleLayoutButton.text=Circle
|
||||||
VisualizationPanel.organicLayoutButton.text=Organic
|
VisualizationPanel.organicLayoutButton.text=Organic
|
||||||
VisualizationPanel.fastOrganicLayoutButton.text=
|
|
||||||
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
|
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
|
||||||
VisualizationPanel.clearVizButton.text_1=
|
VisualizationPanel.clearVizButton.text_1=
|
||||||
VisualizationPanel.snapshotButton.text_1=Snapshot Report
|
VisualizationPanel.snapshotButton.text_1=Snapshot Report
|
||||||
>>>>>>> develop
|
|
||||||
VisualizationPanel.clearVizButton.actionCommand=
|
VisualizationPanel.clearVizButton.actionCommand=
|
||||||
VisualizationPanel.backButton.toolTipText=Click to go back
|
VisualizationPanel.backButton.toolTipText=Click to go back
|
||||||
VisualizationPanel.forwardButton.toolTipText=Click to go forward
|
VisualizationPanel.forwardButton.toolTipText=Click to go forward
|
||||||
VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart
|
VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart
|
||||||
VisualizationPanel.clearVizButton.toolTipText=Click to clear 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.deviceRequiredLabel.text=Select at least one.
|
||||||
FiltersPanel.accountTypeRequiredLabel.text=Select at least one.
|
FiltersPanel.accountTypeRequiredLabel.text=Select at least one.
|
||||||
FiltersPanel.needsRefreshLabel.text=Displayed data is out of date. Press Refresh.
|
FiltersPanel.needsRefreshLabel.text=Displayed data is out of date. Press Refresh.
|
||||||
MessageBrowser.DataResultViewerTable.title=Messages
|
|
||||||
OpenCVTAction.displayName=Communications
|
OpenCVTAction.displayName=Communications
|
||||||
PinAccountsAction.pluralText=Add Selected Accounts to Visualization
|
PinAccountsAction.pluralText=Add Selected Accounts to Visualization
|
||||||
PinAccountsAction.singularText=Add Selected Account to Visualization
|
PinAccountsAction.singularText=Add Selected Account to Visualization
|
||||||
@ -76,24 +75,19 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in
|
|||||||
VisualizationPanel.zoomInButton.text=
|
VisualizationPanel.zoomInButton.text=
|
||||||
VisualizationPanel.zoomOutButton.toolTipText=Zoom out
|
VisualizationPanel.zoomOutButton.toolTipText=Zoom out
|
||||||
VisualizationPanel.zoomOutButton.text=
|
VisualizationPanel.zoomOutButton.text=
|
||||||
<<<<<<< HEAD
|
VisualizationPanel.fastOrganicLayoutButton.text=
|
||||||
VisualizationPanel.fastOrganicLayoutButton.text=Redraw
|
|
||||||
VisualizationPanel.clearVizButton.text_1=Clear
|
|
||||||
VisualizationPanel.backButton.text_1=
|
VisualizationPanel.backButton.text_1=
|
||||||
VisualizationPanel.forwardButton.text=
|
|
||||||
=======
|
|
||||||
VisualizationPanel.circleLayoutButton.text=Circle
|
VisualizationPanel.circleLayoutButton.text=Circle
|
||||||
VisualizationPanel.organicLayoutButton.text=Organic
|
VisualizationPanel.organicLayoutButton.text=Organic
|
||||||
VisualizationPanel.fastOrganicLayoutButton.text=
|
|
||||||
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
|
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
|
||||||
VisualizationPanel.clearVizButton.text_1=
|
VisualizationPanel.clearVizButton.text_1=
|
||||||
VisualizationPanel.snapshotButton.text_1=Snapshot Report
|
VisualizationPanel.snapshotButton.text_1=Snapshot Report
|
||||||
>>>>>>> develop
|
|
||||||
VisualizationPanel.clearVizButton.actionCommand=
|
VisualizationPanel.clearVizButton.actionCommand=
|
||||||
VisualizationPanel.backButton.toolTipText=Click to go back
|
VisualizationPanel.backButton.toolTipText=Click to go back
|
||||||
VisualizationPanel.forwardButton.toolTipText=Click to go forward
|
VisualizationPanel.forwardButton.toolTipText=Click to go forward
|
||||||
VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart
|
VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart
|
||||||
VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart
|
VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart
|
||||||
|
VisualizationPanel.forwardButton.text=
|
||||||
VisualizationPanel_action_dialogs_title=Communications
|
VisualizationPanel_action_dialogs_title=Communications
|
||||||
VisualizationPanel_action_name_text=Snapshot Report
|
VisualizationPanel_action_name_text=Snapshot Report
|
||||||
VisualizationPanel_module_name=Communications
|
VisualizationPanel_module_name=Communications
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.communications;
|
package org.sleuthkit.autopsy.communications;
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -61,8 +62,11 @@ public final class CVTTopComponent extends TopComponent {
|
|||||||
associateLookup(proxyLookup);
|
associateLookup(proxyLookup);
|
||||||
// Make sure the Global Actions Context is proxying the selection of the active tab.
|
// Make sure the Global Actions Context is proxying the selection of the active tab.
|
||||||
browseVisualizeTabPane.addChangeListener(changeEvent -> {
|
browseVisualizeTabPane.addChangeListener(changeEvent -> {
|
||||||
Lookup.Provider selectedComponent = (Lookup.Provider) browseVisualizeTabPane.getSelectedComponent();
|
Component selectedComponent = browseVisualizeTabPane.getSelectedComponent();
|
||||||
proxyLookup.setNewLookups(selectedComponent.getLookup());
|
if(selectedComponent instanceof Lookup.Provider) {
|
||||||
|
Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup();
|
||||||
|
proxyLookup.setNewLookups(lookup);
|
||||||
|
}
|
||||||
filtersPane.setDeviceAccountTypeEnabled(browseVisualizeTabPane.getSelectedIndex() != 0);
|
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.CommunicationsFilter.DeviceFilter;
|
||||||
import org.sleuthkit.datamodel.DataSource;
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG;
|
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 static org.sleuthkit.datamodel.Relationship.Type.MESSAGE;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -598,7 +599,7 @@ final public class FiltersPanel extends JPanel {
|
|||||||
commsFilter.addAndFilter(getAccountTypeFilter());
|
commsFilter.addAndFilter(getAccountTypeFilter());
|
||||||
commsFilter.addAndFilter(getDateRangeFilter());
|
commsFilter.addAndFilter(getDateRangeFilter());
|
||||||
commsFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter(
|
commsFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter(
|
||||||
ImmutableSet.of(CALL_LOG, MESSAGE)));
|
ImmutableSet.of(CALL_LOG, MESSAGE, CONTACT)));
|
||||||
return commsFilter;
|
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.
|
* delegated to.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
final class ModifiableProxyLookup extends ProxyLookup {
|
final public class ModifiableProxyLookup extends ProxyLookup {
|
||||||
|
|
||||||
ModifiableProxyLookup(final Lookup... lookups) {
|
public ModifiableProxyLookup(final Lookup... lookups) {
|
||||||
super(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.
|
* Utility class with helpers for dealing with accounts.
|
||||||
*/
|
*/
|
||||||
class Utils {
|
public final class Utils {
|
||||||
|
|
||||||
private Utils() {
|
private Utils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoneId getUserPreferredZoneId() {
|
static public ZoneId getUserPreferredZoneId() {
|
||||||
ZoneId zone = UserPreferences.displayTimesInLocalTime() ?
|
ZoneId zone = UserPreferences.displayTimesInLocalTime() ?
|
||||||
ZoneOffset.systemDefault() : TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()).toZoneId();
|
ZoneOffset.systemDefault() : TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()).toZoneId();
|
||||||
return zone;
|
return zone;
|
||||||
@ -44,7 +44,7 @@ class Utils {
|
|||||||
*
|
*
|
||||||
* @return The path of the icon for the given Account Type.
|
* @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);
|
return Accounts.getIconFilePath(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.event.MouseWheelEvent;
|
import java.awt.event.MouseWheelEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyVetoException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -62,11 +61,11 @@ import java.nio.file.Paths;
|
|||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@ -98,23 +97,20 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.controlsfx.control.Notifications;
|
import org.controlsfx.control.Notifications;
|
||||||
import org.jdesktop.layout.GroupLayout;
|
import org.jdesktop.layout.GroupLayout;
|
||||||
import org.jdesktop.layout.LayoutStyle;
|
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.NbBundle;
|
||||||
import org.openide.util.lookup.ProxyLookup;
|
|
||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
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.communications.snapshot.CommSnapShotReportWriter;
|
||||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
|
import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
|
||||||
|
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
||||||
import org.sleuthkit.datamodel.CommunicationsFilter;
|
import org.sleuthkit.datamodel.CommunicationsFilter;
|
||||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||||
import org.sleuthkit.datamodel.Content;
|
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
/**
|
/**
|
||||||
* A panel that goes in the Visualize tab of the Communications Visualization
|
* 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.
|
* actions to work correctly.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
@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 long serialVersionUID = 1L;
|
||||||
private static final Logger logger = Logger.getLogger(VisualizationPanel.class.getName());
|
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")
|
@NbBundle.Messages("VisualizationPanel.cancelButton.text=Cancel")
|
||||||
private static final String CANCEL = Bundle.VisualizationPanel_cancelButton_text();
|
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 Frame windowAncestor;
|
||||||
|
|
||||||
private CommunicationsManager commsManager;
|
private CommunicationsManager commsManager;
|
||||||
@ -161,6 +154,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
|
|
||||||
private final Map<NamedGraphLayout, JButton> layoutButtons = new HashMap<>();
|
private final Map<NamedGraphLayout, JButton> layoutButtons = new HashMap<>();
|
||||||
private NamedGraphLayout currentLayout;
|
private NamedGraphLayout currentLayout;
|
||||||
|
|
||||||
|
private final RelationshipBrowser relationshipBrowser;
|
||||||
|
|
||||||
private final StateManager stateManager;
|
private final StateManager stateManager;
|
||||||
|
|
||||||
@ -225,13 +220,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
final GraphMouseListener graphMouseListener = new GraphMouseListener();
|
final GraphMouseListener graphMouseListener = new GraphMouseListener();
|
||||||
graphComponent.getGraphControl().addMouseWheelListener(graphMouseListener);
|
graphComponent.getGraphControl().addMouseWheelListener(graphMouseListener);
|
||||||
graphComponent.getGraphControl().addMouseListener(graphMouseListener);
|
graphComponent.getGraphControl().addMouseListener(graphMouseListener);
|
||||||
|
|
||||||
final MessageBrowser messageBrowser = new MessageBrowser(vizEM, gacEM);
|
relationshipBrowser = new RelationshipBrowser();
|
||||||
splitPane.setRightComponent(messageBrowser);
|
splitPane.setRightComponent(relationshipBrowser);
|
||||||
proxyLookup = new ProxyLookup(
|
|
||||||
ExplorerUtils.createLookup(vizEM, getActionMap()),
|
|
||||||
messageBrowser.getLookup()
|
|
||||||
);
|
|
||||||
|
|
||||||
//feed selection to explorermanager
|
//feed selection to explorermanager
|
||||||
graph.getSelectionModel().addListener(mxEvent.CHANGE, new SelectionListener());
|
graph.getSelectionModel().addListener(mxEvent.CHANGE, new SelectionListener());
|
||||||
@ -257,12 +248,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
|
|
||||||
setStateButtonsEnabled();
|
setStateButtonsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Lookup getLookup() {
|
|
||||||
return proxyLookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handle(LockedVertexModel.VertexLockEvent event) {
|
void handle(LockedVertexModel.VertexLockEvent event) {
|
||||||
final Set<mxCell> vertices = event.getVertices();
|
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
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
splitPane = new JSplitPane();
|
splitPane = new javax.swing.JSplitPane();
|
||||||
borderLayoutPanel = new JPanel();
|
borderLayoutPanel = new javax.swing.JPanel();
|
||||||
placeHolderPanel = new JPanel();
|
placeHolderPanel = new javax.swing.JPanel();
|
||||||
jTextArea1 = new JTextArea();
|
jTextArea1 = new javax.swing.JTextArea();
|
||||||
toolbar = new JPanel();
|
toolbar = new javax.swing.JPanel();
|
||||||
fastOrganicLayoutButton = new JButton();
|
fastOrganicLayoutButton = new javax.swing.JButton();
|
||||||
zoomOutButton = new JButton();
|
zoomOutButton = new javax.swing.JButton();
|
||||||
zoomInButton = new JButton();
|
zoomInButton = new javax.swing.JButton();
|
||||||
zoomActualButton = new JButton();
|
zoomActualButton = new javax.swing.JButton();
|
||||||
fitZoomButton = new JButton();
|
fitZoomButton = new javax.swing.JButton();
|
||||||
jLabel2 = new JLabel();
|
jLabel2 = new javax.swing.JLabel();
|
||||||
zoomLabel = new JLabel();
|
zoomLabel = new javax.swing.JLabel();
|
||||||
clearVizButton = new JButton();
|
clearVizButton = new javax.swing.JButton();
|
||||||
jSeparator2 = new JToolBar.Separator();
|
jSeparator2 = new javax.swing.JToolBar.Separator();
|
||||||
backButton = new JButton();
|
backButton = new javax.swing.JButton();
|
||||||
forwardButton = new JButton();
|
forwardButton = new javax.swing.JButton();
|
||||||
snapshotButton = new JButton();
|
snapshotButton = new javax.swing.JButton();
|
||||||
jSeparator3 = new JToolBar.Separator();
|
jSeparator3 = new javax.swing.JToolBar.Separator();
|
||||||
jSeparator4 = new JToolBar.Separator();
|
jSeparator4 = new javax.swing.JToolBar.Separator();
|
||||||
notificationsJFXPanel = new JFXPanel();
|
notificationsJFXPanel = new javafx.embed.swing.JFXPanel();
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
|
||||||
splitPane.setDividerLocation(800);
|
splitPane.setDividerLocation(800);
|
||||||
splitPane.setResizeWeight(0.5);
|
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.setColumns(20);
|
||||||
jTextArea1.setLineWrap(true);
|
jTextArea1.setLineWrap(true);
|
||||||
jTextArea1.setRows(5);
|
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);
|
placeHolderPanel.setLayout(placeHolderPanelLayout);
|
||||||
placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
|
placeHolderPanelLayout.setHorizontalGroup(
|
||||||
|
placeHolderPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(placeHolderPanelLayout.createSequentialGroup()
|
.add(placeHolderPanelLayout.createSequentialGroup()
|
||||||
.addContainerGap(250, Short.MAX_VALUE)
|
.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))
|
.addContainerGap(423, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
|
placeHolderPanelLayout.setVerticalGroup(
|
||||||
|
placeHolderPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(placeHolderPanelLayout.createSequentialGroup()
|
.add(placeHolderPanelLayout.createSequentialGroup()
|
||||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 47, GroupLayout.PREFERRED_SIZE)
|
.add(jTextArea1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 47, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.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.setIcon(new javax.swing.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.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.text")); // NOI18N
|
||||||
fastOrganicLayoutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.toolTipText")); // NOI18N
|
fastOrganicLayoutButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.toolTipText")); // NOI18N
|
||||||
fastOrganicLayoutButton.setFocusable(false);
|
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.setIcon(new javax.swing.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.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.text")); // NOI18N
|
||||||
zoomOutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N
|
zoomOutButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N
|
||||||
zoomOutButton.setFocusable(false);
|
zoomOutButton.setFocusable(false);
|
||||||
zoomOutButton.setHorizontalTextPosition(SwingConstants.CENTER);
|
zoomOutButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||||
zoomOutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
|
zoomOutButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||||
zoomOutButton.addActionListener(new ActionListener() {
|
zoomOutButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
zoomOutButtonActionPerformed(evt);
|
zoomOutButtonActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
zoomInButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png"))); // NOI18N
|
zoomInButton.setIcon(new javax.swing.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.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.text")); // NOI18N
|
||||||
zoomInButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N
|
zoomInButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N
|
||||||
zoomInButton.setFocusable(false);
|
zoomInButton.setFocusable(false);
|
||||||
zoomInButton.setHorizontalTextPosition(SwingConstants.CENTER);
|
zoomInButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||||
zoomInButton.setVerticalTextPosition(SwingConstants.BOTTOM);
|
zoomInButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||||
zoomInButton.addActionListener(new ActionListener() {
|
zoomInButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
zoomInButtonActionPerformed(evt);
|
zoomInButtonActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
zoomActualButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); // NOI18N
|
zoomActualButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); // NOI18N
|
||||||
zoomActualButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.text")); // NOI18N
|
zoomActualButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.text")); // NOI18N
|
||||||
zoomActualButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N
|
zoomActualButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N
|
||||||
zoomActualButton.setFocusable(false);
|
zoomActualButton.setFocusable(false);
|
||||||
zoomActualButton.setHorizontalTextPosition(SwingConstants.CENTER);
|
zoomActualButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||||
zoomActualButton.setVerticalTextPosition(SwingConstants.BOTTOM);
|
zoomActualButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||||
zoomActualButton.addActionListener(new ActionListener() {
|
zoomActualButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
zoomActualButtonActionPerformed(evt);
|
zoomActualButtonActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
fitZoomButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); // NOI18N
|
fitZoomButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); // NOI18N
|
||||||
fitZoomButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.text")); // NOI18N
|
fitZoomButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.text")); // NOI18N
|
||||||
fitZoomButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N
|
fitZoomButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N
|
||||||
fitZoomButton.setFocusable(false);
|
fitZoomButton.setFocusable(false);
|
||||||
fitZoomButton.setHorizontalTextPosition(SwingConstants.CENTER);
|
fitZoomButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||||
fitZoomButton.setVerticalTextPosition(SwingConstants.BOTTOM);
|
fitZoomButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||||
fitZoomButton.addActionListener(new ActionListener() {
|
fitZoomButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
fitZoomButtonActionPerformed(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.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/broom.png"))); // NOI18N
|
||||||
clearVizButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.text_1")); // NOI18N
|
clearVizButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.text_1")); // NOI18N
|
||||||
clearVizButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.toolTipText")); // NOI18N
|
clearVizButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.toolTipText")); // NOI18N
|
||||||
clearVizButton.setActionCommand(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.actionCommand")); // NOI18N
|
clearVizButton.setActionCommand(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.actionCommand")); // NOI18N
|
||||||
clearVizButton.addActionListener(new ActionListener() {
|
clearVizButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
clearVizButtonActionPerformed(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.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_previous.png"))); // NOI18N
|
||||||
backButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N
|
backButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N
|
||||||
backButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.toolTipText")); // NOI18N
|
backButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.toolTipText")); // NOI18N
|
||||||
backButton.addActionListener(new ActionListener() {
|
backButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
backButtonActionPerformed(evt);
|
backButtonActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
forwardButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_next.png"))); // NOI18N
|
forwardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_next.png"))); // NOI18N
|
||||||
forwardButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N
|
forwardButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N
|
||||||
forwardButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.toolTipText")); // NOI18N
|
forwardButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.toolTipText")); // NOI18N
|
||||||
forwardButton.setHorizontalTextPosition(SwingConstants.LEADING);
|
forwardButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||||
forwardButton.addActionListener(new ActionListener() {
|
forwardButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
forwardButtonActionPerformed(evt);
|
forwardButtonActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
snapshotButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/report/images/image.png"))); // NOI18N
|
snapshotButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/report/images/image.png"))); // NOI18N
|
||||||
snapshotButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapshotButton.text_1")); // NOI18N
|
snapshotButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapshotButton.text_1")); // NOI18N
|
||||||
snapshotButton.addActionListener(new ActionListener() {
|
snapshotButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
snapshotButtonActionPerformed(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);
|
toolbar.setLayout(toolbarLayout);
|
||||||
toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING)
|
toolbarLayout.setHorizontalGroup(
|
||||||
|
toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(toolbarLayout.createSequentialGroup()
|
.add(toolbarLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.add(backButton)
|
.add(backButton)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(forwardButton)
|
.add(forwardButton)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(jSeparator4, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
|
.add(jSeparator4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(fastOrganicLayoutButton)
|
.add(fastOrganicLayoutButton)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(clearVizButton)
|
.add(clearVizButton)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
|
.add(jSeparator2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(jLabel2)
|
.add(jLabel2)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(zoomLabel)
|
.add(zoomLabel)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(zoomOutButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
|
.add(zoomOutButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(zoomInButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
|
.add(zoomInButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(zoomActualButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)
|
.add(zoomActualButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 33, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(fitZoomButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
|
.add(fitZoomButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(jSeparator3, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
|
.add(jSeparator3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(snapshotButton)
|
.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(toolbarLayout.createSequentialGroup()
|
||||||
.add(3, 3, 3)
|
.add(3, 3, 3)
|
||||||
.add(toolbarLayout.createParallelGroup(GroupLayout.CENTER)
|
.add(toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.CENTER)
|
||||||
.add(fastOrganicLayoutButton)
|
.add(fastOrganicLayoutButton)
|
||||||
.add(zoomOutButton)
|
.add(zoomOutButton)
|
||||||
.add(zoomInButton, 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, GroupLayout.DEFAULT_SIZE, 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, GroupLayout.DEFAULT_SIZE, 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(jLabel2)
|
||||||
.add(zoomLabel)
|
.add(zoomLabel)
|
||||||
.add(clearVizButton)
|
.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(backButton)
|
||||||
.add(forwardButton)
|
.add(forwardButton)
|
||||||
.add(snapshotButton)
|
.add(snapshotButton)
|
||||||
.add(jSeparator3, 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, GroupLayout.DEFAULT_SIZE, 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))
|
.add(3, 3, 3))
|
||||||
);
|
);
|
||||||
|
|
||||||
borderLayoutPanel.add(toolbar, BorderLayout.PAGE_START);
|
borderLayoutPanel.add(toolbar, java.awt.BorderLayout.PAGE_START);
|
||||||
borderLayoutPanel.add(notificationsJFXPanel, BorderLayout.PAGE_END);
|
borderLayoutPanel.add(notificationsJFXPanel, java.awt.BorderLayout.PAGE_END);
|
||||||
|
|
||||||
splitPane.setLeftComponent(borderLayoutPanel);
|
splitPane.setLeftComponent(borderLayoutPanel);
|
||||||
|
|
||||||
add(splitPane, BorderLayout.CENTER);
|
add(splitPane, java.awt.BorderLayout.CENTER);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void fitZoomButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_fitZoomButtonActionPerformed
|
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
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private JButton backButton;
|
private javax.swing.JButton backButton;
|
||||||
private JPanel borderLayoutPanel;
|
private javax.swing.JPanel borderLayoutPanel;
|
||||||
private JButton clearVizButton;
|
private javax.swing.JButton clearVizButton;
|
||||||
private JButton fastOrganicLayoutButton;
|
private javax.swing.JButton fastOrganicLayoutButton;
|
||||||
private JButton fitZoomButton;
|
private javax.swing.JButton fitZoomButton;
|
||||||
private JButton forwardButton;
|
private javax.swing.JButton forwardButton;
|
||||||
private JLabel jLabel2;
|
private javax.swing.JLabel jLabel2;
|
||||||
private JToolBar.Separator jSeparator2;
|
private javax.swing.JToolBar.Separator jSeparator2;
|
||||||
private JToolBar.Separator jSeparator3;
|
private javax.swing.JToolBar.Separator jSeparator3;
|
||||||
private JToolBar.Separator jSeparator4;
|
private javax.swing.JToolBar.Separator jSeparator4;
|
||||||
private JTextArea jTextArea1;
|
private javax.swing.JTextArea jTextArea1;
|
||||||
private JFXPanel notificationsJFXPanel;
|
private javafx.embed.swing.JFXPanel notificationsJFXPanel;
|
||||||
private JPanel placeHolderPanel;
|
private javax.swing.JPanel placeHolderPanel;
|
||||||
private JButton snapshotButton;
|
private javax.swing.JButton snapshotButton;
|
||||||
private JSplitPane splitPane;
|
private javax.swing.JSplitPane splitPane;
|
||||||
private JPanel toolbar;
|
private javax.swing.JPanel toolbar;
|
||||||
private JButton zoomActualButton;
|
private javax.swing.JButton zoomActualButton;
|
||||||
private JButton zoomInButton;
|
private javax.swing.JButton zoomInButton;
|
||||||
private JLabel zoomLabel;
|
private javax.swing.JLabel zoomLabel;
|
||||||
private JButton zoomOutButton;
|
private javax.swing.JButton zoomOutButton;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -922,40 +912,25 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
@Override
|
@Override
|
||||||
public void invoke(Object sender, mxEventObject evt) {
|
public void invoke(Object sender, mxEventObject evt) {
|
||||||
Object[] selectionCells = graph.getSelectionCells();
|
Object[] selectionCells = graph.getSelectionCells();
|
||||||
Node rootNode = Node.EMPTY;
|
|
||||||
Node[] selectedNodes = new Node[0];
|
|
||||||
if (selectionCells.length > 0) {
|
if (selectionCells.length > 0) {
|
||||||
mxICell[] selectedCells = Arrays.asList(selectionCells).toArray(new mxCell[selectionCells.length]);
|
mxICell[] selectedCells = Arrays.asList(selectionCells).toArray(new mxCell[selectionCells.length]);
|
||||||
HashSet<Content> relationshipSources = new HashSet<>();
|
HashSet<AccountDeviceInstance> deviceInstances = new HashSet<>();
|
||||||
HashSet<AccountDeviceInstanceKey> adis = new HashSet<>();
|
|
||||||
for (mxICell cell : selectedCells) {
|
for (mxICell cell : selectedCells) {
|
||||||
if (cell.isEdge()) {
|
if (cell.isEdge()) {
|
||||||
mxICell source = (mxICell) graph.getModel().getTerminal(cell, true);
|
mxICell source = (mxICell) graph.getModel().getTerminal(cell, true);
|
||||||
AccountDeviceInstanceKey account1 = (AccountDeviceInstanceKey) source.getValue();
|
|
||||||
mxICell target = (mxICell) graph.getModel().getTerminal(cell, false);
|
mxICell target = (mxICell) graph.getModel().getTerminal(cell, false);
|
||||||
AccountDeviceInstanceKey account2 = (AccountDeviceInstanceKey) target.getValue();
|
|
||||||
try {
|
deviceInstances.add(((AccountDeviceInstanceKey) source.getValue()).getAccountDeviceInstance());
|
||||||
final List<Content> relationshipSources1 = commsManager.getRelationshipSources(
|
deviceInstances.add(((AccountDeviceInstanceKey) target.getValue()).getAccountDeviceInstance());
|
||||||
account1.getAccountDeviceInstance(),
|
|
||||||
account2.getAccountDeviceInstance(),
|
|
||||||
currentFilter);
|
|
||||||
relationshipSources.addAll(relationshipSources1);
|
|
||||||
} catch (TskCoreException tskCoreException) {
|
|
||||||
logger.log(Level.SEVERE, " Error getting relationsips....", tskCoreException);
|
|
||||||
}
|
|
||||||
} else if (cell.isVertex()) {
|
} else if (cell.isVertex()) {
|
||||||
adis.add((AccountDeviceInstanceKey) cell.getValue());
|
deviceInstances.add(((AccountDeviceInstanceKey) cell.getValue()).getAccountDeviceInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootNode = SelectionNode.createFromAccountsAndRelationships(relationshipSources, adis, currentFilter, commsManager);
|
relationshipBrowser.setSelectionInfo(new SelectionInfo(deviceInstances, currentFilter));
|
||||||
selectedNodes = new Node[]{rootNode};
|
} else {
|
||||||
}
|
relationshipBrowser.setSelectionInfo(new SelectionInfo(Collections.EMPTY_SET, currentFilter));
|
||||||
vizEM.setRootContext(rootNode);
|
|
||||||
try {
|
|
||||||
vizEM.setSelectedNodes(selectedNodes);
|
|
||||||
} catch (PropertyVetoException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Selection vetoed.", ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.communications;
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2017-2018 Basis Technology Corp.
|
* Copyright 2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.communications;
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@ -25,12 +25,12 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
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;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START;
|
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.Tag;
|
||||||
import org.sleuthkit.datamodel.TimeUtilities;
|
import org.sleuthkit.datamodel.TimeUtilities;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
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);
|
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);
|
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
|
@Override
|
||||||
protected Sheet createSheet() {
|
protected Sheet createSheet() {
|
||||||
Sheet sheet = new Sheet();
|
Sheet sheet = super.createSheet();
|
||||||
List<Tag> tags = getAllTagsFromDatabase();
|
List<Tag> tags = getAllTagsFromDatabase();
|
||||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||||
if (sheetSet == null) {
|
if (sheetSet == null) {
|
||||||
@ -68,62 +79,63 @@ final class RelationshipNode extends BlackboardArtifactNode {
|
|||||||
sheet.put(sheetSet);
|
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);
|
addScoreProperty(sheetSet, tags);
|
||||||
|
|
||||||
CorrelationAttributeInstance correlationAttribute = null;
|
CorrelationAttributeInstance correlationAttribute = null;
|
||||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
|
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||||
correlationAttribute = getCorrelationAttributeInstance();
|
correlationAttribute = getCorrelationAttributeInstance();
|
||||||
}
|
}
|
||||||
addCommentProperty(sheetSet, tags, correlationAttribute);
|
addCommentProperty(sheetSet, tags, correlationAttribute);
|
||||||
|
|
||||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
|
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||||
addCountProperty(sheetSet, correlationAttribute);
|
addCountProperty(sheetSet, correlationAttribute);
|
||||||
}
|
}
|
||||||
final BlackboardArtifact artifact = getArtifact();
|
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) {
|
if (null != fromID) {
|
||||||
//Consider refactoring this to reduce boilerplate
|
//Consider refactoring this to reduce boilerplate
|
||||||
switch (fromID) {
|
switch (fromID) {
|
||||||
case TSK_EMAIL_MSG:
|
case TSK_EMAIL_MSG:
|
||||||
sheetSet.put(new NodeProperty<>("From", "From", "From",
|
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||||
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;")));
|
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("To", "To", "To",
|
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
|
||||||
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;")));
|
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
|
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_DATETIME_SENT)));
|
getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject",
|
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_SUBJECT)));
|
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
|
||||||
try {
|
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) {
|
} 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;
|
break;
|
||||||
case TSK_MESSAGE:
|
case TSK_MESSAGE:
|
||||||
sheetSet.put(new NodeProperty<>("From", "From", "From",
|
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM)));
|
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("To", "To", "To",
|
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO)));
|
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
|
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_DATETIME)));
|
getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject",
|
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_SUBJECT)));
|
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
|
||||||
try {
|
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) {
|
} 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;
|
break;
|
||||||
case TSK_CALLLOG:
|
case TSK_CALLLOG:
|
||||||
sheetSet.put(new NodeProperty<>("From", "From", "From",
|
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM)));
|
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("To", "To", "To",
|
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO)));
|
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("Date", "Date", "Date",
|
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_DATETIME_START)));
|
getAttributeDisplayString(artifact, TSK_DATETIME_START))); //NON-NLS
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -144,7 +156,7 @@ final class RelationshipNode extends BlackboardArtifactNode {
|
|||||||
* @return The display string, or an empty string if there is no such
|
* @return The display string, or an empty string if there is no such
|
||||||
* attribute or an an error.
|
* 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 {
|
try {
|
||||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attributeType.getTypeID())));
|
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attributeType.getTypeID())));
|
||||||
if (attribute == null) {
|
if (attribute == null) {
|
||||||
@ -156,7 +168,7 @@ final class RelationshipNode extends BlackboardArtifactNode {
|
|||||||
return attribute.getDisplayString();
|
return attribute.getDisplayString();
|
||||||
}
|
}
|
||||||
} catch (TskCoreException tskCoreException) {
|
} catch (TskCoreException tskCoreException) {
|
||||||
logger.log(Level.WARNING, "Error getting attribute value.", tskCoreException);
|
logger.log(Level.WARNING, "Error getting attribute value.", tskCoreException); //NON-NLS
|
||||||
return "";
|
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_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
<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_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
@ -16,40 +16,36 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
<Component id="splitPane" max="32767" attributes="0"/>
|
<Component id="scrollPane" alignment="1" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
<Component id="splitPane" pref="1083" max="32767" attributes="0"/>
|
<Component id="scrollPane" alignment="0" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
<Container class="javax.swing.JScrollPane" name="scrollPane">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="dividerLocation" type="int" value="400"/>
|
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
|
||||||
<Property name="dividerSize" type="int" value="10"/>
|
|
||||||
<Property name="orientation" type="int" value="0"/>
|
|
||||||
<Property name="resizeWeight" type="double" value="0.5"/>
|
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Component class="org.sleuthkit.autopsy.communications.MessageDataContent" name="messageDataContent">
|
<Container class="javax.swing.JTabbedPane" name="tabPane">
|
||||||
<Constraints>
|
<Events>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabPaneStateChanged"/>
|
||||||
<JSplitPaneConstraints position="bottom"/>
|
</Events>
|
||||||
</Constraint>
|
|
||||||
</Constraints>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||||
</Component>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</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();
|
htmlPanel.reset();
|
||||||
textbodyTextArea.setText("");
|
textbodyTextArea.setText("");
|
||||||
msgbodyTabbedPane.setEnabled(false);
|
msgbodyTabbedPane.setEnabled(false);
|
||||||
|
drp.setNode(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -561,7 +562,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
|||||||
msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
|
msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
|
||||||
msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")");
|
msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")");
|
||||||
drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(
|
drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(
|
||||||
new AttachmentsChildren(attachments)), null), true));
|
new AttachmentsChildren(attachments))), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String wrapInHtmlBody(String htmlText) {
|
private static String wrapInHtmlBody(String htmlText) {
|
||||||
|
@ -386,7 +386,13 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
|||||||
rootNodeChildren.cancelLoadingThumbnails();
|
rootNodeChildren.cancelLoadingThumbnails();
|
||||||
}
|
}
|
||||||
try {
|
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;
|
rootNode = (TableFilterNode) givenNode;
|
||||||
/*
|
/*
|
||||||
* Wrap the given node in a ThumbnailViewChildren that will
|
* Wrap the given node in a ThumbnailViewChildren that will
|
||||||
|
@ -126,7 +126,20 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
static private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
|
static private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
|
||||||
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
|
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
|
||||||
|
|
||||||
|
// Assumptions are made in GetPreferredActionsDisplayableItemNodeVisitor that
|
||||||
|
// sourceEm is the directory tree explorer manager.
|
||||||
private final ExplorerManager sourceEm;
|
private final ExplorerManager sourceEm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a node used to wrap another node before passing it to the
|
||||||
|
* result viewers. The wrapper node defines the actions associated with the
|
||||||
|
* wrapped node and may filter out some of its children.
|
||||||
|
*
|
||||||
|
* @param node The node to wrap.
|
||||||
|
*/
|
||||||
|
public DataResultFilterNode(Node node) {
|
||||||
|
this(node, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a node used to wrap another node before passing it to the
|
* Constructs a node used to wrap another node before passing it to the
|
||||||
@ -635,6 +648,9 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
// is a DirectoryTreeFilterNode that wraps the dataModelNode. We need
|
// is a DirectoryTreeFilterNode that wraps the dataModelNode. We need
|
||||||
// to set that wrapped node as the selection and root context of the
|
// to set that wrapped node as the selection and root context of the
|
||||||
// directory tree explorer manager (sourceEm)
|
// directory tree explorer manager (sourceEm)
|
||||||
|
if(sourceEm == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0];
|
final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0];
|
||||||
|
|
||||||
return new AbstractAction() {
|
return new AbstractAction() {
|
||||||
@ -675,6 +691,9 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private AbstractAction openParent(AbstractNode node) {
|
private AbstractAction openParent(AbstractNode node) {
|
||||||
|
if(sourceEm == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// @@@ Why do we ignore node?
|
// @@@ Why do we ignore node?
|
||||||
Node[] selectedFilterNodes = sourceEm.getSelectedNodes();
|
Node[] selectedFilterNodes = sourceEm.getSelectedNodes();
|
||||||
Node selectedFilterNode = selectedFilterNodes[0];
|
Node selectedFilterNode = selectedFilterNodes[0];
|
||||||
|
@ -163,6 +163,8 @@ final class ContactAnalyzer {
|
|||||||
data1 = resultSet.getString("data1"); //NON-NLS
|
data1 = resultSet.getString("data1"); //NON-NLS
|
||||||
mimetype = resultSet.getString("mimetype"); //NON-NLS
|
mimetype = resultSet.getString("mimetype"); //NON-NLS
|
||||||
if (name.equals(oldName) == false) {
|
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));
|
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name));
|
||||||
}
|
}
|
||||||
if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS
|
if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS
|
||||||
@ -170,6 +172,12 @@ final class ContactAnalyzer {
|
|||||||
} else {
|
} else {
|
||||||
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1));
|
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;
|
oldName = name;
|
||||||
|
|
||||||
bba.addAttributes(attributes);
|
bba.addAttributes(attributes);
|
||||||
|
@ -141,6 +141,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer):
|
|||||||
name = resultSet.getString("display_name")
|
name = resultSet.getString("display_name")
|
||||||
data1 = resultSet.getString("data1") # the phone number or email
|
data1 = resultSet.getString("data1") # the phone number or email
|
||||||
mimetype = resultSet.getString("mimetype") # either phone or email
|
mimetype = resultSet.getString("mimetype") # either phone or email
|
||||||
|
attributes = ArrayList()
|
||||||
if name != oldName:
|
if name != oldName:
|
||||||
artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT)
|
artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT)
|
||||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name))
|
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#Updated by build script
|
#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
|
LBL_splash_window_title=Starting Autopsy
|
||||||
SPLASH_HEIGHT=314
|
SPLASH_HEIGHT=314
|
||||||
SPLASH_WIDTH=538
|
SPLASH_WIDTH=538
|
||||||
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
|
|||||||
SplashRunningTextColor=0x0
|
SplashRunningTextColor=0x0
|
||||||
SplashRunningTextFontSize=19
|
SplashRunningTextFontSize=19
|
||||||
|
|
||||||
currentVersion=Autopsy 4.10.0
|
currentVersion=Autopsy 4.11.0
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#Updated by build script
|
#Updated by build script
|
||||||
#Tue, 26 Feb 2019 14:37:44 -0500
|
#Wed, 08 May 2019 21:37:02 -0400
|
||||||
CTL_MainWindow_Title=Autopsy 4.10.0
|
CTL_MainWindow_Title=Autopsy 4.11.0
|
||||||
CTL_MainWindow_Title_No_Project=Autopsy 4.10.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()) {
|
for (Telephone telephone : vcard.getTelephoneNumbers()) {
|
||||||
addPhoneAttributes(telephone, abstractFile, attributes);
|
addPhoneAttributes(telephone, abstractFile, attributes);
|
||||||
@ -412,7 +412,7 @@ final class VcardParser {
|
|||||||
type.getValue().toUpperCase().replaceAll("\\s+","").split(","));
|
type.getValue().toUpperCase().replaceAll("\\s+","").split(","));
|
||||||
|
|
||||||
for (String splitType : splitTelephoneTypes) {
|
for (String splitType : splitTelephoneTypes) {
|
||||||
String attributeTypeName = "TSK_PHONE_" + splitType;
|
String attributeTypeName = "TSK_PHONE_NUMBER_" + splitType;
|
||||||
try {
|
try {
|
||||||
BlackboardAttribute.Type attributeType = tskCase.getAttributeType(attributeTypeName);
|
BlackboardAttribute.Type attributeType = tskCase.getAttributeType(attributeTypeName);
|
||||||
if (attributeType == null) {
|
if (attributeType == null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user