From 7e7ba8b4deb8151363a930e13b1fc7372bf487ce Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 16 Apr 2019 10:48:56 -0400 Subject: [PATCH] Added the new MessageBrowser to the VisualizationPanel --- .../communications/AccountDetailsNode.java | 88 ------- .../communications/CVTTopComponent.java | 8 +- .../communications/MessageBrowser.form | 56 ----- .../communications/MessageBrowser.java | 231 ------------------ .../autopsy/communications/MessageNode.java | 2 +- .../communications/MessagesViewer.java | 4 +- .../communications/RelationshipBrowser.java | 18 +- .../communications/RelationshipNode.java | 174 ------------- .../autopsy/communications/SelectionNode.java | 140 ----------- .../communications/VisualizationPanel.java | 66 ++--- .../keywordsearch/Bundle.properties-MERGED | 2 +- .../recentactivity/Bundle.properties-MERGED | 2 +- 12 files changed, 42 insertions(+), 749 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/communications/AccountDetailsNode.java delete mode 100644 Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.form delete mode 100644 Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java delete mode 100644 Core/src/org/sleuthkit/autopsy/communications/RelationshipNode.java delete mode 100644 Core/src/org/sleuthkit/autopsy/communications/SelectionNode.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountDetailsNode.java b/Core/src/org/sleuthkit/autopsy/communications/AccountDetailsNode.java deleted file mode 100644 index 39eae2b9f3..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/AccountDetailsNode.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2017 Basis Technology Corp. - * Contact: carrier sleuthkit 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 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 { - - private final Set accountDeviceInstances; - private final CommunicationsManager commsManager; - private final CommunicationsFilter filter; - - private AccountRelationshipChildren(Set accountDeviceInstances, CommunicationsManager commsManager, CommunicationsFilter filter) { - this.accountDeviceInstances = accountDeviceInstances; - this.commsManager = commsManager; - this.filter = filter; - } - - @Override - protected boolean createKeys(List 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."); - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java index 1e1004de25..d8a53784b7 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.communications; import com.google.common.eventbus.Subscribe; +import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.util.List; @@ -61,8 +62,11 @@ public final class CVTTopComponent extends TopComponent { associateLookup(proxyLookup); // Make sure the Global Actions Context is proxying the selection of the active tab. browseVisualizeTabPane.addChangeListener(changeEvent -> { - Lookup.Provider selectedComponent = (Lookup.Provider) browseVisualizeTabPane.getSelectedComponent(); - proxyLookup.setNewLookups(selectedComponent.getLookup()); + Component selectedComponent = browseVisualizeTabPane.getSelectedComponent(); + if(selectedComponent instanceof Lookup.Provider) { + Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup(); + proxyLookup.setNewLookups(lookup); + } filtersPane.setDeviceAccountTypeEnabled(browseVisualizeTabPane.getSelectedIndex() != 0); }); diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.form b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.form deleted file mode 100644 index 58e19523f1..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.form +++ /dev/null @@ -1,56 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java deleted file mode 100644 index 339e842280..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2017-2018 Basis Technology Corp. - * Contact: carrier sleuthkit 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 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") - // //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)) - ); - }// //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 - -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java index 8fd5e44d96..56870afe32 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -48,7 +48,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ 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()); MessageNode(BlackboardArtifact artifact) { super(artifact); diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java index 45b121e243..fde59ed8f2 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -109,6 +109,9 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer, if (nodes != null && nodes.length > 0) { contentViewer.setNode(nodes[0]); } + else { + contentViewer.setNode(null); + } } }); @@ -127,7 +130,6 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer, @Override public void setSelectionInfo(SelectionInfo info) { -// tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true)), getExplorerManager()), true)); nodeFactory.refresh(info); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 8fa082fc2c..0ee0aad79f 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.communications; import javax.swing.JPanel; -import org.openide.util.Lookup; /** * Displays the Relationship information for the currently selected accounts. @@ -28,16 +27,21 @@ import org.openide.util.Lookup; final class RelationshipBrowser extends JPanel { private SelectionInfo currentSelection; + + private final MessagesViewer messagesViewer; + private final ContactsViewer contactsViewer; /** * Creates new form RelationshipBrowser */ public RelationshipBrowser() { initComponents(); - - Lookup.getDefault().lookupAll(RelationshipsViewer.class).forEach((viewer) -> { - tabPane.add(viewer.getDisplayName(), viewer.getPanel()); - }); + + messagesViewer = new MessagesViewer(); + contactsViewer = new ContactsViewer(); + + tabPane.add(messagesViewer.getDisplayName(), messagesViewer); + tabPane.add(contactsViewer.getDisplayName(), contactsViewer); } /** @@ -81,7 +85,9 @@ final class RelationshipBrowser extends JPanel { }// //GEN-END:initComponents private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged - ((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); + if(currentSelection != null) { + ((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); + } }//GEN-LAST:event_tabPaneStateChanged diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipNode.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipNode.java deleted file mode 100644 index 3fc7e36e4e..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipNode.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2017-2018 Basis Technology Corp. - * Contact: carrier sleuthkit 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.TimeZone; -import java.util.logging.Level; -import org.apache.commons.lang3.StringUtils; -import org.openide.nodes.Sheet; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; -import org.sleuthkit.autopsy.core.UserPreferences; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; -import org.sleuthkit.autopsy.datamodel.NodeProperty; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT; -import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME; -import org.sleuthkit.datamodel.Tag; -import org.sleuthkit.datamodel.TimeUtilities; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Node for a relationship, as represented by a BlackboardArtifact. - */ -final class RelationshipNode extends BlackboardArtifactNode { - - private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName()); - - RelationshipNode(BlackboardArtifact artifact) { - super(artifact); - final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); - String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); - setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase); - } - - @Override - protected Sheet createSheet() { - Sheet sheet = new Sheet(); - List tags = getAllTagsFromDatabase(); - Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); - if (sheetSet == null) { - sheetSet = Sheet.createPropertiesSet(); - sheet.put(sheetSet); - } - - sheetSet.put(new NodeProperty<>("Type", "Type", "Type", getDisplayName())); - - addScoreProperty(sheetSet, tags); - - CorrelationAttributeInstance correlationAttribute = null; - if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) { - correlationAttribute = getCorrelationAttributeInstance(); - } - addCommentProperty(sheetSet, tags, correlationAttribute); - - if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) { - addCountProperty(sheetSet, correlationAttribute); - } - final BlackboardArtifact artifact = getArtifact(); - BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(getArtifact().getArtifactTypeID()); - if (null != fromID) { - //Consider refactoring this to reduce boilerplate - switch (fromID) { - case TSK_EMAIL_MSG: - sheetSet.put(new NodeProperty<>("From", "From", "From", - StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); - sheetSet.put(new NodeProperty<>("To", "To", "To", - StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); - sheetSet.put(new NodeProperty<>("Date", "Date", "Date", - getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); - sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject", - getAttributeDisplayString(artifact, TSK_SUBJECT))); - try { - sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount())); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); - } - - break; - case TSK_MESSAGE: - sheetSet.put(new NodeProperty<>("From", "From", "From", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); - sheetSet.put(new NodeProperty<>("To", "To", "To", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); - sheetSet.put(new NodeProperty<>("Date", "Date", "Date", - getAttributeDisplayString(artifact, TSK_DATETIME))); - sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject", - getAttributeDisplayString(artifact, TSK_SUBJECT))); - try { - sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount())); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); - } - break; - case TSK_CALLLOG: - sheetSet.put(new NodeProperty<>("From", "From", "From", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); - sheetSet.put(new NodeProperty<>("To", "To", "To", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); - sheetSet.put(new NodeProperty<>("Date", "Date", "Date", - getAttributeDisplayString(artifact, TSK_DATETIME_START))); - break; - default: - break; - } - } - - return sheet; - } - - /** - * - * Get the display string for the attribute of the given type from the given - * artifact. - * - * @param artifact the value of artifact - * @param attributeType the value of TSK_SUBJECT1 - * - * @return The display string, or an empty string if there is no such - * attribute or an an error. - */ - private static String getAttributeDisplayString(final BlackboardArtifact artifact, final ATTRIBUTE_TYPE attributeType) { - 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); - 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(); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/SelectionNode.java b/Core/src/org/sleuthkit/autopsy/communications/SelectionNode.java deleted file mode 100644 index 1618bb9ecc..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/SelectionNode.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2018 Basis Technology Corp. - * Contact: carrier sleuthkit 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 edgeRelationshipArtifacts, - Set accountDeviceInstanceKeys, - CommunicationsFilter filter, - CommunicationsManager commsManager) { - - Set 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 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 { - - static final private Logger logger = Logger.getLogger(RelationshipChildren.class.getName()); - - private final Set edgeRelationshipArtifacts; - - private final Set accountDeviceInstances; - - private final CommunicationsManager commsManager; - private final CommunicationsFilter filter; - - private RelationshipChildren(Set selectedEdgeRelationshipSources, Set selecedAccountDeviceInstances, CommunicationsManager commsManager, CommunicationsFilter filter) { - this.edgeRelationshipArtifacts = selectedEdgeRelationshipSources; - this.accountDeviceInstances = selecedAccountDeviceInstances; - this.commsManager = commsManager; - this.filter = filter; - } - - @Override - protected boolean createKeys(List list) { - try { - final Set 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."); - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java index f3d4f95bb2..d9bbcb8d39 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java @@ -55,7 +55,6 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; -import java.beans.PropertyVetoException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -63,11 +62,11 @@ import java.nio.file.Paths; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -99,12 +98,8 @@ import org.apache.commons.lang3.StringUtils; import org.controlsfx.control.Notifications; import org.jdesktop.layout.GroupLayout; import org.jdesktop.layout.LayoutStyle; -import org.openide.explorer.ExplorerManager; -import org.openide.explorer.ExplorerUtils; -import org.openide.nodes.Node; import org.openide.util.Lookup; import org.openide.util.NbBundle; -import org.openide.util.lookup.ProxyLookup; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -113,9 +108,9 @@ import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator; +import org.sleuthkit.datamodel.AccountDeviceInstance; import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.datamodel.CommunicationsManager; -import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** * A panel that goes in the Visualize tab of the Communications Visualization @@ -128,7 +123,7 @@ import org.sleuthkit.datamodel.TskCoreException; * actions to work correctly. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -final public class VisualizationPanel extends JPanel implements Lookup.Provider { +final public class VisualizationPanel extends JPanel { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(VisualizationPanel.class.getName()); @@ -141,9 +136,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider @NbBundle.Messages("VisualizationPanel.cancelButton.text=Cancel") private static final String CANCEL = Bundle.VisualizationPanel_cancelButton_text(); - private final ExplorerManager vizEM = new ExplorerManager(); - private final ExplorerManager gacEM = new ExplorerManager(); - private final ProxyLookup proxyLookup; private Frame windowAncestor; private CommunicationsManager commsManager; @@ -162,6 +154,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider private final Map layoutButtons = new HashMap<>(); private NamedGraphLayout currentLayout; + + private final RelationshipBrowser relationshipBrowser; @NbBundle.Messages("VisalizationPanel.paintingError=Problem painting visualization.") public VisualizationPanel() { @@ -224,13 +218,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider final GraphMouseListener graphMouseListener = new GraphMouseListener(); graphComponent.getGraphControl().addMouseWheelListener(graphMouseListener); graphComponent.getGraphControl().addMouseListener(graphMouseListener); - - final MessageBrowser messageBrowser = new MessageBrowser(vizEM, gacEM); - splitPane.setRightComponent(messageBrowser); - proxyLookup = new ProxyLookup( - ExplorerUtils.createLookup(vizEM, getActionMap()), - messageBrowser.getLookup() - ); + + relationshipBrowser = new RelationshipBrowser(); + splitPane.setRightComponent(relationshipBrowser); //feed selection to explorermanager graph.getSelectionModel().addListener(mxEvent.CHANGE, new SelectionListener()); @@ -259,12 +249,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider applyLayout(fastOrganicLayout); } - - @Override - public Lookup getLookup() { - return proxyLookup; - } - + @Subscribe void handle(LockedVertexModel.VertexLockEvent event) { final Set vertices = event.getVertices(); @@ -884,40 +869,25 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider @Override public void invoke(Object sender, mxEventObject evt) { Object[] selectionCells = graph.getSelectionCells(); - Node rootNode = Node.EMPTY; - Node[] selectedNodes = new Node[0]; if (selectionCells.length > 0) { mxICell[] selectedCells = Arrays.asList(selectionCells).toArray(new mxCell[selectionCells.length]); - HashSet relationshipSources = new HashSet<>(); - HashSet adis = new HashSet<>(); + HashSet deviceInstances = new HashSet<>(); for (mxICell cell : selectedCells) { if (cell.isEdge()) { mxICell source = (mxICell) graph.getModel().getTerminal(cell, true); - AccountDeviceInstanceKey account1 = (AccountDeviceInstanceKey) source.getValue(); mxICell target = (mxICell) graph.getModel().getTerminal(cell, false); - AccountDeviceInstanceKey account2 = (AccountDeviceInstanceKey) target.getValue(); - try { - final List relationshipSources1 = commsManager.getRelationshipSources( - account1.getAccountDeviceInstance(), - account2.getAccountDeviceInstance(), - currentFilter); - relationshipSources.addAll(relationshipSources1); - } catch (TskCoreException tskCoreException) { - logger.log(Level.SEVERE, " Error getting relationsips....", tskCoreException); - } + + deviceInstances.add(((AccountDeviceInstanceKey) source.getValue()).getAccountDeviceInstance()); + deviceInstances.add(((AccountDeviceInstanceKey) target.getValue()).getAccountDeviceInstance()); + } else if (cell.isVertex()) { - adis.add((AccountDeviceInstanceKey) cell.getValue()); + deviceInstances.add(((AccountDeviceInstanceKey) cell.getValue()).getAccountDeviceInstance()); } } - rootNode = SelectionNode.createFromAccountsAndRelationships(relationshipSources, adis, currentFilter, commsManager); - selectedNodes = new Node[]{rootNode}; - } - vizEM.setRootContext(rootNode); - try { - vizEM.setSelectedNodes(selectedNodes); - } catch (PropertyVetoException ex) { - logger.log(Level.SEVERE, "Selection vetoed.", ex); + relationshipBrowser.setSelectionInfo(new SelectionInfo(deviceInstances, currentFilter)); + } else { + relationshipBrowser.setSelectionInfo(new SelectionInfo(Collections.EMPTY_SET, currentFilter)); } } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index ab7e11a07f..6f95dfc82f 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -35,7 +35,7 @@ KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found KeywordSearchResultFactory.query.exception.msg=Could not perform the query OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\nThe module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 7da2ebca7b..17d744eee1 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -64,7 +64,7 @@ ExtractZone_progress_Msg=Extracting :Zone.Identifer files ExtractZone_Restricted=Restricted Sites Zone ExtractZone_Trusted=Trusted Sites Zone OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. +OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome