From f1962bd082ecdf5c5d863a6c6c8ce839d12a4303 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 9 Apr 2019 10:34:55 -0400 Subject: [PATCH 01/78] Inital POC of new Communications Relationship Panel --- .../communications/ContactsViewer.form | 45 ++++++++++ .../communications/ContactsViewer.java | 88 +++++++++++++++++++ .../communications/MessagesViewer.form | 45 ++++++++++ .../communications/MessagesViewer.java | 88 +++++++++++++++++++ .../communications/RelationshipBrowser.form | 34 +++++++ .../communications/RelationshipBrowser.java | 75 ++++++++++++++++ .../communications/RelationshipsViewer.java | 34 +++++++ .../autopsy/communications/SelectionInfo.java | 46 ++++++++++ 8 files changed, 455 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form new file mode 100755 index 0000000000..81e1e314ef --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form @@ -0,0 +1,45 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java new file mode 100755 index 0000000000..66c22fa4d2 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -0,0 +1,88 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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 javax.swing.JPanel; +import org.openide.util.lookup.ServiceProvider; + +/** + * Visualization for contacts + * + */ +@ServiceProvider(service=RelationshipsViewer.class) +public class ContactsViewer extends JPanel implements RelationshipsViewer{ + + /** + * Creates new form ContactsViewer + */ + public ContactsViewer() { + initComponents(); + } + + @Override + public String getDisplayName() { + return "Contacts"; + } + + @Override + public JPanel getPanel() { + return this; + } + + @Override + public void setSelectionInfo(SelectionInfo info) { + testLabel.setText(info.getString()); + } + + /** + * 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() { + + testLabel = new javax.swing.JLabel(); + + org.openide.awt.Mnemonics.setLocalizedText(testLabel, org.openide.util.NbBundle.getMessage(ContactsViewer.class, "ContactsViewer.testLabel.text")); // NOI18N + + 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() + .addComponent(testLabel) + .addContainerGap(294, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(testLabel) + .addContainerGap(264, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel testLabel; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form new file mode 100755 index 0000000000..a80677b2ee --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form @@ -0,0 +1,45 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java new file mode 100755 index 0000000000..4624005140 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -0,0 +1,88 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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 javax.swing.JPanel; +import org.openide.util.lookup.ServiceProvider; + +/** + * Visualation for Contacts + * + */ +@ServiceProvider(service=RelationshipsViewer.class) +public class MessagesViewer extends JPanel implements RelationshipsViewer{ + + /** + * Creates new form MessagesViewer + */ + public MessagesViewer() { + initComponents(); + } + + @Override + public String getDisplayName() { + return "Messages"; + } + + @Override + public JPanel getPanel() { + return this; + } + + @Override + public void setSelectionInfo(SelectionInfo info) { + testLabel.setText(info.getString()); + } + + /** + * 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() { + + testLabel = new javax.swing.JLabel(); + + org.openide.awt.Mnemonics.setLocalizedText(testLabel, org.openide.util.NbBundle.getMessage(MessagesViewer.class, "MessagesViewer.testLabel.text")); // NOI18N + + 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() + .addComponent(testLabel) + .addContainerGap(294, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(testLabel) + .addContainerGap(264, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel testLabel; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form new file mode 100755 index 0000000000..a6a3e195a6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form @@ -0,0 +1,34 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java new file mode 100755 index 0000000000..75f2a5beb4 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -0,0 +1,75 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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 javax.swing.JPanel; +import org.openide.util.Lookup; + +/** + * + * + */ +public class RelationshipBrowser extends JPanel { + + /** + * Creates new form RelationshipBrowser + */ + public RelationshipBrowser() { + initComponents(); + + Lookup.getDefault().lookupAll(RelationshipsViewer.class).forEach((viewer) -> { + tabPane.add(viewer.getDisplayName(), viewer.getPanel()); + }); + } + + public void setSelectionInfo(SelectionInfo info) { + ((RelationshipsViewer)tabPane.getSelectedComponent()).setSelectionInfo(info); + + // TODO If we only pass the info to the currently selected tab, we + // need to do something when the tab changes + } + + /** + * 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() { + + tabPane = new javax.swing.JTabbedPane(); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTabbedPane tabPane; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java new file mode 100755 index 0000000000..9a35b42a66 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java @@ -0,0 +1,34 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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 javax.swing.JPanel; + +/** + * + * + */ +public interface RelationshipsViewer { + + public String getDisplayName(); + + public JPanel getPanel(); + + public void setSelectionInfo(SelectionInfo info); +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java new file mode 100755 index 0000000000..0b63e1c129 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java @@ -0,0 +1,46 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.util.Date; + + +/** + * Class to wrap the details of the current selection from the AccountBrowser or + * VisualizationPane + * + */ +public class SelectionInfo { + + private final String displayString; + + SelectionInfo() { + displayString = (new Date()).toString(); + } + + /** + * Temporary function for testing data flow + * + * @return A String representing the time the object was created + */ + public String getString() { + return displayString; + } + +} From ee7df91d725bf6fbe107d98037867c30b7a8bed1 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 9 Apr 2019 10:45:28 -0400 Subject: [PATCH 02/78] Cleaned up comments --- .../communications/AccountsBrowser.java | 14 +++++- .../autopsy/communications/Bundle.properties | 2 + .../communications/Bundle.properties-MERGED | 2 + .../autopsy/communications/MessageNode.java | 40 ++++++++++++++++ .../communications/MessageNodeFactory.java | 48 +++++++++++++++++++ .../RelaionshipSetNodeFactory.java | 19 ++++++-- .../communications/RelationshipBrowser.form | 2 +- .../communications/RelationshipBrowser.java | 2 +- .../communications/RelationshipsViewer.java | 19 +++++++- .../keywordsearch/Bundle.properties-MERGED | 2 +- .../recentactivity/Bundle.properties-MERGED | 2 +- 11 files changed, 142 insertions(+), 10 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/communications/MessageNode.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java index 006fbd846f..d52d2341ab 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java @@ -20,6 +20,9 @@ package org.sleuthkit.autopsy.communications; import com.google.common.eventbus.Subscribe; import java.awt.Component; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import java.util.logging.Level; import javax.swing.JPanel; import javax.swing.ListSelectionModel; @@ -31,11 +34,13 @@ import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerUtils; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; +import org.openide.nodes.Node; import org.openide.util.Lookup; import org.openide.util.lookup.ProxyLookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AccountDeviceInstance; import org.sleuthkit.datamodel.CommunicationsManager; import org.sleuthkit.datamodel.TskCoreException; @@ -58,6 +63,8 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro private final ExplorerManager messageBrowserEM = new ExplorerManager(); private final ExplorerManager accountsTableEM = new ExplorerManager(); + + final RelationshipBrowser relationshipBrowser; /* * This lookup proxies the selection lookup of both he accounts table and @@ -78,17 +85,22 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName()); outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); outline.setColumnSorted(3, false, 1); //it would be nice if the column index wasn't hardcoded + + relationshipBrowser = new RelationshipBrowser(); + jSplitPane1.setRightComponent(relationshipBrowser); accountsTableEM.addPropertyChangeListener(evt -> { if (ExplorerManager.PROP_ROOT_CONTEXT.equals(evt.getPropertyName())) { SwingUtilities.invokeLater(this::setColumnWidths); } else if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) { SwingUtilities.invokeLater(this::setColumnWidths); + } else if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { + relationshipBrowser.setSelectionInfo(new SelectionInfo()); } }); final MessageBrowser messageBrowser = new MessageBrowser(accountsTableEM, messageBrowserEM); - jSplitPane1.setRightComponent(messageBrowser); +// jSplitPane1.setRightComponent(messageBrowser); proxyLookup = new ProxyLookup( messageBrowser.getLookup(), diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index 6665c2e958..de986e82e2 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -39,3 +39,5 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report +ContactsViewer.testLabel.text=No Value Set +MessagesViewer.testLabel.text=No Value Set diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index e4daded09b..88ddd57253 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -83,6 +83,8 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report +ContactsViewer.testLabel.text=No Value Set +MessagesViewer.testLabel.text=No Value Set VisualizationPanel_action_dialogs_title=Communications VisualizationPanel_action_name_text=Snapshot Report VisualizationPanel_module_name=Communications diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java new file mode 100755 index 0000000000..12c1231628 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -0,0 +1,40 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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 org.apache.commons.lang3.StringUtils; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * + */ +final class MessageNode extends BlackboardArtifactNode { + private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName()); + + MessageNode(BlackboardArtifact artifact) { + super(artifact); + // Grabbed this from RelationshipNode, does always work even with internalization? + final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS + String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS + setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java new file mode 100755 index 0000000000..c06bffe692 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java @@ -0,0 +1,48 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.Collection; +import java.util.List; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Node; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * + */ +public class MessageNodeFactory extends ChildFactory { + private final Collection artifacts; + + MessageNodeFactory(Collection artifacts) { + this.artifacts = artifacts; + } + + @Override + protected boolean createKeys(List list) { + list.addAll(artifacts); + return true; + } + + @Override + protected Node createNodeForKey(BlackboardArtifact key) { + return new MessageNode(key); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java index b147ea9537..ac2e5d1c54 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java @@ -1,7 +1,20 @@ /* - * 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. + * Autopsy Forensic Browser + * + * Copyright 2017-2019 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; diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form index a6a3e195a6..7b6fa1d18f 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form @@ -1,6 +1,6 @@ -
+ diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 75f2a5beb4..c934ebade9 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -22,7 +22,7 @@ import javax.swing.JPanel; import org.openide.util.Lookup; /** - * + * Displays the Relationship information for the currently selected accounts. * */ public class RelationshipBrowser extends JPanel { diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java index 9a35b42a66..82464de4ba 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java @@ -21,14 +21,29 @@ package org.sleuthkit.autopsy.communications; import javax.swing.JPanel; /** - * - * + * Interface for Controls wishing to appear in the RelationshipBrowser tabPane. */ public interface RelationshipsViewer { + /** + * 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); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index 6f95dfc82f..ab7e11a07f 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\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-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-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 17d744eee1..7da2ebca7b 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\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-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-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome From 3b810693b8d7ab9297a318fba5c3788e8d847c6d Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 10 Apr 2019 11:35:32 -0400 Subject: [PATCH 03/78] Added OutlineView in the messages tab for displaying the messages of the currently selected accounts --- .../communications/AccountsBrowser.java | 26 ++-- .../autopsy/communications/Bundle.properties | 1 - .../communications/Bundle.properties-MERGED | 1 - .../communications/ContactsViewer.java | 2 +- .../autopsy/communications/MessageNode.java | 136 +++++++++++++++++- .../communications/MessageNodeFactory.java | 48 ------- .../MessagesChildNodeFactory.java | 102 +++++++++++++ .../communications/MessagesViewer.form | 18 +-- .../communications/MessagesViewer.java | 72 +++++++--- .../autopsy/communications/SelectionInfo.java | 28 ++-- 10 files changed, 324 insertions(+), 110 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java index d52d2341ab..671f5ed8a2 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.communications; import com.google.common.eventbus.Subscribe; import java.awt.Component; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; @@ -36,11 +35,11 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.util.Lookup; -import org.openide.util.lookup.ProxyLookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AccountDeviceInstance; +import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.datamodel.CommunicationsManager; import org.sleuthkit.datamodel.TskCoreException; @@ -70,7 +69,7 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro * This lookup proxies the selection lookup of both he accounts table and * the messages table. */ - private final ProxyLookup proxyLookup; + private final Lookup lookup; public AccountsBrowser() { initComponents(); @@ -95,16 +94,19 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro } else if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) { SwingUtilities.invokeLater(this::setColumnWidths); } else if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { - relationshipBrowser.setSelectionInfo(new SelectionInfo()); + final Node[] selectedNodes = accountsTableEM.getSelectedNodes(); + final Set accountDeviceInstances = new HashSet<>(); + + CommunicationsFilter filter = null; + for (final Node node : selectedNodes) { + accountDeviceInstances.add(((AccountDeviceInstanceNode) node).getAccountDeviceInstance()); + filter = ((AccountDeviceInstanceNode)node).getFilter(); + } + relationshipBrowser.setSelectionInfo(new SelectionInfo(accountDeviceInstances, filter)); } }); - final MessageBrowser messageBrowser = new MessageBrowser(accountsTableEM, messageBrowserEM); - -// jSplitPane1.setRightComponent(messageBrowser); - - proxyLookup = new ProxyLookup( - messageBrowser.getLookup(), - ExplorerUtils.createLookup(accountsTableEM, getActionMap())); + + lookup = ExplorerUtils.createLookup(accountsTableEM, getActionMap()); } private void setColumnWidths() { @@ -176,6 +178,6 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro @Override public Lookup getLookup() { - return proxyLookup; + return lookup; } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index de986e82e2..70fb3bc757 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -40,4 +40,3 @@ VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report ContactsViewer.testLabel.text=No Value Set -MessagesViewer.testLabel.text=No Value Set diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index 88ddd57253..c3c4fbc6f1 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -84,7 +84,6 @@ VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report ContactsViewer.testLabel.text=No Value Set -MessagesViewer.testLabel.text=No Value Set VisualizationPanel_action_dialogs_title=Communications VisualizationPanel_action_name_text=Snapshot Report VisualizationPanel_module_name=Communications diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index 66c22fa4d2..1808c8bb62 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -47,7 +47,7 @@ public class ContactsViewer extends JPanel implements RelationshipsViewer{ @Override public void setSelectionInfo(SelectionInfo info) { - testLabel.setText(info.getString()); + } /** diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java index 12c1231628..c557809a54 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -18,23 +18,147 @@ */ package org.sleuthkit.autopsy.communications; +import java.util.TimeZone; +import java.util.logging.Level; import org.apache.commons.lang3.StringUtils; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; +import org.sleuthkit.autopsy.datamodel.ExtractedContent; +import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +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.TimeUtilities; +import org.sleuthkit.datamodel.TskCoreException; /** - * - * + * Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView */ -final class MessageNode extends BlackboardArtifactNode { +final class MessageNode extends AbstractNode { private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName()); + private final BlackboardArtifact artifact; + MessageNode(BlackboardArtifact artifact) { - super(artifact); - // Grabbed this from RelationshipNode, does always work even with internalization? + super(Children.LEAF, Lookups.fixed(artifact)); + this.artifact = artifact; + final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase); + + int typeID = artifact.getArtifactTypeID(); + + String filePath = "org/sleuthkit/autopsy/images/"; //NON-NLS + if( typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) { + filePath = filePath + "mail-icon-16.png"; //NON-NLS + } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { + filePath = filePath + "message.png"; //NON-NLS + } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) { + filePath = filePath + "calllog.png"; //NON-NLS + } + + setIconBaseWithExtension(filePath); + } + + @Override + protected Sheet 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<>("Type", "Type", "Type", getDisplayName())); //NON-NLS + + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); + if (null != fromID) { + //Consider refactoring this to reduce boilerplate + switch (fromID) { + case TSK_EMAIL_MSG: + sheetSet.put(new NodeProperty<>("From", "From", "From", + StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS + sheetSet.put(new NodeProperty<>("To", "To", "To", + StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS + sheetSet.put(new NodeProperty<>("Date", "Date", "Date", + getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS + sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject", + getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS + try { + sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount())); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS + } + + break; + case TSK_MESSAGE: + sheetSet.put(new NodeProperty<>("From", "From", "From", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS + sheetSet.put(new NodeProperty<>("To", "To", "To", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS + sheetSet.put(new NodeProperty<>("Date", "Date", "Date", + getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS + sheetSet.put(new NodeProperty<>("Subject", "Subject", "Subject", + getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS + try { + sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount())); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS + } + break; + case TSK_CALLLOG: + sheetSet.put(new NodeProperty<>("From", "From", "From", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS + sheetSet.put(new NodeProperty<>("To", "To", "To", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS + sheetSet.put(new NodeProperty<>("Date", "Date", "Date", + getAttributeDisplayString(artifact, TSK_DATETIME_START))); //NON-NLS + 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 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 ""; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java deleted file mode 100755 index c06bffe692..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNodeFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2019 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.Collection; -import java.util.List; -import org.openide.nodes.ChildFactory; -import org.openide.nodes.Node; -import org.sleuthkit.datamodel.BlackboardArtifact; - -/** - * - * - */ -public class MessageNodeFactory extends ChildFactory { - private final Collection artifacts; - - MessageNodeFactory(Collection artifacts) { - this.artifacts = artifacts; - } - - @Override - protected boolean createKeys(List list) { - list.addAll(artifacts); - return true; - } - - @Override - protected Node createNodeForKey(BlackboardArtifact key) { - return new MessageNode(key); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java new file mode 100755 index 0000000000..9a1c7d1024 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java @@ -0,0 +1,102 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.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. + * + */ +public class MessagesChildNodeFactory extends ChildFactory { + + private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName()); + + private CommunicationsManager communicationManager = null; + private final 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; + + try { + communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS + } + } + + /** + * 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 list) { + if (communicationManager == null) { + return false; + } + + final Set 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); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form index a80677b2ee..a8a0606f8f 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form @@ -16,30 +16,20 @@ - - - - - + - - - + + - - - - - - + diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java index 4624005140..b5b5159aa3 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -19,25 +19,61 @@ package org.sleuthkit.autopsy.communications; import javax.swing.JPanel; +import javax.swing.ListSelectionModel; +import org.netbeans.swing.outline.DefaultOutlineModel; +import org.netbeans.swing.outline.Outline; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.util.Lookup; +import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; /** - * Visualation for Contacts - * + * Visualation for the messages of the currently selected accounts. */ @ServiceProvider(service=RelationshipsViewer.class) -public class MessagesViewer extends JPanel implements RelationshipsViewer{ +public class MessagesViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { + private final ExplorerManager tableEM = new ExplorerManager(); + private final Lookup lookup; + private final Outline outline; + + @Messages({ + "MessageViewer_tabTitle=Messages", + "MessageViewer_columnHeader_From=From", + "MessageViewer_columnHeader_To=To", + "MessageViewer_columnHeader_Date=Date", + "MessageViewer_columnHeader_Subject=Subject", + "MessageViewer_columnHeader_Attms=Attachments" + }) + /** * Creates new form MessagesViewer */ public MessagesViewer() { 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() + + ); + outline.setRootVisible(false); + outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName()); + + lookup = ExplorerUtils.createLookup(tableEM, getActionMap()); } @Override public String getDisplayName() { - return "Messages"; + return Bundle.MessageViewer_tabTitle(); } @Override @@ -47,7 +83,17 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer{ @Override public void setSelectionInfo(SelectionInfo info) { - testLabel.setText(info.getString()); + tableEM.setRootContext(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true))); + } + + @Override + public ExplorerManager getExplorerManager() { + return tableEM; + } + + @Override + public Lookup getLookup() { + return lookup; } /** @@ -59,30 +105,24 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer{ // //GEN-BEGIN:initComponents private void initComponents() { - testLabel = new javax.swing.JLabel(); - - org.openide.awt.Mnemonics.setLocalizedText(testLabel, org.openide.util.NbBundle.getMessage(MessagesViewer.class, "MessagesViewer.testLabel.text")); // NOI18N + outlineView = new org.openide.explorer.view.OutlineView(); 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() - .addComponent(testLabel) - .addContainerGap(294, Short.MAX_VALUE)) + .addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, 480, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(testLabel) - .addContainerGap(264, Short.MAX_VALUE)) + .addComponent(outlineView, javax.swing.GroupLayout.PREFERRED_SIZE, 475, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 16, Short.MAX_VALUE)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel testLabel; + private org.openide.explorer.view.OutlineView outlineView; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java index 0b63e1c129..6dc370841b 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java +++ b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java @@ -18,7 +18,10 @@ */ package org.sleuthkit.autopsy.communications; -import java.util.Date; +import java.util.Set; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AccountDeviceInstance; +import org.sleuthkit.datamodel.CommunicationsFilter; /** @@ -28,19 +31,22 @@ import java.util.Date; */ public class SelectionInfo { - private final String displayString; + static final private Logger logger = Logger.getLogger(SelectionInfo.class.getName()); + + private final Set accountDeviceInstances; + private final CommunicationsFilter communicationFilter; - SelectionInfo() { - displayString = (new Date()).toString(); + SelectionInfo(Set accountDeviceInstances, CommunicationsFilter communicationFilter) { + this.accountDeviceInstances = accountDeviceInstances; + this.communicationFilter = communicationFilter; } - /** - * Temporary function for testing data flow - * - * @return A String representing the time the object was created - */ - public String getString() { - return displayString; + public Set getAccountDevicesInstances(){ + return accountDeviceInstances; + } + + public CommunicationsFilter getCommunicationsFilter() { + return communicationFilter; } } From 6fcb97429640fcef669ec837db96d7552feab4ba Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 10 Apr 2019 11:40:15 -0400 Subject: [PATCH 04/78] Removed unused import --- .../autopsy/communications/Bundle.properties-MERGED | 6 ++++++ .../org/sleuthkit/autopsy/communications/MessageNode.java | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index c3c4fbc6f1..e5f00998a6 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -23,6 +23,12 @@ FiltersPanel.deviceRequiredLabel.text=Select at least one. FiltersPanel.accountTypeRequiredLabel.text=Select at least one. FiltersPanel.needsRefreshLabel.text=Displayed data is out of date. Press Refresh. MessageBrowser.DataResultViewerTable.title=Messages +MessageViewer_columnHeader_Attms=Attachments +MessageViewer_columnHeader_Date=Date +MessageViewer_columnHeader_From=From +MessageViewer_columnHeader_Subject=Subject +MessageViewer_columnHeader_To=To +MessageViewer_tabTitle=Messages OpenCVTAction.displayName=Communications PinAccountsAction.pluralText=Add Selected Accounts to Visualization PinAccountsAction.singularText=Add Selected Account to Visualization diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java index c557809a54..4a02a1d0ce 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -26,7 +26,6 @@ import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.ExtractedContent; import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; From f4c6d70ff7bfe38419bad411e9713f5735088044 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 11 Apr 2019 11:46:41 -0400 Subject: [PATCH 05/78] Added the message content viewer to the MessageBrowser --- .../autopsy/communications/Bundle.properties | 1 - .../communications/Bundle.properties-MERGED | 1 - .../communications/ContactsViewer.form | 21 +--- .../communications/ContactsViewer.java | 15 +-- .../autopsy/communications/MessageNode.java | 53 +++++---- .../communications/MessagesViewer.form | 13 ++- .../communications/MessagesViewer.java | 101 ++++++++++++++---- .../RelaionshipSetNodeFactory.java | 48 --------- .../communications/RelationshipBrowser.form | 3 + .../communications/RelationshipBrowser.java | 22 +++- 10 files changed, 147 insertions(+), 131 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index 70fb3bc757..6665c2e958 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -39,4 +39,3 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report -ContactsViewer.testLabel.text=No Value Set diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index e5f00998a6..1716b3c7e8 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -89,7 +89,6 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report -ContactsViewer.testLabel.text=No Value Set VisualizationPanel_action_dialogs_title=Communications VisualizationPanel_action_name_text=Snapshot Report VisualizationPanel_module_name=Communications diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form index 81e1e314ef..e7e306cf63 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form @@ -16,30 +16,13 @@ - - - - - + - - - - - + - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index 1808c8bb62..0473ba0e13 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -59,30 +59,19 @@ public class ContactsViewer extends JPanel implements RelationshipsViewer{ // //GEN-BEGIN:initComponents private void initComponents() { - testLabel = new javax.swing.JLabel(); - - org.openide.awt.Mnemonics.setLocalizedText(testLabel, org.openide.util.NbBundle.getMessage(ContactsViewer.class, "ContactsViewer.testLabel.text")); // NOI18N - 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() - .addComponent(testLabel) - .addContainerGap(294, Short.MAX_VALUE)) + .addGap(0, 692, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(testLabel) - .addContainerGap(264, Short.MAX_VALUE)) + .addGap(0, 573, Short.MAX_VALUE) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel testLabel; // 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 4a02a1d0ce..963cd2369e 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -18,14 +18,15 @@ */ 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.AbstractNode; -import org.openide.nodes.Children; import org.openide.nodes.Sheet; -import org.openide.util.lookup.Lookups; +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; @@ -38,42 +39,28 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHO 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; /** * Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView */ -final class MessageNode extends AbstractNode { +final class MessageNode extends BlackboardArtifactNode { private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName()); - private final BlackboardArtifact artifact; - MessageNode(BlackboardArtifact artifact) { - super(Children.LEAF, Lookups.fixed(artifact)); - this.artifact = artifact; + super(artifact); final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase); - - int typeID = artifact.getArtifactTypeID(); - - String filePath = "org/sleuthkit/autopsy/images/"; //NON-NLS - if( typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) { - filePath = filePath + "mail-icon-16.png"; //NON-NLS - } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { - filePath = filePath + "message.png"; //NON-NLS - } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) { - filePath = filePath + "calllog.png"; //NON-NLS - } - - setIconBaseWithExtension(filePath); } @Override protected Sheet createSheet() { Sheet sheet = new Sheet(); + List tags = getAllTagsFromDatabase(); Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); if (sheetSet == null) { sheetSet = Sheet.createPropertiesSet(); @@ -82,6 +69,19 @@ final class MessageNode extends AbstractNode { sheetSet.put(new NodeProperty<>("Type", "Type", "Type", getDisplayName())); //NON-NLS + 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(artifact.getArtifactTypeID()); if (null != fromID) { //Consider refactoring this to reduce boilerplate @@ -160,4 +160,15 @@ final class MessageNode extends AbstractNode { 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/MessagesViewer.form b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form index a8a0606f8f..7368b264e5 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form @@ -16,14 +16,16 @@ - + + - - + + + @@ -31,5 +33,10 @@ + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java index b5b5159aa3..e58bf3a39c 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -18,28 +18,36 @@ */ package org.sleuthkit.autopsy.communications; +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 org.openide.explorer.ExplorerUtils; +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.directorytree.DataResultFilterNode; /** * Visualation for the messages of the currently selected accounts. */ -@ServiceProvider(service=RelationshipsViewer.class) -public class MessagesViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { +@ServiceProvider(service = RelationshipsViewer.class) +public class MessagesViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider{ - private final ExplorerManager tableEM = new ExplorerManager(); - private final Lookup lookup; + private final ExplorerManager tableEM; private final Outline outline; - + private final ModifiableProxyLookup proxyLookup; + private final PropertyChangeListener focusPropertyListener; + @Messages({ "MessageViewer_tabTitle=Messages", "MessageViewer_columnHeader_From=From", @@ -48,13 +56,36 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo "MessageViewer_columnHeader_Subject=Subject", "MessageViewer_columnHeader_Attms=Attachments" }) - + /** * Creates new form MessagesViewer */ public MessagesViewer() { + tableEM = new ExplorerManager(); + 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, 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(), @@ -62,38 +93,60 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo "Date", Bundle.MessageViewer_columnHeader_Date(), "Subject", Bundle.MessageViewer_columnHeader_Subject(), "Attms", Bundle.MessageViewer_columnHeader_Attms() - ); outline.setRootVisible(false); outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName()); - - lookup = ExplorerUtils.createLookup(tableEM, getActionMap()); + + tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> { + if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { + final Node[] nodes = tableEM.getSelectedNodes(); + + if (nodes != null && nodes.length > 0) { + contentViewer.setNode(nodes[0]); + } + } + }); } - + @Override public String getDisplayName() { return Bundle.MessageViewer_tabTitle(); } - + @Override public JPanel getPanel() { return this; } - + @Override public void setSelectionInfo(SelectionInfo info) { - tableEM.setRootContext(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true))); + tableEM.setRootContext(new DataResultFilterNode(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true)), getExplorerManager())); } - - @Override + + @Override public ExplorerManager getExplorerManager() { return tableEM; } - + @Override public Lookup getLookup() { - return lookup; + 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); } /** @@ -106,23 +159,27 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo 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, 480, Short.MAX_VALUE) + .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.PREFERRED_SIZE, 475, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 16, Short.MAX_VALUE)) + .addComponent(outlineView, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 778, Short.MAX_VALUE)) ); }// //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 } diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java deleted file mode 100644 index ac2e5d1c54..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/RelaionshipSetNodeFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2017-2019 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.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 { - - private final Collection artifacts; - - public RelaionshipSetNodeFactory(Collection artifacts) { - this.artifacts = artifacts; - } - - @Override - protected boolean createKeys(List list) { - list.addAll(artifacts); - return true; - } - - @Override - protected Node createNodeForKey(BlackboardArtifact key) { - return new RelationshipNode(key); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form index 7b6fa1d18f..a664317372 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form @@ -27,6 +27,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index c934ebade9..6f60981278 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -27,6 +27,8 @@ import org.openide.util.Lookup; */ public class RelationshipBrowser extends JPanel { + private SelectionInfo currentSelection; + /** * Creates new form RelationshipBrowser */ @@ -38,11 +40,15 @@ public class RelationshipBrowser extends JPanel { }); } + /** + * 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); - - // TODO If we only pass the info to the currently selected tab, we - // need to do something when the tab changes } /** @@ -56,6 +62,12 @@ public class RelationshipBrowser extends JPanel { tabPane = new javax.swing.JTabbedPane(); + tabPane.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + tabPaneStateChanged(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -68,6 +80,10 @@ public class RelationshipBrowser extends JPanel { ); }// //GEN-END:initComponents + private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged + ((RelationshipsViewer)tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); + }//GEN-LAST:event_tabPaneStateChanged + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTabbedPane tabPane; From 6bf77cc1e0a924e0be1cdaf654b2aa201297bf70 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 12 Apr 2019 15:44:26 -0400 Subject: [PATCH 06/78] Relationship viewer with contacts tab is completed --- .../autopsy/communications/Bundle.properties | 1 + .../communications/Bundle.properties-MERGED | 12 ++ .../communications/ContactDetailsPane.form | 61 ++++++++ .../communications/ContactDetailsPane.java | 99 +++++++++++++ .../autopsy/communications/ContactNode.java | 126 +++++++++++++++++ .../ContactsChildNodeFactory.java | 98 +++++++++++++ .../communications/ContactsViewer.form | 18 ++- .../communications/ContactsViewer.java | 131 ++++++++++++++++-- .../autopsy/communications/FiltersPanel.java | 3 +- .../autopsy/communications/MessageNode.java | 23 +-- .../MessagesChildNodeFactory.java | 4 +- .../communications/MessagesViewer.java | 18 +-- .../communications/RelationshipBrowser.java | 18 +-- .../communications/RelationshipsViewer.java | 16 +-- .../autopsy/communications/SelectionInfo.java | 55 +++++--- 15 files changed, 609 insertions(+), 74 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ContactNode.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index 6665c2e958..5f1dd31ce7 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -39,3 +39,4 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report +ContactDetailsPane.nameLabel.text=jLabel1 diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index 1716b3c7e8..de288e42f3 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -3,6 +3,17 @@ AccountNode.accountType=Type AccountNode.device=Device AccountNode.messageCount=Msgs applyText=Apply +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 CTL_OpenCVTAction=Communications CVTTopComponent.name=\ Communications Visualization CVTTopComponent.TabConstraints.tabTitle=Visualize @@ -89,6 +100,7 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report +ContactDetailsPane.nameLabel.text=jLabel1 VisualizationPanel_action_dialogs_title=Communications VisualizationPanel_action_name_text=Snapshot Report VisualizationPanel_module_name=Communications diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.form b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.form new file mode 100755 index 0000000000..2cf54c02ea --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.form @@ -0,0 +1,61 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java new file mode 100755 index 0000000000..0d466dac88 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java @@ -0,0 +1,99 @@ +/* + * 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 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); + } + + /** + * Sets the list of nodes for the property sheet. + * + * @param nodes List of nodes to set + */ + public void setNode(Node[] nodes) { + if (nodes != null) { + nameLabel.setText(nodes[0].getDisplayName()); + } else { + nameLabel.setText(""); + } + + propertySheet.setNodes(nodes); + } + + @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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + 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()) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel nameLabel; + private org.openide.explorer.propertysheet.PropertySheet propertySheet; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java new file mode 100755 index 0000000000..4792e70af8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -0,0 +1,126 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.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_EMAIL; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL; +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; + +/** + * Extends BlackboardArtifactNode to override createSheet to create a contact + * artifact specific sheet. + */ +final class ContactNode extends BlackboardArtifactNode { + + private static final Logger logger = Logger.getLogger(RelationshipNode.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); + + setDisplayName(getAttributeDisplayString(artifact, TSK_NAME)); + } + + @Override + protected Sheet createSheet() { + final BlackboardArtifact artifact = getArtifact(); + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); + if (fromID != TSK_CONTACT) { + return super.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<>("email", Bundle.ContactNode_Email(), "", + getAttributeDisplayString(artifact, TSK_EMAIL))); //NON-NLS + sheetSet.put(new NodeProperty<>("phone", Bundle.ContactNode_Phone(), "", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER))); //NON-NLS + sheetSet.put(new NodeProperty<>("mobile", Bundle.ContactNode_Mobile_Number(), "", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_MOBILE))); //NON-NLS + sheetSet.put(new NodeProperty<>("home", Bundle.ContactNode_Home_Number(), "", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_HOME))); //NON-NLS + sheetSet.put(new NodeProperty<>("office", Bundle.ContactNode_Office_Number(), "", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_OFFICE))); //NON-NLS + sheetSet.put(new NodeProperty<>("url", Bundle.ContactNode_URL(), "", + getAttributeDisplayString(artifact, TSK_URL))); //NON-NLS + + return sheet; + } + + 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(); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java new file mode 100755 index 0000000000..4e5df13589 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java @@ -0,0 +1,98 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.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{ + private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName()); + + private CommunicationsManager communicationManager = null; + private final 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; + + try { + communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS + } + } + + /** + * 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 list) { + if (communicationManager == null) { + return false; + } + + final Set 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); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form index e7e306cf63..166fd065bf 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form @@ -16,13 +16,27 @@ - + + - + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index 0473ba0e13..3e794f48a8 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -18,36 +18,134 @@ */ package org.sleuthkit.autopsy.communications; +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.corecomponents.TableFilterNode; +import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; /** - * Visualization for contacts - * + * Visualization for contact nodes. + * */ -@ServiceProvider(service=RelationshipsViewer.class) -public class ContactsViewer extends JPanel implements RelationshipsViewer{ +@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; + + @NbBundle.Messages({ + "ContactsViewer_tabTitle=Contacts", + "ContactsViewer_columnHeader_Name=Name", + "ContactsViewer_columnHeader_Phone=Phone", + "ContactsViewer_columnHeader_Email=Email",}) /** - * Creates new form ContactsViewer + * Visualization for contact nodes. */ public ContactsViewer() { + tableEM = new ExplorerManager(); + 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, 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( + "email", Bundle.ContactsViewer_columnHeader_Email(), + "phone", Bundle.ContactsViewer_columnHeader_Phone() + ); + outline.setRootVisible(false); + outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + ((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(); + + if (nodes != null && nodes.length > 0) { + contactPane.setEnabled(true); + contactPane.setNode(nodes); + } + } + }); } - + @Override public String getDisplayName() { - return "Contacts"; + 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); + tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new ContactsChildNodeFactory(info), true)), getExplorerManager()), true)); + } + + @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); } /** @@ -59,19 +157,28 @@ public class ContactsViewer extends JPanel implements RelationshipsViewer{ // //GEN-BEGIN:initComponents private void initComponents() { + outlineView = new org.openide.explorer.view.OutlineView(); + contactPane = new org.sleuthkit.autopsy.communications.ContactDetailsPane(); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 692, Short.MAX_VALUE) + .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) - .addGap(0, 573, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(contactPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables + private org.sleuthkit.autopsy.communications.ContactDetailsPane contactPane; + private org.openide.explorer.view.OutlineView outlineView; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java index 587bf47260..287b6f9ae9 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java @@ -49,6 +49,7 @@ import org.sleuthkit.datamodel.CommunicationsFilter.DateRangeFilter; import org.sleuthkit.datamodel.CommunicationsFilter.DeviceFilter; import org.sleuthkit.datamodel.DataSource; import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG; +import static org.sleuthkit.datamodel.Relationship.Type.CONTACT; import static org.sleuthkit.datamodel.Relationship.Type.MESSAGE; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -514,7 +515,7 @@ final public class FiltersPanel extends JPanel { commsFilter.addAndFilter(getAccountTypeFilter()); commsFilter.addAndFilter(getDateRangeFilter()); commsFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter( - ImmutableSet.of(CALL_LOG, MESSAGE))); + ImmutableSet.of(CALL_LOG, MESSAGE, CONTACT))); return commsFilter; } diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java index 963cd2369e..8fd5e44d96 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -47,16 +47,17 @@ import org.sleuthkit.datamodel.TskCoreException; * Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView */ final class MessageNode extends BlackboardArtifactNode { + private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName()); - + MessageNode(BlackboardArtifact artifact) { super(artifact); - + final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase); } - + @Override protected Sheet createSheet() { Sheet sheet = new Sheet(); @@ -68,20 +69,20 @@ final class MessageNode extends BlackboardArtifactNode { } sheetSet.put(new NodeProperty<>("Type", "Type", "Type", getDisplayName())); //NON-NLS - + addScoreProperty(sheetSet, tags); - + CorrelationAttributeInstance correlationAttribute = null; - if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) { + if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) { correlationAttribute = getCorrelationAttributeInstance(); } addCommentProperty(sheetSet, tags, correlationAttribute); - - if (UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) { + + if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) { addCountProperty(sheetSet, correlationAttribute); } final BlackboardArtifact artifact = getArtifact(); - + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); if (null != fromID) { //Consider refactoring this to reduce boilerplate @@ -160,8 +161,8 @@ final class MessageNode extends BlackboardArtifactNode { return ""; } } - - /** + + /** * Circumvent DataResultFilterNode's slightly odd delegation to * BlackboardArtifactNode.getSourceName(). * diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java index 9a1c7d1024..220e3f718f 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java @@ -36,7 +36,7 @@ import org.sleuthkit.datamodel.TskCoreException; * only emails, call logs and messages. * */ -public class MessagesChildNodeFactory extends ChildFactory { +final class MessagesChildNodeFactory extends ChildFactory { private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName()); @@ -62,7 +62,9 @@ public class MessagesChildNodeFactory extends ChildFactory { /** * 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 diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java index e58bf3a39c..ca185eee90 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -35,13 +35,14 @@ 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.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; /** * Visualation for the messages of the currently selected accounts. */ @ServiceProvider(service = RelationshipsViewer.class) -public class MessagesViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider{ +public final class MessagesViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { private final ExplorerManager tableEM; private final Outline outline; @@ -58,7 +59,7 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo }) /** - * Creates new form MessagesViewer + * Visualation for the messages of the currently selected accounts. */ public MessagesViewer() { tableEM = new ExplorerManager(); @@ -69,7 +70,7 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo focusPropertyListener = (final PropertyChangeEvent focusEvent) -> { if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) { final Component newFocusOwner = (Component) focusEvent.getNewValue(); - + if (newFocusOwner == null) { return; } @@ -79,10 +80,10 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo } else if (isDescendingFrom(newFocusOwner, MessagesViewer.this)) { //... or if it is within the Results table. proxyLookup.setNewLookups(createLookup(tableEM, getActionMap())); - + } } - } ; + }; initComponents(); @@ -92,11 +93,12 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo "To", Bundle.MessageViewer_columnHeader_To(), "Date", Bundle.MessageViewer_columnHeader_Date(), "Subject", Bundle.MessageViewer_columnHeader_Subject(), - "Attms", Bundle.MessageViewer_columnHeader_Attms() + "Attms", Bundle.MessageViewer_columnHeader_Attms(), + "Type", "Type" ); outline.setRootVisible(false); outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.AccountNode_accountName()); + ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel("Type"); tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> { if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { @@ -121,7 +123,7 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer, Explo @Override public void setSelectionInfo(SelectionInfo info) { - tableEM.setRootContext(new DataResultFilterNode(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true)), getExplorerManager())); + tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true)), getExplorerManager()), true)); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 6f60981278..8fa082fc2c 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -23,12 +23,12 @@ import org.openide.util.Lookup; /** * Displays the Relationship information for the currently selected accounts. - * + * */ -public class RelationshipBrowser extends JPanel { +final class RelationshipBrowser extends JPanel { private SelectionInfo currentSelection; - + /** * Creates new form RelationshipBrowser */ @@ -39,16 +39,16 @@ public class RelationshipBrowser extends JPanel { tabPane.add(viewer.getDisplayName(), viewer.getPanel()); }); } - + /** - * Sets the value of currentSelection and passes the SelectionInfo onto - * the currently selected\visible tab. - * + * 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); + ((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(info); } /** @@ -81,7 +81,7 @@ public class RelationshipBrowser extends JPanel { }// //GEN-END:initComponents private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged - ((RelationshipsViewer)tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); + ((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); }//GEN-LAST:event_tabPaneStateChanged diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java index 82464de4ba..395182f5d6 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java @@ -24,26 +24,26 @@ import javax.swing.JPanel; * Interface for Controls wishing to appear in the RelationshipBrowser tabPane. */ public interface RelationshipsViewer { - + /** * 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 + * accounts */ - public void setSelectionInfo(SelectionInfo info); + public void setSelectionInfo(SelectionInfo info); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java index 6dc370841b..d4131b2024 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java +++ b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java @@ -19,34 +19,45 @@ package org.sleuthkit.autopsy.communications; import java.util.Set; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AccountDeviceInstance; import org.sleuthkit.datamodel.CommunicationsFilter; - /** * Class to wrap the details of the current selection from the AccountBrowser or * VisualizationPane - * */ -public class SelectionInfo { - - static final private Logger logger = Logger.getLogger(SelectionInfo.class.getName()); +final class SelectionInfo { + + private final Set accountDeviceInstances; + private final CommunicationsFilter communicationFilter; + + /** + * Wraps the details of the currently selected accounts. + * + * @param accountDeviceInstances Selected accountDecivedInstances + * @param communicationFilter Currently selected communications filters + */ + SelectionInfo(Set accountDeviceInstances, CommunicationsFilter communicationFilter) { + this.accountDeviceInstances = accountDeviceInstances; + this.communicationFilter = communicationFilter; + } + + /** + * Returns the currently selected accountDeviceInstances + * + * @return Set of AccountDeviceInstance + */ + public Set getAccountDevicesInstances() { + return accountDeviceInstances; + } + + /** + * Returns the currently selected communications filters. + * + * @return Instance of CommunicationsFilter + */ + public CommunicationsFilter getCommunicationsFilter() { + return communicationFilter; + } - private final Set accountDeviceInstances; - private final CommunicationsFilter communicationFilter; - - SelectionInfo(Set accountDeviceInstances, CommunicationsFilter communicationFilter) { - this.accountDeviceInstances = accountDeviceInstances; - this.communicationFilter = communicationFilter; - } - - public Set getAccountDevicesInstances(){ - return accountDeviceInstances; - } - - public CommunicationsFilter getCommunicationsFilter() { - return communicationFilter; - } - } From febbb1212338aff2b45dbb8f0c274ae40b53c234 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 12 Apr 2019 16:35:17 -0400 Subject: [PATCH 07/78] Added the refresh node functionality to the node factories. --- .../ContactsChildNodeFactory.java | 29 +++++++++++++------ .../communications/ContactsViewer.java | 7 ++++- .../MessagesChildNodeFactory.java | 29 +++++++++++++------ .../communications/MessagesViewer.java | 7 ++++- .../autopsy/communications/SelectionInfo.java | 2 +- 5 files changed, 53 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java index 4e5df13589..08471c5324 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java @@ -38,8 +38,7 @@ import org.sleuthkit.datamodel.TskCoreException; final class ContactsChildNodeFactory extends ChildFactory{ private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName()); - private CommunicationsManager communicationManager = null; - private final SelectionInfo selectionInfo; + private SelectionInfo selectionInfo; /** * Construct a new ContactsChildNodeFactory from the currently selectionInfo @@ -48,13 +47,17 @@ final class ContactsChildNodeFactory extends ChildFactory{ * 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; - - try { - communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); - } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS - } + refresh(true); } /** @@ -65,9 +68,17 @@ final class ContactsChildNodeFactory extends ChildFactory{ */ @Override protected boolean createKeys(List list) { - if (communicationManager == null) { + 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 relationshipSources; diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index 3e794f48a8..3c8cebedd5 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -49,6 +49,7 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, private final Outline outline; private final ModifiableProxyLookup proxyLookup; private final PropertyChangeListener focusPropertyListener; + private final ContactsChildNodeFactory nodeFactory; @NbBundle.Messages({ "ContactsViewer_tabTitle=Contacts", @@ -62,6 +63,7 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, 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 @@ -104,6 +106,8 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, } } }); + + tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(nodeFactory, true)), getExplorerManager()), true)); } @Override @@ -120,7 +124,8 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, public void setSelectionInfo(SelectionInfo info) { contactPane.setNode(new Node[]{new AbstractNode(Children.LEAF)}); contactPane.setEnabled(false); - tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new ContactsChildNodeFactory(info), true)), getExplorerManager()), true)); + + nodeFactory.refresh(info); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java index 220e3f718f..38d5cfa8f0 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java @@ -40,8 +40,7 @@ final class MessagesChildNodeFactory extends ChildFactory { private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName()); - private CommunicationsManager communicationManager = null; - private final SelectionInfo selectionInfo; + private SelectionInfo selectionInfo; /** * Construct a new MessageChildNodeFactory from the currently selectionInfo @@ -51,12 +50,16 @@ final class MessagesChildNodeFactory extends ChildFactory { */ MessagesChildNodeFactory(SelectionInfo selectionInfo) { this.selectionInfo = selectionInfo; - - try { - communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); - } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS - } + } + + /** + * 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); } /** @@ -69,9 +72,17 @@ final class MessagesChildNodeFactory extends ChildFactory { */ @Override protected boolean createKeys(List list) { - if (communicationManager == null) { + 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 relationshipSources; diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java index ca185eee90..45b121e243 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -48,6 +48,7 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer, private final Outline outline; private final ModifiableProxyLookup proxyLookup; private final PropertyChangeListener focusPropertyListener; + private final MessagesChildNodeFactory nodeFactory; @Messages({ "MessageViewer_tabTitle=Messages", @@ -64,6 +65,7 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer, 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 @@ -109,6 +111,8 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer, } } }); + + tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(nodeFactory, true)), getExplorerManager()), true)); } @Override @@ -123,7 +127,8 @@ 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)); +// tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true)), getExplorerManager()), true)); + nodeFactory.refresh(info); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java index d4131b2024..d1a28eb2d6 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java +++ b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java @@ -26,7 +26,7 @@ import org.sleuthkit.datamodel.CommunicationsFilter; * Class to wrap the details of the current selection from the AccountBrowser or * VisualizationPane */ -final class SelectionInfo { +public final class SelectionInfo { private final Set accountDeviceInstances; private final CommunicationsFilter communicationFilter; From 7e7ba8b4deb8151363a930e13b1fc7372bf487ce Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 16 Apr 2019 10:48:56 -0400 Subject: [PATCH 08/78] 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 From c0bfa90032f16227bb480e797e4f9388c8a07348 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 16 Apr 2019 11:23:47 -0400 Subject: [PATCH 09/78] getLogger was referencing wrong class --- Core/src/org/sleuthkit/autopsy/communications/ContactNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java index 4792e70af8..3ed9ffa799 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -47,7 +47,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ final class ContactNode extends BlackboardArtifactNode { - private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName()); + private static final Logger logger = Logger.getLogger(ContactNode.class.getName()); @Messages({ "ContactNode_Name=Name", From d60e12e9083d6502dd43cc5a79230a550ce82f7f Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 16 Apr 2019 11:35:34 -0400 Subject: [PATCH 10/78] Put user visible strings into Messages --- .../autopsy/communications/MessageNode.java | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java index 4a02a1d0ce..ff64185d25 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -24,6 +24,7 @@ import org.apache.commons.lang3.StringUtils; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Sheet; +import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.NodeProperty; @@ -71,6 +72,15 @@ final class MessageNode extends AbstractNode { setIconBaseWithExtension(filePath); } + @Messages({ + "MessageNode_Node_Property_Type=Type", + "MessageNode_Node_Property_From=From", + "MessageNode_Node_Property_To=To", + "MessageNode_Node_Property_Date=Date", + "MessageNode_Node_Property_Subject=Subject", + "MessageNode_Node_Property_Attms=Attachments" + }) + @Override protected Sheet createSheet() { Sheet sheet = new Sheet(); @@ -80,49 +90,49 @@ final class MessageNode extends AbstractNode { sheet.put(sheetSet); } - sheetSet.put(new NodeProperty<>("Type", "Type", "Type", getDisplayName())); //NON-NLS + sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); if (null != fromID) { //Consider refactoring this to reduce boilerplate switch (fromID) { case TSK_EMAIL_MSG: - sheetSet.put(new NodeProperty<>("From", "From", "From", + sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "", StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS - sheetSet.put(new NodeProperty<>("To", "To", "To", + sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "", StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS - sheetSet.put(new NodeProperty<>("Date", "Date", "Date", + sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", 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))); //NON-NLS try { - sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount())); //NON-NLS + sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", artifact.getChildrenCount())); //NON-NLS } catch (TskCoreException ex) { logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS } break; 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))); //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))); //NON-NLS - sheetSet.put(new NodeProperty<>("Date", "Date", "Date", + sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", 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))); //NON-NLS try { - sheetSet.put(new NodeProperty<>("Attms", "Attms", "Attms", artifact.getChildrenCount())); //NON-NLS + sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", artifact.getChildrenCount())); //NON-NLS } catch (TskCoreException ex) { logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS } break; 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))); //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))); //NON-NLS - sheetSet.put(new NodeProperty<>("Date", "Date", "Date", + sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", getAttributeDisplayString(artifact, TSK_DATETIME_START))); //NON-NLS break; default: From a8a6735ecff28af2374b6ced4b010cca04804ec6 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 16 Apr 2019 12:59:01 -0400 Subject: [PATCH 11/78] updated based on review comments --- .../communications/Bundle.properties-MERGED | 7 ++++++- .../communications/ContactDetailsPane.java | 19 ++++++++++++++++--- .../autopsy/communications/ContactNode.java | 1 - 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index de288e42f3..0a92efdbf8 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -33,7 +33,12 @@ FiltersPanel.refreshButton.text=Refresh FiltersPanel.deviceRequiredLabel.text=Select at least one. FiltersPanel.accountTypeRequiredLabel.text=Select at least one. FiltersPanel.needsRefreshLabel.text=Displayed data is out of date. Press Refresh. -MessageBrowser.DataResultViewerTable.title=Messages +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 diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java index 0d466dac88..c22f60fb7e 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java @@ -1,7 +1,20 @@ /* - * 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. + * Autopsy Forensic Browser + * + * Copyright 2019 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; diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java index 4792e70af8..f70cbcf682 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -73,7 +73,6 @@ final class ContactNode extends BlackboardArtifactNode { } Sheet sheet = new Sheet(); - List tags = getAllTagsFromDatabase(); Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); if (sheetSet == null) { sheetSet = Sheet.createPropertiesSet(); From 8a0a84a6f8f80874c068d721bcefb816b4162808 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 16 Apr 2019 13:00:32 -0400 Subject: [PATCH 12/78] update based on review comments --- Core/src/org/sleuthkit/autopsy/communications/ContactNode.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java index f70cbcf682..c73cfff430 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.communications; -import java.util.List; import java.util.TimeZone; import java.util.logging.Level; import org.openide.nodes.Sheet; @@ -37,7 +36,6 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHO import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL; 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; From 475bd75fc85a97e96299467059fe110ecade0f3e Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 17 Apr 2019 11:31:08 -0400 Subject: [PATCH 13/78] Inital work on thumbnailViewer --- .../communications/Bundle.properties-MERGED | 1 + .../communications/RelationshipBrowser.java | 3 + .../autopsy/communications/ThumbnailNode.java | 27 +++++ .../communications/ThumbnailNodeFactory.java | 87 ++++++++++++++ .../communications/ThumbnailViewer.form | 42 +++++++ .../communications/ThumbnailViewer.java | 112 ++++++++++++++++++ 6 files changed, 272 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index 0a92efdbf8..22bc2cdd10 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -51,6 +51,7 @@ PinAccountsAction.singularText=Add Selected Account to Visualization refreshText=Refresh Results ResetAndPinAccountsAction.pluralText=Visualize Only Selected Accounts ResetAndPinAccountsAction.singularText=Visualize Only Selected Account +ThumbnailViewer_Name=Thumbnails UnpinAccountsAction.pluralText=Remove Selected Accounts UnpinAccountsAction.singularText=Remove Selected Account VisalizationPanel.paintingError=Problem painting visualization. diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 0ee0aad79f..83fe1b3ef2 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -30,6 +30,7 @@ final class RelationshipBrowser extends JPanel { private final MessagesViewer messagesViewer; private final ContactsViewer contactsViewer; + private final ThumbnailViewer thumbnailViewer; /** * Creates new form RelationshipBrowser @@ -39,9 +40,11 @@ final class RelationshipBrowser extends JPanel { messagesViewer = new MessagesViewer(); contactsViewer = new ContactsViewer(); + thumbnailViewer = new ThumbnailViewer(); tabPane.add(messagesViewer.getDisplayName(), messagesViewer); tabPane.add(contactsViewer.getDisplayName(), contactsViewer); + tabPane.add(thumbnailViewer.getDisplayName(), thumbnailViewer); } /** diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java new file mode 100755 index 0000000000..229174efea --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java @@ -0,0 +1,27 @@ +/* + * 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 org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.sleuthkit.datamodel.AbstractContent; + +/** + * + * + */ +public class ThumbnailNode extends AbstractNode{ + + private final AbstractContent content; + + public ThumbnailNode(AbstractContent content) { + super(Children.LEAF); + this.content = content; + + setDisplayName(content.getName()); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java new file mode 100755 index 0000000000..529239a056 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java @@ -0,0 +1,87 @@ +/* + * 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.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.autopsy.datamodel.BlackboardArtifactNode; +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; + +/** + * + * @author kelly + */ +public class ThumbnailNodeFactory extends ChildFactory { + private static final Logger logger = Logger.getLogger(ThumbnailNodeFactory.class.getName()); + + private SelectionInfo selectionInfo; + + ThumbnailNodeFactory(SelectionInfo selectionInfo) { + this.selectionInfo = selectionInfo; + } + + @Override + protected boolean createKeys(List 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 relationshipSources; + + try { + relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS + return false; + } + + 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_MESSAGE) { + + try{ + if(bba.hasChildren()) { + + for(Content child: bba.getChildren()) { + list.add(child); + } + } + } catch(TskCoreException ex) { + + } + } + }); + + return true; + } + + @Override + protected Node createNodeForKey(Content key) { + return new ThumbnailNode((AbstractContent)key); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form new file mode 100755 index 0000000000..3a7a0d392b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form @@ -0,0 +1,42 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java new file mode 100755 index 0000000000..84306847e6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java @@ -0,0 +1,112 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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 javax.swing.JPanel; +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.util.Lookup; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.corecomponents.TableFilterNode; +import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; + +/** + * + */ +public class ThumbnailViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { + + private final ExplorerManager tableEM = new ExplorerManager(); + + private final ModifiableProxyLookup proxyLookup; + + @Messages({ + "ThumbnailViewer_Name=Thumbnails" + }) + /** + * Creates new form ThumbnailViewer + */ + public ThumbnailViewer() { + proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap())); + + initComponents(); + } + + @Override + public String getDisplayName() { + return Bundle.ThumbnailViewer_Name(); + } + + @Override + public JPanel getPanel() { + return this; + } + + @Override + public void setSelectionInfo(SelectionInfo info) { +// thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new ThumbnailNodeFactory(info), true)), getExplorerManager()), true)); + tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new ThumbnailNodeFactory(info), true)), getExplorerManager()), true)); + } + + @Override + public ExplorerManager getExplorerManager() { + return tableEM; + } + + @Override + public Lookup getLookup() { + return proxyLookup; + } + + /** + * 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() { + + thumbnailViewer = new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM); + contentViewer = new org.sleuthkit.autopsy.contentviewers.MessageContentViewer(); + + 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.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(contentViewer, 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(thumbnailViewer, javax.swing.GroupLayout.PREFERRED_SIZE, 443, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, Short.MAX_VALUE) + .addComponent(contentViewer, javax.swing.GroupLayout.PREFERRED_SIZE, 532, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer; + private org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail thumbnailViewer; + // End of variables declaration//GEN-END:variables + +} From d96e9f19d3b379f7aa8e4e329e9fa749d57b1926 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 18 Apr 2019 10:22:40 -0400 Subject: [PATCH 14/78] Fixed issue displaying contact information for vcards --- .../autopsy/communications/ContactNode.java | 30 +++++++++++-------- .../communications/ContactsViewer.java | 5 ++-- .../keywordsearch/Bundle.properties-MERGED | 2 +- .../recentactivity/Bundle.properties-MERGED | 2 +- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java index e6c9b64b34..9a59b82a99 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.communications; +import java.util.List; import java.util.TimeZone; import java.util.logging.Level; import org.openide.nodes.Sheet; @@ -30,12 +31,14 @@ import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTA import org.sleuthkit.datamodel.BlackboardAttribute; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL; 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.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL; import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME; +import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TimeUtilities; import org.sleuthkit.datamodel.TskCoreException; @@ -59,7 +62,12 @@ final class ContactNode extends BlackboardArtifactNode { ContactNode(BlackboardArtifact artifact) { super(artifact); - setDisplayName(getAttributeDisplayString(artifact, TSK_NAME)); + 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 @@ -76,19 +84,15 @@ final class ContactNode extends BlackboardArtifactNode { sheetSet = Sheet.createPropertiesSet(); sheet.put(sheetSet); } + + try { + for (BlackboardAttribute bba : artifact.getAttributes()) { + sheetSet.put(new NodeProperty<>(bba.getAttributeType().getTypeName(), bba.getAttributeType().getDisplayName(), "", bba.getDisplayString())); + } - sheetSet.put(new NodeProperty<>("email", Bundle.ContactNode_Email(), "", - getAttributeDisplayString(artifact, TSK_EMAIL))); //NON-NLS - sheetSet.put(new NodeProperty<>("phone", Bundle.ContactNode_Phone(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER))); //NON-NLS - sheetSet.put(new NodeProperty<>("mobile", Bundle.ContactNode_Mobile_Number(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_MOBILE))); //NON-NLS - sheetSet.put(new NodeProperty<>("home", Bundle.ContactNode_Home_Number(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_HOME))); //NON-NLS - sheetSet.put(new NodeProperty<>("office", Bundle.ContactNode_Office_Number(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_OFFICE))); //NON-NLS - sheetSet.put(new NodeProperty<>("url", Bundle.ContactNode_URL(), "", - getAttributeDisplayString(artifact, TSK_URL))); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error getting attribute values.", ex); //NON-NLS + } return sheet; } diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index 3c8cebedd5..5e500b3482 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -37,6 +37,7 @@ import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; +import org.sleuthkit.datamodel.BlackboardAttribute; /** * Visualization for contact nodes. @@ -89,8 +90,8 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, outline = outlineView.getOutline(); outlineView.setPropertyColumns( - "email", Bundle.ContactsViewer_columnHeader_Email(), - "phone", Bundle.ContactsViewer_columnHeader_Phone() + "TSK_EMAIL", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getDisplayName(), + "TSK_PHONE_NUMBER", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getDisplayName() ); outline.setRootVisible(false); outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index 6f95dfc82f..ab7e11a07f 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\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-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-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 17d744eee1..7da2ebca7b 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\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-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-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome From 24c256f3d2988c61bf262b08aa06c35bcda5b9fb Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 18 Apr 2019 14:00:03 -0400 Subject: [PATCH 15/78] Modified ContactNode so that all attributes are correctly being displayed from vcards and contacts with multiple attrbutes of the same type --- .../communications/ContactDetailsPane.java | 2 + .../autopsy/communications/ContactNode.java | 55 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java index c22f60fb7e..d699c7cddf 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java @@ -34,6 +34,8 @@ public final class ContactDetailsPane extends javax.swing.JPanel implements Expl public ContactDetailsPane() { initComponents(); this.setEnabled(false); + + nameLabel.setText(""); } /** diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java index 9a59b82a99..e58161b4f0 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.communications; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.TimeZone; import java.util.logging.Level; @@ -63,7 +65,7 @@ final class ContactNode extends BlackboardArtifactNode { super(artifact); String name = getAttributeDisplayString(artifact, TSK_NAME); - if(name == null || name.trim().isEmpty()) { + if (name == null || name.trim().isEmpty()) { // VCards use TSK_NAME_PERSON instead of TSK_NAME name = getAttributeDisplayString(artifact, TSK_NAME_PERSON); } @@ -84,10 +86,57 @@ final class ContactNode extends BlackboardArtifactNode { 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. try { + HashMap phoneNumList = new HashMap<>(); + HashMap emailList = new HashMap<>(); + HashMap nameList = new HashMap<>(); + HashMap otherList = new HashMap<>(); for (BlackboardAttribute bba : artifact.getAttributes()) { - sheetSet.put(new NodeProperty<>(bba.getAttributeType().getTypeName(), bba.getAttributeType().getDisplayName(), "", bba.getDisplayString())); + if (bba.getAttributeType().getTypeName().contains("TSK_PHONE")) { + phoneNumList.put(bba.getDisplayString(), bba); + } else if (bba.getAttributeType().getTypeName().contains("TSK_EMAIL")) { + emailList.put(bba.getDisplayString(), bba); + } else if (bba.getAttributeType().getTypeName().contains("TSK_NAME")) { + nameList.put(bba.getDisplayString(), bba); + } else { + otherList.put(bba.getDisplayString(), bba); + } + } + String propertyID = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getLabel(); + int count = 0; + for (BlackboardAttribute bba : nameList.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())); + } + } + + propertyID = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getLabel(); + count = 0; + for (BlackboardAttribute bba : phoneNumList.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())); + } + } + + propertyID = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getLabel(); + count = 0; + for (BlackboardAttribute bba : emailList.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())); + } + } + + for (BlackboardAttribute bba1 : otherList.values()) { + sheetSet.put(new NodeProperty<>(bba1.getAttributeType().getTypeName(), bba1.getAttributeType().getDisplayName(), "", bba1.getDisplayString())); } } catch (TskCoreException ex) { From 72b30ea922094eb2c021f08dfa69aa4616944243 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 19 Apr 2019 16:36:36 -0400 Subject: [PATCH 16/78] Updated after review comments from will --- .../autopsy/communications/ContactDetailsPane.java | 2 +- .../sleuthkit/autopsy/communications/ContactNode.java | 9 --------- .../sleuthkit/autopsy/communications/ContactsViewer.java | 6 +----- .../autopsy/communications/VisualizationPanel.java | 1 - 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java index d699c7cddf..a092d41483 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java @@ -44,7 +44,7 @@ public final class ContactDetailsPane extends javax.swing.JPanel implements Expl * @param nodes List of nodes to set */ public void setNode(Node[] nodes) { - if (nodes != null) { + if (nodes != null && nodes.length > 0) { nameLabel.setText(nodes[0].getDisplayName()); } else { nameLabel.setText(""); diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java index e58161b4f0..1f1a54038b 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -18,9 +18,7 @@ */ package org.sleuthkit.autopsy.communications; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.TimeZone; import java.util.logging.Level; import org.openide.nodes.Sheet; @@ -31,16 +29,9 @@ 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_EMAIL; 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.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL; import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME; -import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TimeUtilities; import org.sleuthkit.datamodel.TskCoreException; diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index 5e500b3482..cf1369661c 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -100,11 +100,7 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> { if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { final Node[] nodes = tableEM.getSelectedNodes(); - - if (nodes != null && nodes.length > 0) { - contactPane.setEnabled(true); - contactPane.setNode(nodes); - } + contactPane.setNode(nodes); } }); diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java index d9bbcb8d39..210b0dfbb0 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java @@ -98,7 +98,6 @@ import org.apache.commons.lang3.StringUtils; import org.controlsfx.control.Notifications; import org.jdesktop.layout.GroupLayout; import org.jdesktop.layout.LayoutStyle; -import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; From ae796dfcb013750e79b8db2bb4ce2c965278a3c3 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 22 Apr 2019 10:37:56 -0400 Subject: [PATCH 17/78] Fixed bugs with contact creation --- .../sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java | 8 ++++++++ InternalPythonModules/android/contact.py | 1 + .../sleuthkit/autopsy/thunderbirdparser/VcardParser.java | 4 ++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java index 85fa762300..ce3f971bee 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java @@ -163,6 +163,8 @@ final class ContactAnalyzer { data1 = resultSet.getString("data1"); //NON-NLS mimetype = resultSet.getString("mimetype"); //NON-NLS if (name.equals(oldName) == false) { + bba = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); } if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS @@ -170,6 +172,12 @@ final class ContactAnalyzer { } else { attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1)); } + + // TODO: If this code comes back to life, add code to create the account + // and relationship between the phone numbers & emails. Also + // investigate if the mimetype "vnd.android.cursor.item/phone_v2" + // makes sense in an ios word + oldName = name; bba.addAttributes(attributes); diff --git a/InternalPythonModules/android/contact.py b/InternalPythonModules/android/contact.py index e387d73920..2d442c8e4a 100644 --- a/InternalPythonModules/android/contact.py +++ b/InternalPythonModules/android/contact.py @@ -141,6 +141,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): name = resultSet.getString("display_name") data1 = resultSet.getString("data1") # the phone number or email mimetype = resultSet.getString("mimetype") # either phone or email + attributes = ArrayList() if name != oldName: artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/VcardParser.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/VcardParser.java index d1f5f25777..15d52b536e 100755 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/VcardParser.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/VcardParser.java @@ -193,7 +193,7 @@ final class VcardParser { } } } - ThunderbirdMboxFileIngestModule.addArtifactAttribute(name, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON, attributes); + ThunderbirdMboxFileIngestModule.addArtifactAttribute(name, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, attributes); for (Telephone telephone : vcard.getTelephoneNumbers()) { addPhoneAttributes(telephone, abstractFile, attributes); @@ -412,7 +412,7 @@ final class VcardParser { type.getValue().toUpperCase().replaceAll("\\s+","").split(",")); for (String splitType : splitTelephoneTypes) { - String attributeTypeName = "TSK_PHONE_" + splitType; + String attributeTypeName = "TSK_PHONE_NUMBER_" + splitType; try { BlackboardAttribute.Type attributeType = tskCase.getAttributeType(attributeTypeName); if (attributeType == null) { From 6554fe819dd59706ff467fece7f60e6d514eed5d Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 23 Apr 2019 14:20:12 -0400 Subject: [PATCH 18/78] committing current changes before playing with thumbnail viewer layout --- .../autopsy/communications/MessageNode.java | 1 + .../communications/ThumbnailChildren.java | 110 ++++++++++++++++ .../autopsy/communications/ThumbnailNode.java | 27 ---- .../communications/ThumbnailNodeFactory.java | 87 ------------- .../communications/ThumbnailViewer.form | 9 +- .../communications/ThumbnailViewer.java | 122 ++++++++++++++++-- .../DataResultViewerThumbnail.java | 8 +- 7 files changed, 235 insertions(+), 129 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java delete mode 100755 Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java delete mode 100755 Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java index 9b9a94ac31..1b43441a0a 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageNode.java @@ -70,6 +70,7 @@ final class MessageNode extends BlackboardArtifactNode { @Override protected Sheet createSheet() { + super.createSheet(); Sheet sheet = new Sheet(); List tags = getAllTagsFromDatabase(); Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java new file mode 100755 index 0000000000..9312147f41 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java @@ -0,0 +1,110 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.util.Arrays; +import java.util.HashSet; +import java.util.Set; +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.ImageUtils; +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. + * + */ +public class ThumbnailChildren extends Children.Keys { + private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); + + private final Set thumbnails; + + /* + * Creates the list of thumbnails from the given list of BlackboardArtifacts + */ + ThumbnailChildren(Set artifacts) { + super(false); + thumbnails = new HashSet<>(); + + artifacts.forEach((bba) -> { + try{ + for(Content childContent: bba.getChildren()) { + if(childContent instanceof AbstractFile && ImageUtils.thumbnailSupported((AbstractFile)childContent)) { + thumbnails.add((AbstractFile)childContent); + } + } + } catch(TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS + } + }); + } + + @Override + protected Node[] createNodes(AbstractFile t) { + return new Node[]{new ThumbnailNode(t)}; + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(thumbnails); + } + + /** + * A node for representing a thumbnail. + */ + private static class ThumbnailNode extends FileNode { + + ThumbnailNode(AbstractFile file) { + super(file, false); + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Set 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; + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java deleted file mode 100755 index 229174efea..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNode.java +++ /dev/null @@ -1,27 +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 org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.sleuthkit.datamodel.AbstractContent; - -/** - * - * - */ -public class ThumbnailNode extends AbstractNode{ - - private final AbstractContent content; - - public ThumbnailNode(AbstractContent content) { - super(Children.LEAF); - this.content = content; - - setDisplayName(content.getName()); - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java deleted file mode 100755 index 529239a056..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailNodeFactory.java +++ /dev/null @@ -1,87 +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.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.autopsy.datamodel.BlackboardArtifactNode; -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; - -/** - * - * @author kelly - */ -public class ThumbnailNodeFactory extends ChildFactory { - private static final Logger logger = Logger.getLogger(ThumbnailNodeFactory.class.getName()); - - private SelectionInfo selectionInfo; - - ThumbnailNodeFactory(SelectionInfo selectionInfo) { - this.selectionInfo = selectionInfo; - } - - @Override - protected boolean createKeys(List 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 relationshipSources; - - try { - relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter()); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS - return false; - } - - 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_MESSAGE) { - - try{ - if(bba.hasChildren()) { - - for(Content child: bba.getChildren()) { - list.add(child); - } - } - } catch(TskCoreException ex) { - - } - } - }); - - return true; - } - - @Override - protected Node createNodeForKey(Content key) { - return new ThumbnailNode((AbstractContent)key); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form index 3a7a0d392b..94fe03a560 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form @@ -1,6 +1,6 @@ -
+ @@ -23,9 +23,9 @@ - + - + @@ -37,6 +37,9 @@ + + +
diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java index 84306847e6..5014a6c767 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java @@ -18,25 +18,45 @@ */ 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 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.Children; +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.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; /** * */ -public class ThumbnailViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { +public class ThumbnailViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { + + private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); private final ExplorerManager tableEM = new ExplorerManager(); - + private final PropertyChangeListener focusPropertyListener; + private final ModifiableProxyLookup proxyLookup; - + @Messages({ "ThumbnailViewer_Name=Thumbnails" }) @@ -45,10 +65,36 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl */ public ThumbnailViewer() { 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, ThumbnailViewer.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(); + } + }); } - + @Override public String getDisplayName() { return Bundle.ThumbnailViewer_Name(); @@ -61,8 +107,24 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl @Override public void setSelectionInfo(SelectionInfo info) { -// thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new ThumbnailNodeFactory(info), true)), getExplorerManager()), true)); - tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new ThumbnailNodeFactory(info), true)), getExplorerManager()), true)); + final Set relationshipSources; + + CommunicationsManager communicationManager; + Set 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) { + + } + + thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new ThumbnailChildren(artifactList)), tableEM), true)); } @Override @@ -75,6 +137,44 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl 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 > 0) { + 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 @@ -85,7 +185,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl private void initComponents() { thumbnailViewer = new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM); - contentViewer = new org.sleuthkit.autopsy.contentviewers.MessageContentViewer(); + contentViewer = new MessageDataContent(); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -97,9 +197,9 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(thumbnailViewer, javax.swing.GroupLayout.PREFERRED_SIZE, 443, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(thumbnailViewer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(18, 18, Short.MAX_VALUE) - .addComponent(contentViewer, javax.swing.GroupLayout.PREFERRED_SIZE, 532, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index f03c7b01cf..4f4e41d04e 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -386,7 +386,13 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { rootNodeChildren.cancelLoadingThumbnails(); } try { - if (givenNode != null) { + // There is an issue with ThumbnailViewChildren + // addNotify, that it's call to getChildren.getNodes() does not cause the + // children nodes to be created. Adding a call to getChildren.getNodesCount() + // here will assure that the children nodes are created particularly in the + // case where the DataResultViewerThumbnail stands along from the + // DataResultViewer. See DataResultViewer setNode for more information. + if (givenNode != null && givenNode.getChildren().getNodesCount() > 0) { rootNode = (TableFilterNode) givenNode; /* * Wrap the given node in a ThumbnailViewChildren that will From 682f153c301739d643b24744de2515e66b0a2eda Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 23 Apr 2019 15:24:37 -0400 Subject: [PATCH 19/78] Mucked with all three viewer make sure everything is sizing correctly. Added horizontal scroll pane to RelationshipBrowser. --- .../communications/ContactsViewer.form | 6 ++-- .../communications/ContactsViewer.java | 6 ++-- .../communications/MessagesViewer.form | 4 +-- .../communications/MessagesViewer.java | 4 +-- .../communications/RelationshipBrowser.form | 29 +++++++++++++----- .../communications/RelationshipBrowser.java | 13 ++++++-- .../communications/ThumbnailViewer.form | 30 +++++++++++++++---- .../communications/ThumbnailViewer.java | 23 ++++++++++---- 8 files changed, 86 insertions(+), 29 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form index 166fd065bf..efb5c893a3 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.form @@ -23,9 +23,9 @@ - - - + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index cf1369661c..b43aac70b3 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -172,9 +172,9 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(contactPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .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)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form index 7368b264e5..76cf240254 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.form @@ -23,9 +23,9 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java index fde59ed8f2..3d8ce847c1 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -180,9 +180,9 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer, layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(outlineView, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 778, Short.MAX_VALUE)) + .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form index a664317372..ac40867a25 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.form @@ -16,22 +16,37 @@ - + + + + - + + + + - - - - + + + + - + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 83fe1b3ef2..85695e2eb7 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -67,23 +67,31 @@ final class RelationshipBrowser extends JPanel { // //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) - .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .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) - .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) + .addGap(0, 300, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(scrollPane)) ); }// //GEN-END:initComponents @@ -95,6 +103,7 @@ final class RelationshipBrowser extends JPanel { // 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 } diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form index 94fe03a560..a55bacb9bc 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form @@ -16,30 +16,50 @@ - - + + + + + + + - - - + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java index 5014a6c767..e6029cba92 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java @@ -186,26 +186,39 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl thumbnailViewer = new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM); contentViewer = new MessageDataContent(); + separator = new javax.swing.JSeparator(); + + thumbnailViewer.setMinimumSize(new java.awt.Dimension(350, 102)); + + 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.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .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, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(18, 18, Short.MAX_VALUE) - .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .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)) ); }// //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 From 849ca42c04d44c4465601db330a49de803858e91 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 24 Apr 2019 13:18:20 -0400 Subject: [PATCH 20/78] Final cleanup --- .../org/sleuthkit/autopsy/communications/ThumbnailChildren.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java index 9312147f41..fb23d94eb7 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java @@ -45,7 +45,7 @@ public class ThumbnailChildren extends Children.Keys { private final Set thumbnails; /* - * Creates the list of thumbnails from the given list of BlackboardArtifacts + * Creates the list of thumbnails from the given list of BlackboardArtifacts. */ ThumbnailChildren(Set artifacts) { super(false); From bf9c815359c321e3d320f365c91091b71e298b7c Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 26 Apr 2019 11:32:26 -0400 Subject: [PATCH 21/78] Updated code with propogating lookups and default sorting on size. --- .../communications/AccountsBrowser.java | 9 +-- .../communications/Bundle.properties-MERGED | 2 +- .../communications/RelationshipBrowser.java | 32 +++++++-- .../communications/RelationshipsViewer.java | 3 +- .../communications/ThumbnailChildren.java | 69 ++++++++++++------- .../communications/ThumbnailViewer.java | 10 ++- 6 files changed, 85 insertions(+), 40 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java index 671f5ed8a2..37f2df996c 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java @@ -35,6 +35,7 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.util.Lookup; +import org.openide.util.lookup.ProxyLookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; @@ -60,7 +61,6 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro private final Outline outline; - private final ExplorerManager messageBrowserEM = new ExplorerManager(); private final ExplorerManager accountsTableEM = new ExplorerManager(); final RelationshipBrowser relationshipBrowser; @@ -69,7 +69,7 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro * This lookup proxies the selection lookup of both he accounts table and * the messages table. */ - private final Lookup lookup; + private final ProxyLookup proxyLookup; public AccountsBrowser() { initComponents(); @@ -106,7 +106,8 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro } }); - lookup = ExplorerUtils.createLookup(accountsTableEM, getActionMap()); + proxyLookup = new ProxyLookup(relationshipBrowser.getLookup(), + ExplorerUtils.createLookup(accountsTableEM, getActionMap())); } private void setColumnWidths() { @@ -178,6 +179,6 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro @Override public Lookup getLookup() { - return lookup; + return proxyLookup; } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index 22bc2cdd10..7c5889eada 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -51,7 +51,7 @@ PinAccountsAction.singularText=Add Selected Account to Visualization refreshText=Refresh Results ResetAndPinAccountsAction.pluralText=Visualize Only Selected Accounts ResetAndPinAccountsAction.singularText=Visualize Only Selected Account -ThumbnailViewer_Name=Thumbnails +ThumbnailViewer_Name=Media UnpinAccountsAction.pluralText=Remove Selected Accounts UnpinAccountsAction.singularText=Remove Selected Account VisalizationPanel.paintingError=Problem painting visualization. diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 85695e2eb7..432f5e1dd7 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -18,33 +18,42 @@ */ package org.sleuthkit.autopsy.communications; +import java.awt.Component; import javax.swing.JPanel; +import org.openide.util.Lookup; +import org.openide.util.lookup.ProxyLookup; /** * Displays the Relationship information for the currently selected accounts. * */ -final class RelationshipBrowser extends JPanel { +final class RelationshipBrowser extends JPanel implements Lookup.Provider { private SelectionInfo currentSelection; private final MessagesViewer messagesViewer; private final ContactsViewer contactsViewer; - private final ThumbnailViewer thumbnailViewer; + private final ThumbnailViewer thumbnailsViewer; + + private final ModifiableProxyLookup proxyLookup; /** * Creates new form RelationshipBrowser */ public RelationshipBrowser() { - initComponents(); - messagesViewer = new MessagesViewer(); contactsViewer = new ContactsViewer(); - thumbnailViewer = new ThumbnailViewer(); + thumbnailsViewer = new ThumbnailViewer(); + + proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); + + initComponents(); tabPane.add(messagesViewer.getDisplayName(), messagesViewer); tabPane.add(contactsViewer.getDisplayName(), contactsViewer); - tabPane.add(thumbnailViewer.getDisplayName(), thumbnailViewer); + tabPane.add(thumbnailsViewer.getDisplayName(), thumbnailsViewer); + + } /** @@ -99,6 +108,12 @@ final class RelationshipBrowser extends JPanel { 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 @@ -106,4 +121,9 @@ final class RelationshipBrowser extends JPanel { private javax.swing.JScrollPane scrollPane; private javax.swing.JTabbedPane tabPane; // End of variables declaration//GEN-END:variables + + @Override + public Lookup getLookup() { + return proxyLookup; + } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java index 395182f5d6..ed2accee07 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipsViewer.java @@ -19,11 +19,12 @@ package org.sleuthkit.autopsy.communications; import javax.swing.JPanel; +import org.openide.util.Lookup; /** * Interface for Controls wishing to appear in the RelationshipBrowser tabPane. */ -public interface RelationshipsViewer { +public interface RelationshipsViewer extends Lookup.Provider { /** * Returns the value to be displayed on the "tab" diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java index fb23d94eb7..30a95f35aa 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.communications; 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; @@ -38,32 +39,48 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Factory for creating thumbnail children nodes. * + * Given the current way that DataResultViewerThumbnail works this class must + * extend Children.Keys not ChildNodeFactory. When a ChildNodeFactory is used + * the addNotify function in ThumbnailChildNode ends up wtih a list containing + * just the wait node and the thumbanils never appear. */ -public class ThumbnailChildren extends Children.Keys { +final class ThumbnailChildren extends Children.Keys { + private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); - + private final Set thumbnails; - + /* - * Creates the list of thumbnails from the given list of BlackboardArtifacts. + * 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. */ ThumbnailChildren(Set artifacts) { super(false); - thumbnails = new HashSet<>(); - + 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 && ImageUtils.thumbnailSupported((AbstractFile)childContent)) { - thumbnails.add((AbstractFile)childContent); + try { + for (Content childContent : bba.getChildren()) { + if (childContent instanceof AbstractFile && ImageUtils.thumbnailSupported((AbstractFile) childContent)) { + thumbnails.add((AbstractFile) childContent); } } - } catch(TskCoreException ex) { + } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS } }); } - + @Override protected Node[] createNodes(AbstractFile t) { return new Node[]{new ThumbnailNode(t)}; @@ -74,13 +91,13 @@ public class ThumbnailChildren extends Children.Keys { super.addNotify(); setKeys(thumbnails); } - + /** * A node for representing a thumbnail. */ - private static class ThumbnailNode extends FileNode { - - ThumbnailNode(AbstractFile file) { + static class ThumbnailNode extends FileNode { + + ThumbnailNode(AbstractFile file) { super(file, false); } @@ -88,18 +105,18 @@ public class ThumbnailChildren extends Children.Keys { protected Sheet createSheet() { Sheet sheet = super.createSheet(); Set 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"))); - + 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())){ + for (Node.Property p : sheetSet.getProperties()) { + if (!keepProps.contains(p.getName())) { sheetSet.remove(p.getName()); } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java index e6029cba92..a4dea6493f 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java @@ -58,7 +58,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl private final ModifiableProxyLookup proxyLookup; @Messages({ - "ThumbnailViewer_Name=Thumbnails" + "ThumbnailViewer_Name=Media" }) /** * Creates new form ThumbnailViewer @@ -93,6 +93,8 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl handleNodeSelectionChange(); } }); + + thumbnailViewer.resetComponent(); } @Override @@ -121,7 +123,11 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl }); } 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 ThumbnailChildren(artifactList)), tableEM), true)); From 74ba54f9189d65e835c600cec46473932c0e7c1a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 26 Apr 2019 13:49:34 -0400 Subject: [PATCH 22/78] 4989 move translation ui elements to one package --- .../sleuthkit/autopsy/images/translate32.png | Bin 0 -> 2216 bytes .../texttranslation/ui/Bundle.properties | 14 + .../ui}/Bundle.properties-MERGED | 0 .../ui}/TranslatedTextViewer.java | 4 +- .../ui}/TranslationContentPanel.form | 6 +- .../ui}/TranslationContentPanel.java | 4 +- .../ui/TranslationSettingsPanel.form | 154 ++++++++++ .../ui/TranslationSettingsPanel.java | 286 ++++++++++++++++++ .../TranslationSettingsPanelController.java | 130 ++++++++ .../autopsy/translation/Bundle.properties | 3 - 10 files changed, 591 insertions(+), 10 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/images/translate32.png create mode 100644 Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties rename Core/src/org/sleuthkit/autopsy/{translation => texttranslation/ui}/Bundle.properties-MERGED (100%) rename Core/src/org/sleuthkit/autopsy/{translation => texttranslation/ui}/TranslatedTextViewer.java (99%) rename Core/src/org/sleuthkit/autopsy/{translation => texttranslation/ui}/TranslationContentPanel.form (93%) rename Core/src/org/sleuthkit/autopsy/{translation => texttranslation/ui}/TranslationContentPanel.java (99%) create mode 100644 Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanelController.java delete mode 100644 Core/src/org/sleuthkit/autopsy/translation/Bundle.properties diff --git a/Core/src/org/sleuthkit/autopsy/images/translate32.png b/Core/src/org/sleuthkit/autopsy/images/translate32.png new file mode 100644 index 0000000000000000000000000000000000000000..c3579aed78d0d78f1db06592d5ed37a2833e68f0 GIT binary patch literal 2216 zcmV;Z2v_%sP)K2sKGW zK~z}7)t7s4R979xKj++iX7kuQXkJZ1!lNmqX`w(TD!mZ;pcSbvT4?{MRtL?D*vB{n zR0SW?b~>X{9mjFNiqq<#R;E*%YCDdO$F^X=5>f(b$fh9#nrt@7CfRIuvwQD7{*kaH zkkW_!$1`*PIrrS(?|aYh`~7{-5q!j9n&vW~LI~k#txqbYdOk`V@d1;0f%QU&JB1MI z9mlDhYn|5ms1TwVctt7I^05FgP4hnBDWE_~DPyr1fk5CwLJY$|YmLX_!SDAIi9~R_ z-8Rq;+@_Qoyi$C5g~anr(|k!v`P+CrUew*)En8YzFbo6BvN&<#1gTVt+S*#0nwp44 zqpVxEjsph{aQEGJ8(CRd*E^0AHcj)BQgr%n-z#i*;R!|(Ug z*4D=4-4tgNK6yPKRyget>8mX)Dp3FG4%7$09kXXg<@p;wuh zxRdtwAT>1`==?zrfE*DUb99Yce`~D=(j;1_4#ze+O_&? zH{786X6D{>yYZhs;d2H zZ2)}MG|kV?3BWYXdRvJ5SBJwqcJwH=5d5L0hOgXwGlzEaniB5Dr5_ zpTe^8xbC{0tXj2&($Z$4(UrXZdNYpW2Kd>WGBi!|WH6Ch^5l^gJU9Rx$(zT^H5GK_ z<|5KimYSqI5vOo!3IV)YQo^WJLO6T}Zuc;Le?Q)=K0Llb+}ft++JrlEaH51Y0*zFnksIqJl+NKFdT_G8R0(Iq!wBCheM;Ut!zA zwekKig*ESPPh!g8t%q~jSoaPOY(B#S`V7gqK{Vze9QCs6H%llSO!2*r4g!{y*%@f1 zalT3Y)q8n-xMLPio*tUdGnG~T(HnkWkD~1Y2X1v4nrj!1Lz>KUx+e#Trf&W?q^9S5 z9-Gp_1T|%GT!zMH+f>El6lIc6kL9CLUd=DQjHoL|qBughfTbA{+K#BNt%_Z?cqHb* zkeaLVr#`gFRLA4kLSV_+LaRt5E)--bz=aaj6y~Og40=hW-~FI((2o!>nKU>*1#>Pf0%gQV~apDAr4q zW+f@DtmM$4L#$rCn)>?sS??w$CTMPMCO9_4hKVrNl%RO$B;g+hFtQx}lvj!);B$!q z+)_hIgMhen@w@CYq^3JVLMdhY=}?Ho&ws_~vRY0GKOH&cj6ePp9AIc@XpXk)p!KxE zMZP9~Ym%&6QWQNpiFdJ0zwn_o6mCc&vo+34sRpDMFCdtjsrLL|HpU+2YYb&mJjBC?z1`Q8g?f__w7l$b%o9%u!jD`_2 z9E?gg-a*+EN0N~#Q&vK_GNaglzPeS zIDdVGXNLX^YQPR5Kina`526E4E)ZnrE`h z@!)X#WP~z1$)2H8+?X0CAq;>cN~vGICjg~X2v}xl&AvsYMBE16+J)Tt=Ra~wVx!{GbN7jgC% zPXe%O*Dgv+OWC$<8?o4I{5OltU*spuJHrk3;wCp zivmhxh8W)c=(l4ykmIjclmH@CnR8(QtH6}d^el{^90ZY_-7i}rMqX(SkZal5v9}%AKT^h5+K(A q)j%mw1UNuHa1Q8FO7-*qH2w=%JeXdT;Yu+80000D literal 0 HcmV?d00001 diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties new file mode 100644 index 0000000000..7ff0e4aeef --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties @@ -0,0 +1,14 @@ +OptionsCategory_Name_Machine_Translation=Machine Translation +OptionsCategory_Keywords_Machine_Translation_Settings=Machine Translation Settings +TranslationContentPanel.ShowLabel.text=Show: +TranslationContentPanel.warningLabel2MB.text=Only the first 1MB of text will be displayed +TranslationContentPanel.ocrLabel.text=OCR: +TranslationSettingsPanel.lbIpAddress.text=IP Address or Hostname of Machine Translation Service +TranslationSettingsPanel.tbIpAddress.text= +TranslationSettingsPanel.tbOops.text= +TranslationSettingsPanel.bnTest.text=Test +TranslationSettingsPanel.lbTestIpAddress.text= +TranslationSettingsPanel.IpAddress.toolTipText=IP Address or Hostname of Machine Translation Service +TranslationSettingsPanel.IpAddress.CannotConnect=Cannot connect to machine translation service. +TranslationSettingsPanelController.moduleErr=Module Error +TranslationSettingsPanelController.moduleErr.msg=A module caused an error listening to TranslationSettingsPanelController updates. See log to determine which module. Some data could be incomplete. diff --git a/Core/src/org/sleuthkit/autopsy/translation/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED similarity index 100% rename from Core/src/org/sleuthkit/autopsy/translation/Bundle.properties-MERGED rename to Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED diff --git a/Core/src/org/sleuthkit/autopsy/translation/TranslatedTextViewer.java b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/translation/TranslatedTextViewer.java rename to Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java index 4c3a192aa2..ea3661d81f 100644 --- a/Core/src/org/sleuthkit/autopsy/translation/TranslatedTextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslatedTextViewer.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.translation; +package org.sleuthkit.autopsy.texttranslation.ui; import com.google.common.collect.Lists; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -53,7 +53,7 @@ import org.sleuthkit.autopsy.texttranslation.TranslationException; import org.sleuthkit.datamodel.Content; import java.util.List; import org.sleuthkit.autopsy.coreutils.PlatformUtil; -import org.sleuthkit.autopsy.translation.TranslationContentPanel.DisplayDropdownOptions; +import org.sleuthkit.autopsy.texttranslation.ui.TranslationContentPanel.DisplayDropdownOptions; /** * A TextViewer that displays machine translation of text. diff --git a/Core/src/org/sleuthkit/autopsy/translation/TranslationContentPanel.form b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationContentPanel.form similarity index 93% rename from Core/src/org/sleuthkit/autopsy/translation/TranslationContentPanel.form rename to Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationContentPanel.form index b22da9c7a7..e042876476 100644 --- a/Core/src/org/sleuthkit/autopsy/translation/TranslationContentPanel.form +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationContentPanel.form @@ -102,7 +102,7 @@ - + @@ -148,7 +148,7 @@ - + @@ -159,7 +159,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/translation/TranslationContentPanel.java b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationContentPanel.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/translation/TranslationContentPanel.java rename to Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationContentPanel.java index 480598b15b..0e625f1baa 100644 --- a/Core/src/org/sleuthkit/autopsy/translation/TranslationContentPanel.java +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationContentPanel.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.translation; +package org.sleuthkit.autopsy.texttranslation.ui; import com.google.common.base.Strings; import com.google.common.collect.ImmutableBiMap; @@ -362,7 +362,7 @@ public class TranslationContentPanel extends javax.swing.JPanel { this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 628, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE) .addComponent(jScrollPane1) ); layout.setVerticalGroup( diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.form new file mode 100644 index 0000000000..91b80deaca --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.form @@ -0,0 +1,154 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.java new file mode 100644 index 0000000000..2c21b6ed33 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanel.java @@ -0,0 +1,286 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.texttranslation.ui; + +import java.awt.Color; +import java.awt.Cursor; +import java.util.MissingResourceException; +import javax.swing.ImageIcon; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.openide.util.ImageUtilities; +import org.sleuthkit.autopsy.corecomponents.TextPrompt; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException; +import org.sleuthkit.autopsy.texttranslation.TextTranslationService; +import org.sleuthkit.autopsy.texttranslation.TranslationException; + +public final class TranslationSettingsPanel extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + private static final String HOST_NAME_OR_IP_PROMPT = NbBundle.getMessage(TranslationSettingsPanel.class, "TranslationSettingsPanel.IpAddress.toolTipText"); + private final TranslationSettingsPanel.TextBoxChangedListener textBoxChangedListener; + private final ImageIcon goodIcon; + private final ImageIcon badIcon; + private final TranslationSettingsPanelController controller; + + public TranslationSettingsPanel(TranslationSettingsPanelController theController) { + controller = theController; + initComponents(); + setSize(555, 600); + + // Add text prompt to the text field + TextPrompt textPrompt = new TextPrompt(HOST_NAME_OR_IP_PROMPT, tbIpAddress); + textPrompt.setForeground(Color.LIGHT_GRAY); + textPrompt.changeAlpha(0.9f); + + // Set a "statusIcon" property enabling the DocumentListeners to know which icon to erase when changes are made + tbIpAddress.getDocument().putProperty("statusIcon", lbTestIpAddress); + + /// Register for notifications when the text box gets updated. + textBoxChangedListener = new TranslationSettingsPanel.TextBoxChangedListener(); + tbIpAddress.getDocument().addDocumentListener(textBoxChangedListener); + tbIpAddress.setToolTipText(HOST_NAME_OR_IP_PROMPT); + lbIpAddress.setToolTipText(HOST_NAME_OR_IP_PROMPT); + + goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/good.png", false)); + badIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/bad.png", false)); + } + + /** + * 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() { + + jScrollPane1 = new javax.swing.JScrollPane(); + jPanel1 = new javax.swing.JPanel(); + lbIpAddress = new javax.swing.JLabel(); + bnTest = new javax.swing.JButton(); + tbIpAddress = new javax.swing.JTextField(); + tbOops = new javax.swing.JTextField(); + lbTestIpAddress = new javax.swing.JLabel(); + + setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + jScrollPane1.setBorder(null); + + jPanel1.setPreferredSize(new java.awt.Dimension(410, 100)); + + lbIpAddress.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(lbIpAddress, org.openide.util.NbBundle.getMessage(TranslationSettingsPanel.class, "TranslationSettingsPanel.lbIpAddress.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(bnTest, org.openide.util.NbBundle.getMessage(TranslationSettingsPanel.class, "TranslationSettingsPanel.bnTest.text")); // NOI18N + bnTest.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bnTestActionPerformed(evt); + } + }); + + tbIpAddress.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N + tbIpAddress.setText(org.openide.util.NbBundle.getMessage(TranslationSettingsPanel.class, "TranslationSettingsPanel.tbIpAddress.text")); // NOI18N + + tbOops.setEditable(false); + tbOops.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N + tbOops.setForeground(new java.awt.Color(255, 0, 0)); + tbOops.setText(org.openide.util.NbBundle.getMessage(TranslationSettingsPanel.class, "TranslationSettingsPanel.tbOops.text")); // NOI18N + tbOops.setBorder(null); + + org.openide.awt.Mnemonics.setLocalizedText(lbTestIpAddress, org.openide.util.NbBundle.getMessage(TranslationSettingsPanel.class, "TranslationSettingsPanel.lbTestIpAddress.text")); // NOI18N + lbTestIpAddress.setAutoscrolls(true); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(lbIpAddress) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(bnTest) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lbTestIpAddress, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(tbIpAddress) + .addComponent(tbOops)) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbIpAddress) + .addComponent(bnTest)) + .addComponent(lbTestIpAddress, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tbIpAddress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(13, Short.MAX_VALUE)) + ); + + jScrollPane1.setViewportView(jPanel1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING) + ); + }// //GEN-END:initComponents + + /** + * Allows population of the IP address field from Shared Configuration + * downloads. + * + * @param ipAddress The IP address to populate + */ + void populateIpAddress(String ipAddress) { + tbIpAddress.setText(ipAddress); + } + + private void bnTestActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestActionPerformed + try { + lbTestIpAddress.setIcon(null); + tbOops.setText(""); + store(); + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + /// test if we can connect to the machine translation service + try { + TextTranslationService translator = TextTranslationService.getInstance(); + translator.translate("test input"); + lbTestIpAddress.setIcon(goodIcon); + tbOops.setText(""); + } catch (NoServiceProviderException | TranslationException ex) { + lbTestIpAddress.setIcon(badIcon); + tbOops.setText(NbBundle.getMessage( + TranslationSettingsPanel.class, + "TranslationSettingsPanel.IpAddress.CannotConnect")); + } + + } catch (MissingResourceException ex) { + lbTestIpAddress.setIcon(badIcon); + tbOops.setText(NbBundle.getMessage(TranslationSettingsPanel.class, "TranslationSettingsPanel.IpAddress.CannotConnect") + " " + ex.getMessage()); + } finally { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + }//GEN-LAST:event_bnTestActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton bnTest; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JLabel lbIpAddress; + private javax.swing.JLabel lbTestIpAddress; + private javax.swing.JTextField tbIpAddress; + private javax.swing.JTextField tbOops; + // End of variables declaration//GEN-END:variables + + void load() { + lbTestIpAddress.setIcon(null); + tbOops.setText(""); +// tbIpAddress.setText(getMachineTranslationIpAddress()); + handleButtons(); + controller.changed(); + } + + void store() { +// setMachineTranslationIpAddress(tbIpAddress.getText()); + } + + boolean valid() { + // machine translation configuration can be either IP address or hostname so + // user should be able to save any string. This includes empty string if + // user wants to stop using machine translation. + return true; + } + + /** + * Used to listen for changes in text boxes. It lets the panel know things + * have been updated so we can clear the status icon. + */ + class TextBoxChangedListener implements DocumentListener { + + @Override + public void changedUpdate(DocumentEvent e) { + Object statusIcon = e.getDocument().getProperty("statusIcon"); + if (statusIcon != null) { + ((javax.swing.JLabel) statusIcon).setIcon(null); + } + tbOops.setText(null); + handleButtons(); + controller.changed(); + } + + @Override + public void insertUpdate(DocumentEvent e) { + Object statusIcon = e.getDocument().getProperty("statusIcon"); + if (statusIcon != null) { + ((javax.swing.JLabel) statusIcon).setIcon(null); + } + tbOops.setText(null); + handleButtons(); + controller.changed(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + Object statusIcon = e.getDocument().getProperty("statusIcon"); + if (statusIcon != null) { + ((javax.swing.JLabel) statusIcon).setIcon(null); + } + tbOops.setText(null); + handleButtons(); + controller.changed(); + } + } + + void handleButtons() { + // If IP address is unset, disable the test button, otherwise enable it. + boolean result = ((tbIpAddress == null || tbIpAddress.getText().isEmpty())); + if (result == true) { + lbTestIpAddress.setText(null); + tbOops.setText(null); + } + bnTest.setEnabled(!result); + } + + @Override + public void setEnabled(boolean enabled) { + bnTest.setEnabled(enabled); + lbIpAddress.setEnabled(enabled); + lbTestIpAddress.setEnabled(enabled); + tbIpAddress.setEnabled(enabled); + tbOops.setEnabled(enabled); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanelController.java b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanelController.java new file mode 100644 index 0000000000..8c1187639b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/TranslationSettingsPanelController.java @@ -0,0 +1,130 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.texttranslation.ui; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import javax.swing.JComponent; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; + +@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Machine_Translation", + iconBase = "org/sleuthkit/autopsy/images/translate32.png", + position = 7, + keywords = "#OptionsCategory_Keywords_Machine_Translation_Settings", + keywordsCategory = "Machine Translation") +public class TranslationSettingsPanelController extends OptionsPanelController { + + private TranslationSettingsPanel panel; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private boolean changed; + private static final Logger logger = Logger.getLogger(TranslationSettingsPanelController.class.getName()); + + @Override + public void update() { + getPanel().load(); + changed = false; + } + + @Override + public void applyChanges() { + getPanel().store(); + changed = false; + } + + @Override + public void cancel() { + } + + @Override + public boolean isValid() { + return getPanel().valid(); + } + + @Override + public boolean isChanged() { + return changed; + } + + @Override + public HelpCtx getHelpCtx() { + return null; + } + + @Override + public JComponent getComponent(Lookup masterLookup) { + return getPanel(); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener l) { + if (pcs.getPropertyChangeListeners().length == 0) { + pcs.addPropertyChangeListener(l); + } + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener l) { + /** + * Note the NetBeans Framework does not appear to call this at all. We + * are using NetBeans 7.3.1 Build 201306052037. Perhaps in a future + * version of the Framework this will be resolved, but for now, simply + * don't unregister anything and add one time only in the + * addPropertyChangeListener() method above. + */ + } + + private TranslationSettingsPanel getPanel() { + if (panel == null) { + panel = new TranslationSettingsPanel(this); + } + return panel; + } + + void changed() { + if (!changed) { + changed = true; + + try { + pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true); + } catch (Exception e) { + logger.log(Level.SEVERE, "TranslationSettingsPanelController listener threw exception", e); //NON-NLS + MessageNotifyUtil.Notify.show( + NbBundle.getMessage(this.getClass(), "TranslationSettingsPanelController.moduleErr"), + NbBundle.getMessage(this.getClass(), "TranslationSettingsPanelController.moduleErr.msg"), + MessageNotifyUtil.MessageType.ERROR); + } + } + + try { + pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null); + } catch (Exception e) { + logger.log(Level.SEVERE, "TranslationSettingsPanelController listener threw exception", e); //NON-NLS + MessageNotifyUtil.Notify.show( + NbBundle.getMessage(this.getClass(), "TranslationSettingsPanelController.moduleErr"), + NbBundle.getMessage(this.getClass(), "TranslationSettingsPanelController.moduleErr.msg"), + MessageNotifyUtil.MessageType.ERROR); + } + } +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/translation/Bundle.properties b/Core/src/org/sleuthkit/autopsy/translation/Bundle.properties deleted file mode 100644 index b525b979a1..0000000000 --- a/Core/src/org/sleuthkit/autopsy/translation/Bundle.properties +++ /dev/null @@ -1,3 +0,0 @@ -TranslationContentPanel.warningLabel2MB.text=Only the first 1MB of text will be displayed -TranslationContentPanel.ShowLabel.text=Show: -TranslationContentPanel.ocrLabel.text=OCR: From 6deb2f526f008b58630ebc1e789b80d21f08e9a5 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 29 Apr 2019 17:53:35 -0400 Subject: [PATCH 23/78] Updated based on review comments on contact code --- .../autopsy/communications/ContactNode.java | 78 +++++++++---------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java index 1f1a54038b..f91fe1be78 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactNode.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.communications; import java.util.HashMap; +import java.util.Map; import java.util.TimeZone; import java.util.logging.Level; import org.openide.nodes.Sheet; @@ -79,55 +80,35 @@ final class ContactNode extends BlackboardArtifactNode { } // Sorting the attributes by type so that the duplicates can be removed - // and they can be grouped by type for display. + // 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 phoneNumList = new HashMap<>(); - HashMap emailList = new HashMap<>(); - HashMap nameList = new HashMap<>(); - HashMap otherList = new HashMap<>(); + HashMap phoneNumMap = new HashMap<>(); + HashMap emailMap = new HashMap<>(); + HashMap nameMap = new HashMap<>(); + HashMap otherMap = new HashMap<>(); for (BlackboardAttribute bba : artifact.getAttributes()) { - if (bba.getAttributeType().getTypeName().contains("TSK_PHONE")) { - phoneNumList.put(bba.getDisplayString(), bba); - } else if (bba.getAttributeType().getTypeName().contains("TSK_EMAIL")) { - emailList.put(bba.getDisplayString(), bba); - } else if (bba.getAttributeType().getTypeName().contains("TSK_NAME")) { - nameList.put(bba.getDisplayString(), bba); + 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 { - otherList.put(bba.getDisplayString(), bba); - } - } - String propertyID = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getLabel(); - int count = 0; - for (BlackboardAttribute bba : nameList.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())); + 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); - propertyID = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getLabel(); - count = 0; - for (BlackboardAttribute bba : phoneNumList.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())); - } - } - - propertyID = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getLabel(); - count = 0; - for (BlackboardAttribute bba : emailList.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())); - } - } - - for (BlackboardAttribute bba1 : otherList.values()) { - sheetSet.put(new NodeProperty<>(bba1.getAttributeType().getTypeName(), bba1.getAttributeType().getDisplayName(), "", bba1.getDisplayString())); + for (BlackboardAttribute bba : otherMap.values()) { + sheetSet.put(new NodeProperty<>(bba.getAttributeType().getTypeName(), bba.getAttributeType().getDisplayName(), "", bba.getDisplayString())); } } catch (TskCoreException ex) { @@ -136,6 +117,17 @@ final class ContactNode extends BlackboardArtifactNode { return sheet; } + + private void addPropertiesToSheet(String propertyID, Sheet.Set sheetSet, Map 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 { From ad6c84bc859d555589c8331778badade3b30a140 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 30 Apr 2019 08:08:12 -0400 Subject: [PATCH 24/78] Updated based on review comment --- .../org/sleuthkit/autopsy/communications/ThumbnailChildren.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java index 30a95f35aa..8d9b0bdc4b 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java @@ -40,7 +40,7 @@ import org.sleuthkit.datamodel.TskCoreException; * Factory for creating thumbnail children nodes. * * Given the current way that DataResultViewerThumbnail works this class must - * extend Children.Keys not ChildNodeFactory. When a ChildNodeFactory is used + * extend Children.Keys not ChildFactory. When a ChildFactory is used * the addNotify function in ThumbnailChildNode ends up wtih a list containing * just the wait node and the thumbanils never appear. */ From 6658ca44d5d18fabcd83d8fd43c4d5265717de8f Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 30 Apr 2019 12:26:56 -0400 Subject: [PATCH 25/78] Removed comment from ThumbnailChildren and initalization of the keys to addNotify --- .../communications/ThumbnailChildren.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java index 8d9b0bdc4b..6f60d2cb75 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java @@ -38,17 +38,12 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Factory for creating thumbnail children nodes. - * - * Given the current way that DataResultViewerThumbnail works this class must - * extend Children.Keys not ChildFactory. When a ChildFactory is used - * the addNotify function in ThumbnailChildNode ends up wtih a list containing - * just the wait node and the thumbanils never appear. */ final class ThumbnailChildren extends Children.Keys { private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); - private final Set thumbnails; + private final Set artifacts; /* * Creates the list of thumbnails from the given list of @@ -59,7 +54,22 @@ final class ThumbnailChildren extends Children.Keys { */ ThumbnailChildren(Set artifacts) { super(false); - thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> { + + this.artifacts = artifacts; + + + } + + @Override + protected Node[] createNodes(AbstractFile t) { + return new Node[]{new ThumbnailNode(t)}; + } + + @Override + protected void addNotify() { + super.addNotify(); + + Set thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> { int result = Long.compare(file1.getSize(), file2.getSize()); if (result == 0) { result = file1.getName().compareTo(file2.getName()); @@ -71,7 +81,7 @@ final class ThumbnailChildren extends Children.Keys { artifacts.forEach((bba) -> { try { for (Content childContent : bba.getChildren()) { - if (childContent instanceof AbstractFile && ImageUtils.thumbnailSupported((AbstractFile) childContent)) { + if (childContent instanceof AbstractFile) { thumbnails.add((AbstractFile) childContent); } } @@ -79,16 +89,7 @@ final class ThumbnailChildren extends Children.Keys { logger.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS } }); - } - - @Override - protected Node[] createNodes(AbstractFile t) { - return new Node[]{new ThumbnailNode(t)}; - } - - @Override - protected void addNotify() { - super.addNotify(); + setKeys(thumbnails); } From 3f3e8f859140a9f05d06ef497038d8dabdf36652 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 2 May 2019 09:18:42 -0400 Subject: [PATCH 26/78] Updated code fixing issues found in review by Will --- .../autopsy/communications/Bundle.properties | 2 +- .../communications/Bundle.properties-MERGED | 2 +- .../communications/ContactDetailsPane.java | 6 +- .../communications/ContactsViewer.java | 1 - .../communications/MessagesViewer.java | 3 +- .../communications/ThumbnailViewer.java | 4 +- .../communications/VisualizationPanel.java | 292 +++++++++--------- .../contentviewers/MessageContentViewer.java | 3 +- 8 files changed, 158 insertions(+), 155 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index 0463c566e0..08c5b50959 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -32,7 +32,7 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in VisualizationPanel.zoomInButton.text= VisualizationPanel.zoomOutButton.toolTipText=Zoom out VisualizationPanel.zoomOutButton.text= -VisualizationPanel.fastOrganicLayoutButton.text=Redraw +VisualizationPanel.fastOrganicLayoutButton.text= VisualizationPanel.backButton.text_1= VisualizationPanel.circleLayoutButton.text=Circle VisualizationPanel.organicLayoutButton.text=Organic diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index 843370320d..b840b64e62 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -99,7 +99,7 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in VisualizationPanel.zoomInButton.text= VisualizationPanel.zoomOutButton.toolTipText=Zoom out VisualizationPanel.zoomOutButton.text= -VisualizationPanel.fastOrganicLayoutButton.text=Redraw +VisualizationPanel.fastOrganicLayoutButton.text= VisualizationPanel.backButton.text_1= VisualizationPanel.circleLayoutButton.text=Circle VisualizationPanel.organicLayoutButton.text=Organic diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java index a092d41483..4006877d23 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java @@ -44,13 +44,13 @@ public final class ContactDetailsPane extends javax.swing.JPanel implements Expl * @param nodes List of nodes to set */ public void setNode(Node[] nodes) { - if (nodes != null && nodes.length > 0) { + if (nodes != null && nodes.length == 1) { nameLabel.setText(nodes[0].getDisplayName()); + propertySheet.setNodes(nodes); } else { nameLabel.setText(""); + propertySheet.setNodes(null); } - - propertySheet.setNodes(nodes); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java index b43aac70b3..2bb186aaaf 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ContactsViewer.java @@ -94,7 +94,6 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer, "TSK_PHONE_NUMBER", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getDisplayName() ); outline.setRootVisible(false); - outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.ContactsViewer_columnHeader_Name()); tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> { diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java index 3d8ce847c1..4eb3b1b61e 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessagesViewer.java @@ -99,14 +99,13 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer, "Type", "Type" ); outline.setRootVisible(false); - outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ((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 > 0) { + if (nodes != null && nodes.length == 1) { contentViewer.setNode(nodes[0]); } else { diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java index a4dea6493f..72807810d0 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java @@ -130,7 +130,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl thumbnailViewer.resetComponent(); } - thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new ThumbnailChildren(artifactList)), tableEM), true)); + thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new ThumbnailChildren(artifactList)), tableEM), true, this.getClass().getName())); } @Override @@ -164,7 +164,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl private void handleNodeSelectionChange() { final Node[] nodes = tableEM.getSelectedNodes(); - if (nodes != null && nodes.length > 0) { + if (nodes != null && nodes.length == 1) { AbstractContent thumbnail = nodes[0].getLookup().lookup(AbstractContent.class); if (thumbnail != null) { try { diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java index e87d6464c1..8f202d289b 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java @@ -371,219 +371,223 @@ final public class VisualizationPanel extends JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - splitPane = new JSplitPane(); - borderLayoutPanel = new JPanel(); - placeHolderPanel = new JPanel(); - jTextArea1 = new JTextArea(); - toolbar = new JPanel(); - fastOrganicLayoutButton = new JButton(); - zoomOutButton = new JButton(); - zoomInButton = new JButton(); - zoomActualButton = new JButton(); - fitZoomButton = new JButton(); - jLabel2 = new JLabel(); - zoomLabel = new JLabel(); - clearVizButton = new JButton(); - jSeparator2 = new JToolBar.Separator(); - backButton = new JButton(); - forwardButton = new JButton(); - snapshotButton = new JButton(); - jSeparator3 = new JToolBar.Separator(); - jSeparator4 = new JToolBar.Separator(); - notificationsJFXPanel = new JFXPanel(); + splitPane = new javax.swing.JSplitPane(); + borderLayoutPanel = new javax.swing.JPanel(); + placeHolderPanel = new javax.swing.JPanel(); + jTextArea1 = new javax.swing.JTextArea(); + toolbar = new javax.swing.JPanel(); + fastOrganicLayoutButton = new javax.swing.JButton(); + zoomOutButton = new javax.swing.JButton(); + zoomInButton = new javax.swing.JButton(); + zoomActualButton = new javax.swing.JButton(); + fitZoomButton = new javax.swing.JButton(); + jLabel2 = new javax.swing.JLabel(); + zoomLabel = new javax.swing.JLabel(); + clearVizButton = new javax.swing.JButton(); + jSeparator2 = new javax.swing.JToolBar.Separator(); + backButton = new javax.swing.JButton(); + forwardButton = new javax.swing.JButton(); + snapshotButton = new javax.swing.JButton(); + jSeparator3 = new javax.swing.JToolBar.Separator(); + jSeparator4 = new javax.swing.JToolBar.Separator(); + notificationsJFXPanel = new javafx.embed.swing.JFXPanel(); - setLayout(new BorderLayout()); + setLayout(new java.awt.BorderLayout()); splitPane.setDividerLocation(800); splitPane.setResizeWeight(0.5); - borderLayoutPanel.setLayout(new BorderLayout()); + borderLayoutPanel.setLayout(new java.awt.BorderLayout()); - jTextArea1.setBackground(new Color(240, 240, 240)); + jTextArea1.setBackground(new java.awt.Color(240, 240, 240)); jTextArea1.setColumns(20); jTextArea1.setLineWrap(true); jTextArea1.setRows(5); - jTextArea1.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jTextArea1.text")); // NOI18N + jTextArea1.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jTextArea1.text")); // NOI18N - GroupLayout placeHolderPanelLayout = new GroupLayout(placeHolderPanel); + org.jdesktop.layout.GroupLayout placeHolderPanelLayout = new org.jdesktop.layout.GroupLayout(placeHolderPanel); placeHolderPanel.setLayout(placeHolderPanelLayout); - placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING) + placeHolderPanelLayout.setHorizontalGroup( + placeHolderPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(placeHolderPanelLayout.createSequentialGroup() .addContainerGap(250, Short.MAX_VALUE) - .add(jTextArea1, GroupLayout.PREFERRED_SIZE, 424, GroupLayout.PREFERRED_SIZE) + .add(jTextArea1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 424, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addContainerGap(423, Short.MAX_VALUE)) ); - placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING) + placeHolderPanelLayout.setVerticalGroup( + placeHolderPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(placeHolderPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(jTextArea1, GroupLayout.PREFERRED_SIZE, 47, GroupLayout.PREFERRED_SIZE) - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(jTextArea1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 47, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); - borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER); + borderLayoutPanel.add(placeHolderPanel, java.awt.BorderLayout.CENTER); - fastOrganicLayoutButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N - fastOrganicLayoutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.text")); // NOI18N - fastOrganicLayoutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.toolTipText")); // NOI18N + fastOrganicLayoutButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N + fastOrganicLayoutButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.text")); // NOI18N + fastOrganicLayoutButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.toolTipText")); // NOI18N fastOrganicLayoutButton.setFocusable(false); - fastOrganicLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM); + fastOrganicLayoutButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - zoomOutButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-out-red.png"))); // NOI18N - zoomOutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.text")); // NOI18N - zoomOutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N + zoomOutButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-out-red.png"))); // NOI18N + zoomOutButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.text")); // NOI18N + zoomOutButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N zoomOutButton.setFocusable(false); - zoomOutButton.setHorizontalTextPosition(SwingConstants.CENTER); - zoomOutButton.setVerticalTextPosition(SwingConstants.BOTTOM); - zoomOutButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + zoomOutButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + zoomOutButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + zoomOutButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { zoomOutButtonActionPerformed(evt); } }); - zoomInButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png"))); // NOI18N - zoomInButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.text")); // NOI18N - zoomInButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N + zoomInButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png"))); // NOI18N + zoomInButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.text")); // NOI18N + zoomInButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N zoomInButton.setFocusable(false); - zoomInButton.setHorizontalTextPosition(SwingConstants.CENTER); - zoomInButton.setVerticalTextPosition(SwingConstants.BOTTOM); - zoomInButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + zoomInButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + zoomInButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + zoomInButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { zoomInButtonActionPerformed(evt); } }); - zoomActualButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); // NOI18N - zoomActualButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.text")); // NOI18N - zoomActualButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N + zoomActualButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); // NOI18N + zoomActualButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.text")); // NOI18N + zoomActualButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N zoomActualButton.setFocusable(false); - zoomActualButton.setHorizontalTextPosition(SwingConstants.CENTER); - zoomActualButton.setVerticalTextPosition(SwingConstants.BOTTOM); - zoomActualButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + zoomActualButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + zoomActualButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + zoomActualButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { zoomActualButtonActionPerformed(evt); } }); - fitZoomButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); // NOI18N - fitZoomButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.text")); // NOI18N - fitZoomButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N + fitZoomButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); // NOI18N + fitZoomButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.text")); // NOI18N + fitZoomButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N fitZoomButton.setFocusable(false); - fitZoomButton.setHorizontalTextPosition(SwingConstants.CENTER); - fitZoomButton.setVerticalTextPosition(SwingConstants.BOTTOM); - fitZoomButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + fitZoomButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + fitZoomButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + fitZoomButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { fitZoomButtonActionPerformed(evt); } }); - jLabel2.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jLabel2.text")); // NOI18N + jLabel2.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jLabel2.text")); // NOI18N - zoomLabel.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomLabel.text")); // NOI18N + zoomLabel.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomLabel.text")); // NOI18N - clearVizButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/broom.png"))); // NOI18N - clearVizButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.text_1")); // NOI18N - clearVizButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.toolTipText")); // NOI18N - clearVizButton.setActionCommand(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.actionCommand")); // NOI18N - clearVizButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + clearVizButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/broom.png"))); // NOI18N + clearVizButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.text_1")); // NOI18N + clearVizButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.toolTipText")); // NOI18N + clearVizButton.setActionCommand(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.actionCommand")); // NOI18N + clearVizButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { clearVizButtonActionPerformed(evt); } }); - jSeparator2.setOrientation(SwingConstants.VERTICAL); + jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL); - backButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_previous.png"))); // NOI18N - backButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N - backButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.toolTipText")); // NOI18N - backButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + backButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_previous.png"))); // NOI18N + backButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N + backButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.toolTipText")); // NOI18N + backButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { backButtonActionPerformed(evt); } }); - forwardButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_next.png"))); // NOI18N - forwardButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N - forwardButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.toolTipText")); // NOI18N - forwardButton.setHorizontalTextPosition(SwingConstants.LEADING); - forwardButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + forwardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_next.png"))); // NOI18N + forwardButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N + forwardButton.setToolTipText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.toolTipText")); // NOI18N + forwardButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + forwardButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { forwardButtonActionPerformed(evt); } }); - snapshotButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/report/images/image.png"))); // NOI18N - snapshotButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapshotButton.text_1")); // NOI18N - snapshotButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { + snapshotButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/report/images/image.png"))); // NOI18N + snapshotButton.setText(org.openide.util.NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapshotButton.text_1")); // NOI18N + snapshotButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { snapshotButtonActionPerformed(evt); } }); - jSeparator3.setOrientation(SwingConstants.VERTICAL); + jSeparator3.setOrientation(javax.swing.SwingConstants.VERTICAL); - jSeparator4.setOrientation(SwingConstants.VERTICAL); + jSeparator4.setOrientation(javax.swing.SwingConstants.VERTICAL); - GroupLayout toolbarLayout = new GroupLayout(toolbar); + org.jdesktop.layout.GroupLayout toolbarLayout = new org.jdesktop.layout.GroupLayout(toolbar); toolbar.setLayout(toolbarLayout); - toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING) + toolbarLayout.setHorizontalGroup( + toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(toolbarLayout.createSequentialGroup() .addContainerGap() .add(backButton) - .addPreferredGap(LayoutStyle.RELATED) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(forwardButton) - .addPreferredGap(LayoutStyle.RELATED) - .add(jSeparator4, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jSeparator4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(fastOrganicLayoutButton) - .addPreferredGap(LayoutStyle.RELATED) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(clearVizButton) - .addPreferredGap(LayoutStyle.RELATED) - .add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jSeparator2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jLabel2) - .addPreferredGap(LayoutStyle.RELATED) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(zoomLabel) - .addPreferredGap(LayoutStyle.RELATED) - .add(zoomOutButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED) - .add(zoomInButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED) - .add(zoomActualButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED) - .add(fitZoomButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED) - .add(jSeparator3, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(zoomOutButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(zoomInButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(zoomActualButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 33, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(fitZoomButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jSeparator3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(snapshotButton) - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); - toolbarLayout.setVerticalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING) + toolbarLayout.setVerticalGroup( + toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(toolbarLayout.createSequentialGroup() .add(3, 3, 3) - .add(toolbarLayout.createParallelGroup(GroupLayout.CENTER) + .add(toolbarLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.CENTER) .add(fastOrganicLayoutButton) .add(zoomOutButton) - .add(zoomInButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(zoomActualButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(fitZoomButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(zoomInButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(zoomActualButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(fitZoomButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(jLabel2) .add(zoomLabel) .add(clearVizButton) - .add(jSeparator2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(jSeparator2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(backButton) .add(forwardButton) .add(snapshotButton) - .add(jSeparator3, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(jSeparator4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .add(jSeparator3, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(jSeparator4, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .add(3, 3, 3)) ); - borderLayoutPanel.add(toolbar, BorderLayout.PAGE_START); - borderLayoutPanel.add(notificationsJFXPanel, BorderLayout.PAGE_END); + borderLayoutPanel.add(toolbar, java.awt.BorderLayout.PAGE_START); + borderLayoutPanel.add(notificationsJFXPanel, java.awt.BorderLayout.PAGE_END); splitPane.setLeftComponent(borderLayoutPanel); - add(splitPane, BorderLayout.CENTER); + add(splitPane, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents private void fitZoomButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_fitZoomButtonActionPerformed @@ -874,26 +878,26 @@ final public class VisualizationPanel extends JPanel { } // Variables declaration - do not modify//GEN-BEGIN:variables - private JButton backButton; - private JPanel borderLayoutPanel; - private JButton clearVizButton; - private JButton fastOrganicLayoutButton; - private JButton fitZoomButton; - private JButton forwardButton; - private JLabel jLabel2; - private JToolBar.Separator jSeparator2; - private JToolBar.Separator jSeparator3; - private JToolBar.Separator jSeparator4; - private JTextArea jTextArea1; - private JFXPanel notificationsJFXPanel; - private JPanel placeHolderPanel; - private JButton snapshotButton; - private JSplitPane splitPane; - private JPanel toolbar; - private JButton zoomActualButton; - private JButton zoomInButton; - private JLabel zoomLabel; - private JButton zoomOutButton; + private javax.swing.JButton backButton; + private javax.swing.JPanel borderLayoutPanel; + private javax.swing.JButton clearVizButton; + private javax.swing.JButton fastOrganicLayoutButton; + private javax.swing.JButton fitZoomButton; + private javax.swing.JButton forwardButton; + private javax.swing.JLabel jLabel2; + private javax.swing.JToolBar.Separator jSeparator2; + private javax.swing.JToolBar.Separator jSeparator3; + private javax.swing.JToolBar.Separator jSeparator4; + private javax.swing.JTextArea jTextArea1; + private javafx.embed.swing.JFXPanel notificationsJFXPanel; + private javax.swing.JPanel placeHolderPanel; + private javax.swing.JButton snapshotButton; + private javax.swing.JSplitPane splitPane; + private javax.swing.JPanel toolbar; + private javax.swing.JButton zoomActualButton; + private javax.swing.JButton zoomInButton; + private javax.swing.JLabel zoomLabel; + private javax.swing.JButton zoomOutButton; // End of variables declaration//GEN-END:variables /** diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java index 00c87b3417..e4c99287a9 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java @@ -467,6 +467,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont htmlPanel.reset(); textbodyTextArea.setText(""); msgbodyTabbedPane.setEnabled(false); + drp.setNode(null); } @Override @@ -561,7 +562,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0); msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")"); drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode( - new AttachmentsChildren(attachments)), null), true)); + new AttachmentsChildren(attachments)), drp.getExplorerManager()), true)); } private static String wrapInHtmlBody(String htmlText) { From 806eb76f7fd0933ba98b93cba41912f902cdfda7 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 2 May 2019 11:43:04 -0400 Subject: [PATCH 27/78] inital commit with a message of a merge from my other branch --- ...hildren.java => AttachementsChildren.java} | 44 ++++++++++--------- ...{ThumbnailViewer.form => MediaViewer.form} | 0 ...{ThumbnailViewer.java => MediaViewer.java} | 12 ++--- .../communications/RelationshipBrowser.java | 4 +- .../contentviewers/MessageContentViewer.java | 2 +- .../directorytree/DataResultFilterNode.java | 25 ++++++++++- 6 files changed, 55 insertions(+), 32 deletions(-) rename Core/src/org/sleuthkit/autopsy/communications/{ThumbnailChildren.java => AttachementsChildren.java} (83%) rename Core/src/org/sleuthkit/autopsy/communications/{ThumbnailViewer.form => MediaViewer.form} (100%) rename Core/src/org/sleuthkit/autopsy/communications/{ThumbnailViewer.java => MediaViewer.java} (95%) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/communications/AttachementsChildren.java similarity index 83% rename from Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java rename to Core/src/org/sleuthkit/autopsy/communications/AttachementsChildren.java index 30a95f35aa..429e44d2e7 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AttachementsChildren.java @@ -27,7 +27,6 @@ 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.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.FileNode; @@ -44,11 +43,11 @@ import org.sleuthkit.datamodel.TskCoreException; * the addNotify function in ThumbnailChildNode ends up wtih a list containing * just the wait node and the thumbanils never appear. */ -final class ThumbnailChildren extends Children.Keys { +final class AttachementsChildren extends Children.Keys { - private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); + private static final Logger logger = Logger.getLogger(AttachementsChildren.class.getName()); - private final Set thumbnails; + private final Set artifacts; /* * Creates the list of thumbnails from the given list of @@ -57,9 +56,21 @@ final class ThumbnailChildren extends Children.Keys { * The thumbnails will be initialls sorted by size, then name so that they * appear sorted by size by default. */ - ThumbnailChildren(Set artifacts) { + AttachementsChildren(Set artifacts) { super(false); - thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> { + this.artifacts = artifacts; + } + + @Override + protected Node[] createNodes(AbstractFile t) { + return new Node[]{new AttachmentNode(t)}; + } + + @Override + protected void addNotify() { + super.addNotify(); + + Set attachments = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> { int result = Long.compare(file1.getSize(), file2.getSize()); if (result == 0) { result = file1.getName().compareTo(file2.getName()); @@ -71,33 +82,24 @@ final class ThumbnailChildren extends Children.Keys { artifacts.forEach((bba) -> { try { for (Content childContent : bba.getChildren()) { - if (childContent instanceof AbstractFile && ImageUtils.thumbnailSupported((AbstractFile) childContent)) { - thumbnails.add((AbstractFile) childContent); + if (childContent instanceof AbstractFile) { + attachments.add((AbstractFile) childContent); } } } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS } }); - } - @Override - protected Node[] createNodes(AbstractFile t) { - return new Node[]{new ThumbnailNode(t)}; - } - - @Override - protected void addNotify() { - super.addNotify(); - setKeys(thumbnails); + setKeys(attachments); } /** - * A node for representing a thumbnail. + * A node for representing a attachememt. */ - static class ThumbnailNode extends FileNode { + static class AttachmentNode extends FileNode { - ThumbnailNode(AbstractFile file) { + AttachmentNode(AbstractFile file) { super(file, false); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form b/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.form similarity index 100% rename from Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form rename to Core/src/org/sleuthkit/autopsy/communications/MediaViewer.form diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java similarity index 95% rename from Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java rename to Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java index a4dea6493f..775f9c5f09 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java @@ -46,11 +46,11 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** - * + * This panel is a RelationshipsViewer panel */ -public class ThumbnailViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { +public class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { - private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); + private static final Logger logger = Logger.getLogger(MediaViewer.class.getName()); private final ExplorerManager tableEM = new ExplorerManager(); private final PropertyChangeListener focusPropertyListener; @@ -63,7 +63,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl /** * Creates new form ThumbnailViewer */ - public ThumbnailViewer() { + public MediaViewer() { proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap())); // See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed @@ -78,7 +78,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl 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, ThumbnailViewer.this)) { + } else if (isDescendingFrom(newFocusOwner, MediaViewer.this)) { //... or if it is within the Results table. proxyLookup.setNewLookups(createLookup(tableEM, getActionMap())); @@ -130,7 +130,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl thumbnailViewer.resetComponent(); } - thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new ThumbnailChildren(artifactList)), tableEM), true)); + thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachementsChildren(artifactList)), tableEM), true)); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 432f5e1dd7..49275e4b22 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -33,7 +33,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { private final MessagesViewer messagesViewer; private final ContactsViewer contactsViewer; - private final ThumbnailViewer thumbnailsViewer; + private final MediaViewer thumbnailsViewer; private final ModifiableProxyLookup proxyLookup; @@ -43,7 +43,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { public RelationshipBrowser() { messagesViewer = new MessagesViewer(); contactsViewer = new ContactsViewer(); - thumbnailsViewer = new ThumbnailViewer(); + thumbnailsViewer = new MediaViewer(); proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java index 00c87b3417..92efe43891 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java @@ -561,7 +561,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0); msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")"); drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode( - new AttachmentsChildren(attachments)), null), true)); + new AttachmentsChildren(attachments))), true)); } private static String wrapInHtmlBody(String htmlText) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index c375c7f02b..ef209beee5 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -125,9 +125,23 @@ public class DataResultFilterNode extends FilterNode { static private final DisplayableItemNodeVisitor> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor(); private final DisplayableItemNodeVisitor getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor(); + + // In GetPreferredActionsDisplayableItemNodeVisitor this is expected + // to be 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) { + super(node, null); + this.sourceEm = null; + } + /** * Constructs a node used to wrap another node before passing it to the * result viewers. The wrapper node defines the actions associated with the @@ -635,6 +649,10 @@ public class DataResultFilterNode extends FilterNode { // is a DirectoryTreeFilterNode that wraps the dataModelNode. We need // to set that wrapped node as the selection and root context of the // directory tree explorer manager (sourceEm) + if(sourceEm == null) { + return null; + } + final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0]; return new AbstractAction() { @@ -675,6 +693,9 @@ public class DataResultFilterNode extends FilterNode { * @return */ private AbstractAction openParent(AbstractNode node) { + if(sourceEm == null) { + return null; + } // @@@ Why do we ignore node? Node[] selectedFilterNodes = sourceEm.getSelectedNodes(); Node selectedFilterNode = selectedFilterNodes[0]; From d52b9cfc4dbeb0d6b23aced30028566c8321b743 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 2 May 2019 12:15:58 -0400 Subject: [PATCH 28/78] Revert "inital commit with a message of a merge from my other branch" This reverts commit 806eb76f7fd0933ba98b93cba41912f902cdfda7. --- .../communications/RelationshipBrowser.java | 4 +- ...tsChildren.java => ThumbnailChildren.java} | 44 +++++++++---------- ...{MediaViewer.form => ThumbnailViewer.form} | 0 ...{MediaViewer.java => ThumbnailViewer.java} | 12 ++--- .../contentviewers/MessageContentViewer.java | 2 +- .../directorytree/DataResultFilterNode.java | 25 +---------- 6 files changed, 32 insertions(+), 55 deletions(-) rename Core/src/org/sleuthkit/autopsy/communications/{AttachementsChildren.java => ThumbnailChildren.java} (83%) rename Core/src/org/sleuthkit/autopsy/communications/{MediaViewer.form => ThumbnailViewer.form} (100%) rename Core/src/org/sleuthkit/autopsy/communications/{MediaViewer.java => ThumbnailViewer.java} (95%) diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 49275e4b22..432f5e1dd7 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -33,7 +33,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { private final MessagesViewer messagesViewer; private final ContactsViewer contactsViewer; - private final MediaViewer thumbnailsViewer; + private final ThumbnailViewer thumbnailsViewer; private final ModifiableProxyLookup proxyLookup; @@ -43,7 +43,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { public RelationshipBrowser() { messagesViewer = new MessagesViewer(); contactsViewer = new ContactsViewer(); - thumbnailsViewer = new MediaViewer(); + thumbnailsViewer = new ThumbnailViewer(); proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); diff --git a/Core/src/org/sleuthkit/autopsy/communications/AttachementsChildren.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java similarity index 83% rename from Core/src/org/sleuthkit/autopsy/communications/AttachementsChildren.java rename to Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java index 429e44d2e7..30a95f35aa 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/AttachementsChildren.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java @@ -27,6 +27,7 @@ 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.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.FileNode; @@ -43,11 +44,11 @@ import org.sleuthkit.datamodel.TskCoreException; * the addNotify function in ThumbnailChildNode ends up wtih a list containing * just the wait node and the thumbanils never appear. */ -final class AttachementsChildren extends Children.Keys { +final class ThumbnailChildren extends Children.Keys { - private static final Logger logger = Logger.getLogger(AttachementsChildren.class.getName()); + private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); - private final Set artifacts; + private final Set thumbnails; /* * Creates the list of thumbnails from the given list of @@ -56,21 +57,9 @@ final class AttachementsChildren extends Children.Keys { * The thumbnails will be initialls sorted by size, then name so that they * appear sorted by size by default. */ - AttachementsChildren(Set artifacts) { + ThumbnailChildren(Set artifacts) { super(false); - this.artifacts = artifacts; - } - - @Override - protected Node[] createNodes(AbstractFile t) { - return new Node[]{new AttachmentNode(t)}; - } - - @Override - protected void addNotify() { - super.addNotify(); - - Set attachments = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> { + thumbnails = new TreeSet<>((AbstractFile file1, AbstractFile file2) -> { int result = Long.compare(file1.getSize(), file2.getSize()); if (result == 0) { result = file1.getName().compareTo(file2.getName()); @@ -82,24 +71,33 @@ final class AttachementsChildren extends Children.Keys { artifacts.forEach((bba) -> { try { for (Content childContent : bba.getChildren()) { - if (childContent instanceof AbstractFile) { - attachments.add((AbstractFile) childContent); + if (childContent instanceof AbstractFile && ImageUtils.thumbnailSupported((AbstractFile) childContent)) { + thumbnails.add((AbstractFile) childContent); } } } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get children from artifact.", ex); //NON-NLS } }); + } - setKeys(attachments); + @Override + protected Node[] createNodes(AbstractFile t) { + return new Node[]{new ThumbnailNode(t)}; + } + + @Override + protected void addNotify() { + super.addNotify(); + setKeys(thumbnails); } /** - * A node for representing a attachememt. + * A node for representing a thumbnail. */ - static class AttachmentNode extends FileNode { + static class ThumbnailNode extends FileNode { - AttachmentNode(AbstractFile file) { + ThumbnailNode(AbstractFile file) { super(file, false); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.form b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form similarity index 100% rename from Core/src/org/sleuthkit/autopsy/communications/MediaViewer.form rename to Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form diff --git a/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java similarity index 95% rename from Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java rename to Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java index 775f9c5f09..a4dea6493f 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java @@ -46,11 +46,11 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** - * This panel is a RelationshipsViewer panel + * */ -public class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { +public class ThumbnailViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { - private static final Logger logger = Logger.getLogger(MediaViewer.class.getName()); + private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); private final ExplorerManager tableEM = new ExplorerManager(); private final PropertyChangeListener focusPropertyListener; @@ -63,7 +63,7 @@ public class MediaViewer extends JPanel implements RelationshipsViewer, Explorer /** * Creates new form ThumbnailViewer */ - public MediaViewer() { + public ThumbnailViewer() { proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap())); // See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed @@ -78,7 +78,7 @@ public class MediaViewer extends JPanel implements RelationshipsViewer, Explorer 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)) { + } else if (isDescendingFrom(newFocusOwner, ThumbnailViewer.this)) { //... or if it is within the Results table. proxyLookup.setNewLookups(createLookup(tableEM, getActionMap())); @@ -130,7 +130,7 @@ public class MediaViewer extends JPanel implements RelationshipsViewer, Explorer thumbnailViewer.resetComponent(); } - thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachementsChildren(artifactList)), tableEM), true)); + thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new ThumbnailChildren(artifactList)), tableEM), true)); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java index 92efe43891..00c87b3417 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java @@ -561,7 +561,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0); msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")"); drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode( - new AttachmentsChildren(attachments))), true)); + new AttachmentsChildren(attachments)), null), true)); } private static String wrapInHtmlBody(String htmlText) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index ef209beee5..c375c7f02b 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -125,23 +125,9 @@ public class DataResultFilterNode extends FilterNode { static private final DisplayableItemNodeVisitor> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor(); private final DisplayableItemNodeVisitor getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor(); - - // In GetPreferredActionsDisplayableItemNodeVisitor this is expected - // to be the directory tree explorer manager - private final ExplorerManager sourceEm; - /** - * Constructs a node used to wrap another node before passing it to the - * result viewers. The wrapper node defines the actions associated with the - * wrapped node and may filter out some of its children. - * - * @param node The node to wrap. - */ - public DataResultFilterNode(Node node) { - super(node, null); - this.sourceEm = null; - } - + 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 @@ -649,10 +635,6 @@ public class DataResultFilterNode extends FilterNode { // is a DirectoryTreeFilterNode that wraps the dataModelNode. We need // to set that wrapped node as the selection and root context of the // directory tree explorer manager (sourceEm) - if(sourceEm == null) { - return null; - } - final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0]; return new AbstractAction() { @@ -693,9 +675,6 @@ public class DataResultFilterNode extends FilterNode { * @return */ private AbstractAction openParent(AbstractNode node) { - if(sourceEm == null) { - return null; - } // @@@ Why do we ignore node? Node[] selectedFilterNodes = sourceEm.getSelectedNodes(); Node selectedFilterNode = selectedFilterNodes[0]; From c8e41658f90fddf2aa661745ad1630033aa4351b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 2 May 2019 12:49:04 -0400 Subject: [PATCH 29/78] Updated based on comments from Richard and Will, added constructor to DataResultFilterNode that doesn't take an explorermanger --- ...Children.java => AttachmentsChildren.java} | 13 ++++++------- .../communications/Bundle.properties-MERGED | 2 +- ...{ThumbnailViewer.form => MediaViewer.form} | 3 +++ ...{ThumbnailViewer.java => MediaViewer.java} | 17 +++++++++-------- .../communications/RelationshipBrowser.java | 7 +++---- .../contentviewers/MessageContentViewer.java | 2 +- .../directorytree/DataResultFilterNode.java | 19 +++++++++++++++++++ 7 files changed, 42 insertions(+), 21 deletions(-) rename Core/src/org/sleuthkit/autopsy/communications/{ThumbnailChildren.java => AttachmentsChildren.java} (91%) rename Core/src/org/sleuthkit/autopsy/communications/{ThumbnailViewer.form => MediaViewer.form} (94%) rename Core/src/org/sleuthkit/autopsy/communications/{ThumbnailViewer.java => MediaViewer.java} (93%) diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java b/Core/src/org/sleuthkit/autopsy/communications/AttachmentsChildren.java similarity index 91% rename from Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java rename to Core/src/org/sleuthkit/autopsy/communications/AttachmentsChildren.java index 6f60d2cb75..d53e9c6475 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailChildren.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AttachmentsChildren.java @@ -27,7 +27,6 @@ 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.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.FileNode; @@ -39,9 +38,9 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Factory for creating thumbnail children nodes. */ -final class ThumbnailChildren extends Children.Keys { +final class AttachmentsChildren extends Children.Keys { - private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); + private static final Logger logger = Logger.getLogger(AttachmentsChildren.class.getName()); private final Set artifacts; @@ -52,7 +51,7 @@ final class ThumbnailChildren extends Children.Keys { * The thumbnails will be initialls sorted by size, then name so that they * appear sorted by size by default. */ - ThumbnailChildren(Set artifacts) { + AttachmentsChildren(Set artifacts) { super(false); this.artifacts = artifacts; @@ -62,7 +61,7 @@ final class ThumbnailChildren extends Children.Keys { @Override protected Node[] createNodes(AbstractFile t) { - return new Node[]{new ThumbnailNode(t)}; + return new Node[]{new AttachementNode(t)}; } @Override @@ -96,9 +95,9 @@ final class ThumbnailChildren extends Children.Keys { /** * A node for representing a thumbnail. */ - static class ThumbnailNode extends FileNode { + static class AttachementNode extends FileNode { - ThumbnailNode(AbstractFile file) { + AttachementNode(AbstractFile file) { super(file, false); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index b840b64e62..7fe9cce0c1 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -33,6 +33,7 @@ FiltersPanel.refreshButton.text=Refresh FiltersPanel.deviceRequiredLabel.text=Select at least one. FiltersPanel.accountTypeRequiredLabel.text=Select at least one. FiltersPanel.needsRefreshLabel.text=Displayed data is out of date. Press Refresh. +MediaViewer_Name=Media MessageNode_Node_Property_Attms=Attachments MessageNode_Node_Property_Date=Date MessageNode_Node_Property_From=From @@ -51,7 +52,6 @@ PinAccountsAction.singularText=Add Selected Account to Visualization refreshText=Refresh Results ResetAndPinAccountsAction.pluralText=Visualize Only Selected Accounts ResetAndPinAccountsAction.singularText=Visualize Only Selected Account -ThumbnailViewer_Name=Media UnpinAccountsAction.pluralText=Remove Selected Accounts UnpinAccountsAction.singularText=Remove Selected Account VisalizationPanel.paintingError=Problem painting visualization. diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form b/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.form similarity index 94% rename from Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form rename to Core/src/org/sleuthkit/autopsy/communications/MediaViewer.form index a55bacb9bc..8f311d3dd4 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.form @@ -44,6 +44,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java b/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java rename to Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java index 72807810d0..aa7d5ce707 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/ThumbnailViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MediaViewer.java @@ -46,11 +46,11 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** - * + * A Panel that shows the media (thumbnails) for the selected account. */ -public class ThumbnailViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { +final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider { - private static final Logger logger = Logger.getLogger(ThumbnailChildren.class.getName()); + private static final Logger logger = Logger.getLogger(MediaViewer.class.getName()); private final ExplorerManager tableEM = new ExplorerManager(); private final PropertyChangeListener focusPropertyListener; @@ -58,12 +58,12 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl private final ModifiableProxyLookup proxyLookup; @Messages({ - "ThumbnailViewer_Name=Media" + "MediaViewer_Name=Media" }) /** * Creates new form ThumbnailViewer */ - public ThumbnailViewer() { + public MediaViewer() { proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap())); // See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed @@ -78,7 +78,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl 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, ThumbnailViewer.this)) { + } else if (isDescendingFrom(newFocusOwner, MediaViewer.this)) { //... or if it is within the Results table. proxyLookup.setNewLookups(createLookup(tableEM, getActionMap())); @@ -99,7 +99,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl @Override public String getDisplayName() { - return Bundle.ThumbnailViewer_Name(); + return Bundle.MediaViewer_Name(); } @Override @@ -130,7 +130,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl thumbnailViewer.resetComponent(); } - thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new ThumbnailChildren(artifactList)), tableEM), true, this.getClass().getName())); + thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentsChildren(artifactList)), tableEM), true, this.getClass().getName())); } @Override @@ -195,6 +195,7 @@ public class ThumbnailViewer extends JPanel implements RelationshipsViewer, Expl 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)); diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 432f5e1dd7..2bf82f5e81 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.communications; import java.awt.Component; import javax.swing.JPanel; import org.openide.util.Lookup; -import org.openide.util.lookup.ProxyLookup; /** * Displays the Relationship information for the currently selected accounts. @@ -33,7 +32,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { private final MessagesViewer messagesViewer; private final ContactsViewer contactsViewer; - private final ThumbnailViewer thumbnailsViewer; + private final MediaViewer mediaViewer; private final ModifiableProxyLookup proxyLookup; @@ -43,7 +42,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { public RelationshipBrowser() { messagesViewer = new MessagesViewer(); contactsViewer = new ContactsViewer(); - thumbnailsViewer = new ThumbnailViewer(); + mediaViewer = new MediaViewer(); proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); @@ -51,7 +50,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { tabPane.add(messagesViewer.getDisplayName(), messagesViewer); tabPane.add(contactsViewer.getDisplayName(), contactsViewer); - tabPane.add(thumbnailsViewer.getDisplayName(), thumbnailsViewer); + tabPane.add(mediaViewer.getDisplayName(), mediaViewer); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java index e4c99287a9..48f7e4e82e 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java @@ -562,7 +562,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0); msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")"); drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode( - new AttachmentsChildren(attachments)), drp.getExplorerManager()), true)); + new AttachmentsChildren(attachments))), true)); } private static String wrapInHtmlBody(String htmlText) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index c375c7f02b..d98e58fe70 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -126,7 +126,20 @@ public class DataResultFilterNode extends FilterNode { static private final DisplayableItemNodeVisitor> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor(); private final DisplayableItemNodeVisitor getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor(); + // Assumptions are made in GetPreferredActionsDisplayableItemNodeVisitor that + // sourceEm is the directory tree explorer manager. private final ExplorerManager sourceEm; + + /** + * Constructs a node used to wrap another node before passing it to the + * result viewers. The wrapper node defines the actions associated with the + * wrapped node and may filter out some of its children. + * + * @param node The node to wrap. + */ + public DataResultFilterNode(Node node) { + this(node, null); + } /** * Constructs a node used to wrap another node before passing it to the @@ -635,6 +648,9 @@ public class DataResultFilterNode extends FilterNode { // is a DirectoryTreeFilterNode that wraps the dataModelNode. We need // to set that wrapped node as the selection and root context of the // directory tree explorer manager (sourceEm) + if(sourceEm == null) { + return null; + } final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0]; return new AbstractAction() { @@ -675,6 +691,9 @@ public class DataResultFilterNode extends FilterNode { * @return */ private AbstractAction openParent(AbstractNode node) { + if(sourceEm == null) { + return null; + } // @@@ Why do we ignore node? Node[] selectedFilterNodes = sourceEm.getSelectedNodes(); Node selectedFilterNode = selectedFilterNodes[0]; From 4f6b226db6de0ce452a7ac9aabacde15e39963b4 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 2 May 2019 14:48:56 -0400 Subject: [PATCH 30/78] Added support for drawing 'tag' boxes overtop images --- .../contentviewers/MediaViewImagePanel.java | 173 ++++++++++++++---- 1 file changed, 138 insertions(+), 35 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java index 936716fc78..ebbe9c79e1 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java @@ -49,6 +49,10 @@ import javax.swing.JPanel; import org.controlsfx.control.MaskerPane; import org.openide.util.NbBundle; import org.python.google.common.collect.Lists; +import javafx.scene.Group; +import javafx.scene.input.MouseEvent; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.datamodel.FileNode; @@ -70,18 +74,20 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan private final boolean fxInited; private JFXPanel fxPanel; + private Group imageGroup = new Group(); + private ImageTaggingTool tagger; private ImageView fxImageView; private ScrollPane scrollPane; private final ProgressBar progressBar = new ProgressBar(); private final MaskerPane maskerPane = new MaskerPane(); - + private double zoomRatio; private double rotation; // Can be 0, 90, 180, and 270. - + private static final double[] ZOOM_STEPS = { 0.0625, 0.125, 0.25, 0.375, 0.5, 0.75, 1, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10}; - + private static final double MIN_ZOOM_RATIO = 0.0625; // 6.25% private static final double MAX_ZOOM_RATIO = 10.0; // 1000% @@ -115,11 +121,12 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan // build jfx ui (we could do this in FXML?) fxImageView = new ImageView(); // will hold image - scrollPane = new ScrollPane(fxImageView); // scrolls and sizes imageview + imageGroup.getChildren().add(fxImageView); + scrollPane = new ScrollPane(imageGroup); // scrolls and sizes imageview scrollPane.getStyleClass().add("bg"); //NOI18N scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED); scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED); - + fxPanel = new JFXPanel(); // bridge jfx-swing Scene scene = new Scene(scrollPane); //root of jfx tree scene.getStylesheets().add(MediaViewImagePanel.class.getResource("MediaViewImagePanel.css").toExternalForm()); //NOI18N @@ -146,9 +153,10 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan Platform.runLater(() -> { fxImageView.setViewport(new Rectangle2D(0, 0, 0, 0)); fxImageView.setImage(null); - + tagger.defaultSettings(); + scrollPane.setContent(null); - scrollPane.setContent(fxImageView); + scrollPane.setContent(imageGroup); }); } @@ -160,7 +168,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan * TODO: why is the name passed into the action constructor? it * means we duplicate this string all over the place -jm */ new ExternalViewerAction(Bundle.MediaViewImagePanel_externalViewerButton_text(), new FileNode(file)) - .actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "")) //Swing ActionEvent + .actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "")) //Swing ActionEvent ); final VBox errorNode = new VBox(10, new Label(errorMessage), externalViewerButton); @@ -199,8 +207,11 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan if (nonNull(fxImage)) { // We have a non-null image, so let's show it. fxImageView.setImage(fxImage); + imageGroup.getChildren().remove(tagger); + tagger = new ImageTaggingTool(fxImageView, Color.IVORY); + imageGroup.getChildren().add(tagger); resetView(); - scrollPane.setContent(fxImageView); + scrollPane.setContent(imageGroup); } else { showErrorNode(Bundle.MediaViewImagePanel_errorLabel_text(), file); } @@ -410,7 +421,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan private void zoomInButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomInButtonActionPerformed // Find the next zoom step. - for (int i=0; i < ZOOM_STEPS.length; i++) { + for (int i = 0; i < ZOOM_STEPS.length; i++) { if (zoomRatio < ZOOM_STEPS[i]) { zoomRatio = ZOOM_STEPS[i]; break; @@ -421,7 +432,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan private void zoomOutButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomOutButtonActionPerformed // Find the next zoom step. - for (int i=ZOOM_STEPS.length-1; i >= 0; i--) { + for (int i = ZOOM_STEPS.length - 1; i >= 0; i--) { if (zoomRatio > ZOOM_STEPS[i]) { zoomRatio = ZOOM_STEPS[i]; break; @@ -450,12 +461,12 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan private javax.swing.JButton zoomResetButton; private javax.swing.JTextField zoomTextField; // End of variables declaration//GEN-END:variables - + /** * Reset the zoom and rotation values to their defaults. The zoom level gets * defaulted to the current size of the panel. The rotation will be set to * zero. - * + * * Note: This method will make a call to 'updateView()' after the values * have been reset. */ @@ -464,28 +475,28 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan if (image == null) { return; } - + double imageWidth = image.getWidth(); double imageHeight = image.getHeight(); double scrollPaneWidth = fxPanel.getWidth(); double scrollPaneHeight = fxPanel.getHeight(); double zoomRatioWidth = scrollPaneWidth / imageWidth; double zoomRatioHeight = scrollPaneHeight / imageHeight; - + // Use the smallest ratio size to fit the entire image in the view area. zoomRatio = zoomRatioWidth < zoomRatioHeight ? zoomRatioWidth : zoomRatioHeight; - + rotation = 0; - + scrollPane.setHvalue(0); scrollPane.setVvalue(0); - + updateView(); } - + /** * Update the image to use the current zoom and rotation values. - * + * * Note: For zoom levels less than 100%, special accomodations are made in * order to keep the image fully visible. This is because the viewport size * change occurs before any transforms execute, thus chopping off part of @@ -498,39 +509,39 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan if (image == null) { return; } - + // Image dimensions double imageWidth = image.getWidth(); double imageHeight = image.getHeight(); - + // Image dimensions with zooming applied double adjustedImageWidth = imageWidth * zoomRatio; double adjustedImageHeight = imageHeight * zoomRatio; - + // ImageView viewport dimensions double viewportWidth; double viewportHeight; - + // Panel dimensions double panelWidth = fxPanel.getWidth(); double panelHeight = fxPanel.getHeight(); - + // Coordinates to center the image on the panel double centerOffsetX = (panelWidth / 2) - (imageWidth / 2); double centerOffsetY = (panelHeight / 2) - (imageHeight / 2); - + // Coordinates to keep the image inside the left/top boundaries double leftOffsetX; double topOffsetY; - + // Scroll bar positions double scrollX = scrollPane.getHvalue(); double scrollY = scrollPane.getVvalue(); - + // Scroll bar position boundaries (work-around for viewport size bug) double maxScrollX; double maxScrollY; - + // Set viewport size and translation offsets. if ((rotation % 180) == 0) { // Rotation is 0 or 180. @@ -549,7 +560,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan maxScrollX = (adjustedImageHeight - panelWidth) / (imageWidth - panelWidth); maxScrollY = (adjustedImageWidth - panelHeight) / (imageHeight - panelHeight); } - + // Work around bug that truncates image if dimensions are too small. if (viewportWidth < imageWidth) { viewportWidth = imageWidth; @@ -563,7 +574,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan scrollY = maxScrollY; } } - + // Update the viewport size. fxImageView.setViewport(new Rectangle2D( 0, 0, viewportWidth, viewportHeight)); @@ -589,9 +600,9 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan // Add the transforms in reverse order of intended execution. // Note: They MUST be added in this order to ensure translate is // executed last. - fxImageView.getTransforms().clear(); - fxImageView.getTransforms().addAll(translate, rotate, scale); - + imageGroup.getTransforms().clear(); + imageGroup.getTransforms().addAll(translate, rotate, scale); + // Adjust scroll bar positions for view changes. if (viewportWidth > fxPanel.getWidth()) { scrollPane.setHvalue(scrollX); @@ -599,11 +610,103 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan if (viewportHeight > fxPanel.getHeight()) { scrollPane.setVvalue(scrollY); } - + // Update all image controls to reflect the current values. zoomOutButton.setEnabled(zoomRatio > MIN_ZOOM_RATIO); zoomInButton.setEnabled(zoomRatio < MAX_ZOOM_RATIO); rotationTextField.setText((int) rotation + "°"); zoomTextField.setText((Math.round(zoomRatio * 100.0)) + "%"); } + + /** + * Enables users to 'tag' a region of an image by clicking and dragging a + * rectangle overtop. + */ + class ImageTaggingTool extends Rectangle { + + private final double imageWidth; + private final double imageHeight; + private final double imageOriginX; + private final double imageOriginY; + + //Origin of the drag event. + private double rectangleOriginX; + private double rectangleOriginY; + + /** + * Adds tagging support to an image, where the 'tag' rectangle will be + * the specified color. + * + * @param image Image to tag + * @param color Color of the 'tag' rectangle + */ + private ImageTaggingTool(ImageView image, Color color) { + defaultSettings(); + + imageWidth = image.getImage().getWidth(); + imageHeight = image.getImage().getHeight(); + imageOriginX = image.getX(); + imageOriginY = image.getY(); + + setStroke(color); + setFill(color.deriveColor(0.5, 0, 1, 0.2)); + //Set the stroke width to the min of the height and width, so that + //border of the rectangle is visible on skinny images. + setStrokeWidth(Math.min(imageWidth, imageHeight) / 200.0); + setVisible(false); + + //Create a rectangle by left clicking on the image + image.setOnMousePressed((MouseEvent event) -> { + if (event.isSecondaryButtonDown()) { + return; + } + + //Reset box on new click. + defaultSettings(); + + rectangleOriginX = event.getX(); + rectangleOriginY = event.getY(); + + setX(rectangleOriginX); + setY(rectangleOriginY); + }); + + //Adjust the rectangle by dragging the left mouse button + image.setOnMouseDragged((MouseEvent event) -> { + if (event.isSecondaryButtonDown()) { + return; + } + + /** + * Ensure the rectangle is contained within image boundaries + */ + double newX = Math.min(Math.max(event.getX(), imageOriginX), imageWidth); + double newY = Math.min(Math.max(event.getY(), imageOriginY), imageHeight); + + setVisible(true); + double offsetX = newX - rectangleOriginX; + if (offsetX < 0) { + setX(newX); + } + setWidth(Math.abs(offsetX)); + + double offsetY = newY - rectangleOriginY; + if (offsetY < 0) { + setY(newY); + } + setHeight(Math.abs(offsetY)); + }); + } + + /** + * Reset the rectangle to default dimensions. + */ + public final void defaultSettings() { + setX(0); + setY(0); + setWidth(0); + setHeight(0); + setVisible(false); + } + } } From 9b6e0b7086d9aa3b6e71e963d813170776c060a5 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 2 May 2019 14:52:40 -0400 Subject: [PATCH 31/78] Move group declaration to inside constructor --- .../sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java index ebbe9c79e1..40d6b6d833 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java @@ -74,7 +74,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan private final boolean fxInited; private JFXPanel fxPanel; - private Group imageGroup = new Group(); + private Group imageGroup; private ImageTaggingTool tagger; private ImageView fxImageView; private ScrollPane scrollPane; @@ -121,6 +121,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan // build jfx ui (we could do this in FXML?) fxImageView = new ImageView(); // will hold image + imageGroup = new Group(); imageGroup.getChildren().add(fxImageView); scrollPane = new ScrollPane(imageGroup); // scrolls and sizes imageview scrollPane.getStyleClass().add("bg"); //NOI18N From 2c90521a1c5caf90ac8c8f25f07467be20cbf307 Mon Sep 17 00:00:00 2001 From: Joe Ho Date: Fri, 3 May 2019 11:11:28 -0400 Subject: [PATCH 32/78] Debugging code LogicalImagerDSProcessor class not found --- .../AddImageWizardSelectDspVisual.java | 5 +- .../autopsy/casemodule/Bundle_ja.properties | 4 + .../org/sleuthkit/autopsy/casemodule/Foo.java | 24 + .../autopsy/casemodule/ImageFilePanel.form | 2 +- .../casemodule/LogicalImagerDSProcessor.java | 172 ++++++ .../casemodule/LogicalImagerPanel.form | 269 +++++++++ .../casemodule/LogicalImagerPanel.java | 539 ++++++++++++++++++ .../keywordsearch/Bundle.properties-MERGED | 2 +- .../recentactivity/Bundle.properties-MERGED | 2 +- 9 files changed, 1015 insertions(+), 4 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/Foo.java create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java index 23d25aab2e..e8630b1a5d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java @@ -181,7 +181,7 @@ final class AddImageWizardSelectDspVisual extends JPanel { /** * Create a list of the DataSourceProcessors which should exist as options * on this panel. The default Autopsy DataSourceProcessors will appear at - * the beggining of the list in the same order. + * the beginning of the list in the same order. * * @return dspList a list of DataSourceProcessors which can be chose in this * panel @@ -200,6 +200,9 @@ final class AddImageWizardSelectDspVisual extends JPanel { dspList.add(LocalDiskDSProcessor.getType()); dspList.add(LocalFilesDSProcessor.getType()); dspList.add(RawDSProcessor.getType()); + Foo foo = new Foo(); + dspList.add(foo.bar()); + dspList.add(LogicalImagerDSProcessor.getType()); // now add any addtional DSPs that haven't already been added for (String dspType : datasourceProcessorsMap.keySet()) { if (!dspList.contains(dspType)) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties index 2b05d5cac8..d84c7fd96a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties @@ -196,3 +196,7 @@ CaseDetailsPanel.lbDbName.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\uff1a CaseDetailsPanel.lbDbType.text=\u30b1\u30fc\u30b9\u30bf\u30a4\u30d7\uff1a CaseDetailsPanel.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a OpenMultiUserCasePanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +LogicalImagerPanel.sectorSizeLabel.text=\u30a4\u30f3\u30d7\u30c3\u30c8\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a +LogicalImagerPanel.errorLabel.text=\u30a8\u30e9\u30fc\u30e9\u30d9\u30eb +LogicalImagerPanel.noFatOrphansCheckbox.text=FAT\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306e\u30aa\u30fc\u30d5\u30a1\u30f3\u30d5\u30a1\u30a4\u30eb\u306f\u7121\u8996 +LogicalImagerPanel.browseButton.text=\u95b2\u89a7 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Foo.java b/Core/src/org/sleuthkit/autopsy/casemodule/Foo.java new file mode 100644 index 0000000000..066465e420 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Foo.java @@ -0,0 +1,24 @@ +/* + * 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.casemodule; + +/** + * + * @author jkho + */ +public class Foo { + + public Foo() { + } + + public String bar() { + return "bar"; + } + + public static String getFoo() { + return "foo"; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form index 2274ccb9a7..0c634afc24 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form @@ -116,7 +116,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java new file mode 100644 index 0000000000..60e480c2bb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerDSProcessor.java @@ -0,0 +1,172 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2019 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.casemodule; + +import java.io.File; +import java.util.List; +import javax.swing.JPanel; +import javax.swing.filechooser.FileFilter; +import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; + +/** + * A LogicalImager data source processor that implements the DataSourceProcessor service + * provider interface to allow integration with the add data source wizard. It + * also provides a run method overload to allow it to be used independently of + * the wizard. + */ +@ServiceProvider(service = DataSourceProcessor.class) +public class LogicalImagerDSProcessor implements DataSourceProcessor { + + private final LogicalImagerPanel configPanel; + private final static String DATA_SOURCE_TYPE = NbBundle.getMessage(LogicalImagerDSProcessor.class, "LogicalImagerDSProcessor.dsType.text"); + + /* + * Constructs a Logical Imaager data source processor that implements the + * DataSourceProcessor service provider interface to allow integration with + * the add data source wizard. It also provides a run method overload to + * allow it to be used independently of the wizard. + */ + public LogicalImagerDSProcessor() { + configPanel = LogicalImagerPanel.createInstance(LogicalImagerDSProcessor.class.getName()); + } + + /** + * Gets a string that describes the type of data sources this processor is + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). + * + * @return A data source type display string for this data source processor. + */ + public static String getType() { + return DATA_SOURCE_TYPE; + } + + /** + * Gets a string that describes the type of data sources this processor is + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). + * + * @return A data source type display string for this data source processor. + */ + @Override + public String getDataSourceType() { + return getType(); + } + + /** + * Gets the panel that allows a user to select a data source and do any + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. + * + * @return A selection and configuration panel for this data source + * processor. + */ + @Override + public JPanel getPanel() { + configPanel.readSettings(); + configPanel.select(); + return configPanel; + } + + /** + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. + * + * @return True if the settings are valid and complete and the processor is + * ready to have its run method called, false otherwise. + */ + @Override + public boolean isPanelValid() { + return configPanel.validatePanel(); + } + + /** + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. + * + * This method should not be called unless isPanelValid returns true. + * + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. + */ + @Override + public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { + configPanel.storeSettings(); + // TODO + } + + /** + * Adds a "LogicalImager" data source to the case database using a background task in + * a separate thread and the given settings instead of those provided by the + * selection and configuration panel. Returns as soon as the background task + * is started and uses the callback object to signal task completion and + * return results. + * + * @param deviceId An ASCII-printable identifier for the device + * associated with the data source that is + * intended to be unique across multiple cases + * (e.g., a UUID). + * @param imageFilePath Path to the image file. + * @param timeZone The time zone to use when processing dates + * and times for the image, obtained from + * java.util.TimeZone.getID. + * @param chunkSize The maximum size of each chunk of the raw + * data source as it is divided up into virtual + * unallocated space files. + * @param progressMonitor Progress monitor for reporting progress + * during processing. + * @param callback Callback to call when processing is done. + */ + private void run(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { +// AddRawImageTask addImageTask = new AddRawImageTask(deviceId, imageFilePath, timeZone, chunkSize, progressMonitor, callback); +// new Thread(addImageTask).start(); +// TODO: 5011 Logical Imager DSP adds data + } + + @Override + public void cancel() { + } + + /** + * Resets the selection and configuration panel for this data source + * processor. + */ + @Override + public void reset() { + configPanel.reset(); + } + + private static boolean isAcceptedByFiler(File file, List filters) { + for (FileFilter filter : filters) { + if (filter.accept(file)) { + return true; + } + } + return false; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form new file mode 100644 index 0000000000..9077c1722c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.form @@ -0,0 +1,269 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java new file mode 100644 index 0000000000..d8a0e955ec --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalImagerPanel.java @@ -0,0 +1,539 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-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.casemodule; + +import java.io.File; +import java.util.Calendar; +import java.util.List; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.filechooser.FileFilter; +import org.apache.commons.lang3.StringUtils; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; +import org.sleuthkit.autopsy.coreutils.DriveUtils; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.coreutils.PathValidator; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; +import org.sleuthkit.datamodel.HashUtility; + +/** + * Panel for adding an image file such as .img, .E0x, .00x, etc. Allows the user + * to select a file as well as choose the timezone and whether to ignore orphan + * files in FAT32. + */ +@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives +public class LogicalImagerPanel extends JPanel implements DocumentListener { + + private static final long serialVersionUID = 1L; + private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS + private static final String[] SECTOR_SIZE_CHOICES = {"Auto Detect", "512", "1024", "2048", "4096"}; + private final JFileChooser fileChooser = new JFileChooser(); + private final String contextName; + + /** + * Creates new form LogicalImagerPanel + * + * @param context A string context name used to read/store last + * used settings. + */ + private LogicalImagerPanel(String context) { + this.contextName = context; + initComponents(); + + // Populate the drop down list of time zones + createTimeZoneList(); + + // Populate the drop down list of sector size options + for (String choice : SECTOR_SIZE_CHOICES) { + sectorSizeComboBox.addItem(choice); + } + sectorSizeComboBox.setSelectedIndex(0); + + errorLabel.setVisible(false); + + fileChooser.setDragEnabled(false); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setMultiSelectionEnabled(false); + } + + /** + * Creates the drop down list for the time zones and defaults the selection + * to the local machine time zone. + */ + private void createTimeZoneList() { + List timeZoneList = TimeZoneUtils.createTimeZoneList(); + for (String timeZone : timeZoneList) { + timeZoneComboBox.addItem(timeZone); + } + + // set the selected timezone + timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone())); + } + + /** + * Creates and returns an instance of a LogicalImagerPanel. + * + * @param context A string context name used to read/store last + * used settings. + * @param fileChooserFilters A list of filters to be used with the + * FileChooser. + * + * @return instance of the LogicalImagerPanel + */ + public static synchronized LogicalImagerPanel createInstance(String context) { + LogicalImagerPanel instance = new LogicalImagerPanel(context); + // post-constructor initialization of listener support without leaking references of uninitialized objects + instance.getPathTextField().getDocument().addDocumentListener(instance); + instance.getMd5TextFieldField().getDocument().addDocumentListener(instance); + instance.getSha1TextField().getDocument().addDocumentListener(instance); + instance.getSha256TextField().getDocument().addDocumentListener(instance); + return instance; + } + + private JTextField getPathTextField() { + return pathTextField; + } + + private JTextField getMd5TextFieldField() { + return md5HashTextField; + } + + private JTextField getSha1TextField() { + return sha1HashTextField; + } + + private JTextField getSha256TextField() { + return sha256HashTextField; + } + + /** + * 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + pathLabel = new javax.swing.JLabel(); + browseButton = new javax.swing.JButton(); + pathTextField = new javax.swing.JTextField(); + timeZoneLabel = new javax.swing.JLabel(); + timeZoneComboBox = new javax.swing.JComboBox<>(); + noFatOrphansCheckbox = new javax.swing.JCheckBox(); + errorLabel = new javax.swing.JLabel(); + sectorSizeLabel = new javax.swing.JLabel(); + sectorSizeComboBox = new javax.swing.JComboBox<>(); + sha256HashLabel = new javax.swing.JLabel(); + sha256HashTextField = new javax.swing.JTextField(); + sha1HashTextField = new javax.swing.JTextField(); + md5HashTextField = new javax.swing.JTextField(); + sha1HashLabel = new javax.swing.JLabel(); + md5HashLabel = new javax.swing.JLabel(); + hashValuesLabel = new javax.swing.JLabel(); + hashValuesNoteLabel = new javax.swing.JLabel(); + + setMinimumSize(new java.awt.Dimension(0, 65)); + setPreferredSize(new java.awt.Dimension(403, 65)); + + org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.pathLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.browseButton.text")); // NOI18N + browseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseButtonActionPerformed(evt); + } + }); + + pathTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.pathTextField.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.timeZoneLabel.text")); // NOI18N + + timeZoneComboBox.setMaximumRowCount(30); + + org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.noFatOrphansCheckbox.text")); // NOI18N + noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.noFatOrphansCheckbox.toolTipText")); // NOI18N + + errorLabel.setForeground(new java.awt.Color(255, 0, 0)); + org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.errorLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(sectorSizeLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sectorSizeLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(sha256HashLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha256HashLabel.text")); // NOI18N + sha256HashLabel.setEnabled(false); + + sha256HashTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha256HashTextField.text")); // NOI18N + sha256HashTextField.setEnabled(false); + + sha1HashTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha1HashTextField.text")); // NOI18N + sha1HashTextField.setEnabled(false); + + md5HashTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.md5HashTextField.text")); // NOI18N + md5HashTextField.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(sha1HashLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.sha1HashLabel.text")); // NOI18N + sha1HashLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(md5HashLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.md5HashLabel.text")); // NOI18N + md5HashLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(hashValuesLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.hashValuesLabel.text")); // NOI18N + hashValuesLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(hashValuesNoteLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.hashValuesNoteLabel.text")); // NOI18N + hashValuesNoteLabel.setEnabled(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() + .addComponent(pathTextField) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(browseButton) + .addGap(2, 2, 2)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pathLabel) + .addComponent(noFatOrphansCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 262, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 368, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(errorLabel) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(layout.createSequentialGroup() + .addComponent(timeZoneLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(sectorSizeLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(md5HashLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(sha1HashLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(sha256HashLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(hashValuesNoteLabel) + .addComponent(hashValuesLabel)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(pathLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(browseButton) + .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(noFatOrphansCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(timeZoneLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(sectorSizeLabel)) + .addGap(39, 39, 39) + .addComponent(hashValuesLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(md5HashLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(sha1HashLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(sha256HashLabel)) + .addGap(18, 18, 18) + .addComponent(hashValuesNoteLabel) + .addGap(18, 18, 18) + .addComponent(errorLabel) + .addContainerGap(51, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + @NbBundle.Messages({"LogicalImagerPanel.000.confirmationMessage=The selected file" + + " has extenson .001 but there is a .000 file in the sequence of raw images." + + "\nShould the .000 file be used as the start, instead of the selected .001 file?\n"}) + private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + String oldText = getContentPaths(); + // set the current directory of the FileChooser if the ImagePath Field is valid + File currentDir = new File(oldText); + if (currentDir.exists()) { + fileChooser.setCurrentDirectory(currentDir); + } + + if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + String path = fileChooser.getSelectedFile().getPath(); + if (path.endsWith(".001")) { + String zeroX3_path = StringUtils.removeEnd(path, ".001") + ".000"; + if (new File(zeroX3_path).exists()) { + int showConfirmDialog = JOptionPane.showConfirmDialog(this, + Bundle.LogicalImagerPanel_000_confirmationMessage(), + "Choose .001 file?", JOptionPane.YES_NO_OPTION); + if (showConfirmDialog == JOptionPane.YES_OPTION) { + path = zeroX3_path; + } + } + } + + setContentPath(path); + + /** + * Automatically clear out the hash values if a new image was + * selected. + */ + if (!oldText.equals(getContentPaths())) { + md5HashTextField.setText(null); + sha1HashTextField.setText(null); + sha256HashTextField.setText(null); + } + } + + updateHelper(); + }//GEN-LAST:event_browseButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton browseButton; + private javax.swing.JLabel errorLabel; + private javax.swing.JLabel hashValuesLabel; + private javax.swing.JLabel hashValuesNoteLabel; + private javax.swing.JLabel md5HashLabel; + private javax.swing.JTextField md5HashTextField; + private javax.swing.JCheckBox noFatOrphansCheckbox; + private javax.swing.JLabel pathLabel; + private javax.swing.JTextField pathTextField; + private javax.swing.JComboBox sectorSizeComboBox; + private javax.swing.JLabel sectorSizeLabel; + private javax.swing.JLabel sha1HashLabel; + private javax.swing.JTextField sha1HashTextField; + private javax.swing.JLabel sha256HashLabel; + private javax.swing.JTextField sha256HashTextField; + private javax.swing.JComboBox timeZoneComboBox; + private javax.swing.JLabel timeZoneLabel; + // End of variables declaration//GEN-END:variables + + /** + * Enable or disable all of the hash values components. + * + * @param enabled Enable components if true; otherwise disable. + */ + private void setHashValuesComponentsEnabled(boolean enabled) { + hashValuesLabel.setEnabled(enabled); + hashValuesNoteLabel.setEnabled(enabled); + + md5HashLabel.setEnabled(enabled); + md5HashTextField.setEnabled(enabled); + + sha1HashLabel.setEnabled(enabled); + sha1HashTextField.setEnabled(enabled); + + sha256HashLabel.setEnabled(enabled); + sha256HashTextField.setEnabled(enabled); + } + + /** + * Get the path of the user selected image. + * + * @return the image path + */ + public String getContentPaths() { + return pathTextField.getText(); + } + + /** + * Set the path of the image file. + * + * @param s path of the image file + */ + public void setContentPath(String s) { + pathTextField.setText(s); + } + + /** + * Get the sector size. + * + * @return 0 if autodetect; otherwise the value selected. + */ + public int getSectorSize() { + int sectorSizeSelectionIndex = sectorSizeComboBox.getSelectedIndex(); + + if (sectorSizeSelectionIndex == 0) { + return 0; + } + + return Integer.valueOf((String) sectorSizeComboBox.getSelectedItem()); + } + + public String getTimeZone() { + String tz = timeZoneComboBox.getSelectedItem().toString(); + return tz.substring(tz.indexOf(')') + 2).trim(); + } + + public boolean getNoFatOrphans() { + return noFatOrphansCheckbox.isSelected(); + } + + String getMd5() { + return this.md5HashTextField.getText(); + } + + String getSha1() { + return this.sha1HashTextField.getText(); + } + + String getSha256() { + return this.sha256HashTextField.getText(); + } + + public void reset() { + //reset the UI elements to default + pathTextField.setText(null); + this.md5HashTextField.setText(null); + this.sha1HashTextField.setText(null); + this.sha256HashTextField.setText(null); + } + + /** + * Should we enable the next button of the wizard? + * + * @return true if a proper image has been selected, false otherwise + */ + @NbBundle.Messages({ + "LogicalImagerPanel.validatePanel.dataSourceOnCDriveError=Warning: Path to multi-user data source is on \"C:\" drive", + "LogicalImagerPanel.validatePanel.invalidMD5=Invalid MD5 hash", + "LogicalImagerPanel.validatePanel.invalidSHA1=Invalid SHA1 hash", + "LogicalImagerPanel.validatePanel.invalidSHA256=Invalid SHA256 hash",}) + public boolean validatePanel() { + errorLabel.setVisible(false); + + String path = getContentPaths(); + if (!isImagePathValid()) { + return false; + } + + if (!StringUtils.isBlank(getMd5()) && !HashUtility.isValidMd5Hash(getMd5())) { + errorLabel.setVisible(true); + errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_invalidMD5()); + return false; + } + + if (!StringUtils.isBlank(getSha1()) && !HashUtility.isValidSha1Hash(getSha1())) { + errorLabel.setVisible(true); + errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_invalidSHA1()); + return false; + } + + if (!StringUtils.isBlank(getSha256()) && !HashUtility.isValidSha256Hash(getSha256())) { + errorLabel.setVisible(true); + errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_invalidSHA256()); + return false; + } + + if (!PathValidator.isValidForMultiUserCase(path, Case.getCurrentCase().getCaseType())) { + errorLabel.setVisible(true); + errorLabel.setText(Bundle.LogicalImagerPanel_validatePanel_dataSourceOnCDriveError()); + } + + return true; + } + + private boolean isImagePathValid() { + String path = getContentPaths(); + + if (StringUtils.isBlank(path) || (!(new File(path).isFile() || DriveUtils.isPhysicalDrive(path) || DriveUtils.isPartition(path)))) { + return false; + } + + return true; + } + + public void storeSettings() { + String imagePathName = getContentPaths(); + if (null != imagePathName) { + String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1); + ModuleSettings.setConfigSetting(contextName, PROP_LASTIMAGE_PATH, imagePath); + } + } + + public void readSettings() { + String lastImagePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTIMAGE_PATH); + if (StringUtils.isNotBlank(lastImagePath)) { + setContentPath(lastImagePath); + } + } + + @Override + public void insertUpdate(DocumentEvent e) { + updateHelper(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + updateHelper(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + updateHelper(); + } + + /** + * Update functions are called by the pathTextField which has this set as + * it's DocumentEventListener. Each update function fires a property change + * to be caught by the parent panel. Additionally, the hash values will be + * enabled or disabled depending on the pathTextField input. + */ + @NbBundle.Messages({"LogicalImagerPanel.moduleErr=Module Error", + "LogicalImagerPanel.moduleErr.msg=A module caused an error listening to LogicalImagerPanel updates." + + " See log to determine which module. Some data could be incomplete.\n"}) + private void updateHelper() { + if (isImagePathValid() && !getContentPaths().toLowerCase().endsWith(".e01")) { + setHashValuesComponentsEnabled(true); + } else { + setHashValuesComponentsEnabled(false); + } + + firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); + } + + /** + * Set the focus to the pathTextField. + */ + public void select() { + pathTextField.requestFocusInWindow(); + } +} 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 From e2a2c69a14643666c1f6dfbb96a5bf86b77c7929 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Fri, 3 May 2019 15:34:39 -0400 Subject: [PATCH 33/78] Visual changes per request --- .../contentviewers/MediaViewImagePanel.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java index 40d6b6d833..c48ab8c796 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java @@ -26,6 +26,10 @@ import static java.util.Objects.nonNull; import java.util.SortedSet; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; +import javafx.animation.Interpolator; +import javafx.animation.KeyFrame; +import javafx.animation.KeyValue; +import javafx.animation.Timeline; import javafx.application.Platform; import javafx.concurrent.Task; import javafx.embed.swing.JFXPanel; @@ -53,6 +57,7 @@ import javafx.scene.Group; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; +import javafx.util.Duration; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.datamodel.FileNode; @@ -209,7 +214,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan // We have a non-null image, so let's show it. fxImageView.setImage(fxImage); imageGroup.getChildren().remove(tagger); - tagger = new ImageTaggingTool(fxImageView, Color.IVORY); + tagger = new ImageTaggingTool(fxImageView, Color.RED); imageGroup.getChildren().add(tagger); resetView(); scrollPane.setContent(imageGroup); @@ -634,6 +639,11 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan private double rectangleOriginX; private double rectangleOriginY; + //Rectangle lines should be 1.5% of the image. This level of thickness has + //a good balance between visual acuity and loss of selection at the borders + //of the image. + private double lineThicknessAsPercent = 1.5; + /** * Adds tagging support to an image, where the 'tag' rectangle will be * the specified color. @@ -650,10 +660,13 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan imageOriginY = image.getY(); setStroke(color); - setFill(color.deriveColor(0.5, 0, 1, 0.2)); - //Set the stroke width to the min of the height and width, so that - //border of the rectangle is visible on skinny images. - setStrokeWidth(Math.min(imageWidth, imageHeight) / 200.0); + setFill(color.deriveColor(0, 0, 0, 0)); + + //Calculate how many pixels the stroke width should be to guarentee + //a consistent % of image consumed by the rectangle border. + double min = Math.min(imageWidth, imageHeight); + double lineThicknessPixels = min * lineThicknessAsPercent / 100.0; + setStrokeWidth(lineThicknessPixels); setVisible(false); //Create a rectangle by left clicking on the image @@ -679,10 +692,13 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan } /** - * Ensure the rectangle is contained within image boundaries + * Ensure the rectangle is contained within image boundaries and + * that the line thickness is kept within bounds. */ - double newX = Math.min(Math.max(event.getX(), imageOriginX), imageWidth); - double newY = Math.min(Math.max(event.getY(), imageOriginY), imageHeight); + double newX = Math.min(Math.max(event.getX(), imageOriginX) + + lineThicknessPixels / 2, imageWidth - lineThicknessPixels / 2); + double newY = Math.min(Math.max(event.getY(), imageOriginY) + + lineThicknessPixels / 2, imageHeight - lineThicknessPixels / 2); setVisible(true); double offsetX = newX - rectangleOriginX; From ca9121dbd385263b8d317f40f130b7cd62fd14bf Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Fri, 3 May 2019 15:36:06 -0400 Subject: [PATCH 34/78] Removed unused imports --- .../autopsy/contentviewers/MediaViewImagePanel.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java index c48ab8c796..5c16dbed93 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java @@ -26,10 +26,6 @@ import static java.util.Objects.nonNull; import java.util.SortedSet; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -import javafx.animation.Interpolator; -import javafx.animation.KeyFrame; -import javafx.animation.KeyValue; -import javafx.animation.Timeline; import javafx.application.Platform; import javafx.concurrent.Task; import javafx.embed.swing.JFXPanel; @@ -57,7 +53,6 @@ import javafx.scene.Group; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; -import javafx.util.Duration; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.datamodel.FileNode; From b5fa09b5f6e0d75307bc9973d0aae2bd72aaae63 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 6 May 2019 10:07:31 -0400 Subject: [PATCH 35/78] new account summary panel for communications window. --- .../AccountSourceContentChildNodeFactory.java | 96 ++++++ .../autopsy/communications/Bundle.properties | 14 + .../communications/Bundle.properties-MERGED | 18 + .../CorrelationCaseChildNodeFactory.java | 169 ++++++++++ .../communications/OutlineViewPanel.form | 60 ++++ .../communications/OutlineViewPanel.java | 132 ++++++++ .../communications/RelationshipBrowser.java | 4 +- .../autopsy/communications/SelectionInfo.java | 123 +++++++ .../autopsy/communications/SummaryViewer.form | 215 ++++++++++++ .../autopsy/communications/SummaryViewer.java | 312 ++++++++++++++++++ 10 files changed, 1142 insertions(+), 1 deletion(-) create mode 100755 Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java new file mode 100755 index 0000000000..f7a5065476 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java @@ -0,0 +1,96 @@ +/* + * 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.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.openide.util.Exceptions; +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 { + + private static final Logger logger = Logger.getLogger(AccountSourceContentChildNodeFactory.class.getName()); + + private final Set accounts; + + AccountSourceContentChildNodeFactory(Set accounts) { + this.accounts = accounts; + } + + @Override + protected boolean createKeys(List 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 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"); + } + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index 0463c566e0..8430265e2e 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -46,3 +46,17 @@ VisualizationPanel.forwardButton.toolTipText=Click to go forward VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart VisualizationPanel.forwardButton.text= +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=Case References +OutlineViewPanel.messageLabel.text= +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: diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index 843370320d..9cd3694ba0 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -51,6 +51,10 @@ PinAccountsAction.singularText=Add Selected Account to Visualization refreshText=Refresh Results ResetAndPinAccountsAction.pluralText=Visualize Only Selected Accounts ResetAndPinAccountsAction.singularText=Visualize Only Selected Account +SummaryViewer_CaseRefNameColumn_Title=Case Name +SummaryViewer_CentralRepository_Message= +SummaryViewer_FileRefNameColumn_Title=Path +SummaryViewer_TabTitle=Summary ThumbnailViewer_Name=Media UnpinAccountsAction.pluralText=Remove Selected Accounts UnpinAccountsAction.singularText=Remove Selected Account @@ -113,6 +117,20 @@ VisualizationPanel.forwardButton.toolTipText=Click to go forward VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart VisualizationPanel.forwardButton.text= +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=Case References +OutlineViewPanel.messageLabel.text= +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: VisualizationPanel_action_dialogs_title=Communications VisualizationPanel_action_name_text=Snapshot Report VisualizationPanel_module_name=Communications diff --git a/Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java new file mode 100755 index 0000000000..a539918078 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java @@ -0,0 +1,169 @@ +/* + * 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 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 { + + private static final Logger logger = Logger.getLogger(CorrelationCaseChildNodeFactory.class.getName()); + + private Map correlationTypeMap; + private final Set accounts; + + /** + * ChildFactory for CorrelationCases. + * + * @param accounts List of Account objects + */ + CorrelationCaseChildNodeFactory(Set accounts) { + this.accounts = accounts; + } + + @Override + protected boolean createKeys(List 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); + return false; + } + + Map uniqueCaseMap = new HashMap<>(); + + accounts.forEach((account) -> { + try { + CorrelationAttributeInstance.Type correlationType = getCorrelationType(account.getAccountType()); + if (correlationType != null) { + List 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); + } + }); + + 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 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"); + } + + @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", + correlationCase.getTitleCreationDate(), + correlationCase.getTitleCreationDate(), + correlationCase.getCreationDate())); + + return sheet; + } + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.form b/Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.form new file mode 100755 index 0000000000..584e1e221d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.form @@ -0,0 +1,60 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.java b/Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.java new file mode 100755 index 0000000000..183ebdc0d9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/OutlineViewPanel.java @@ -0,0 +1,132 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.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") + // //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"); + }// //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 + +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java index 432f5e1dd7..aaeafa7c3a 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/RelationshipBrowser.java @@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.communications; import java.awt.Component; import javax.swing.JPanel; import org.openide.util.Lookup; -import org.openide.util.lookup.ProxyLookup; /** * Displays the Relationship information for the currently selected accounts. @@ -34,6 +33,7 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { private final MessagesViewer messagesViewer; private final ContactsViewer contactsViewer; private final ThumbnailViewer thumbnailsViewer; + private final SummaryViewer summaryViewer; private final ModifiableProxyLookup proxyLookup; @@ -44,11 +44,13 @@ final class RelationshipBrowser extends JPanel implements Lookup.Provider { messagesViewer = new MessagesViewer(); contactsViewer = new ContactsViewer(); thumbnailsViewer = new ThumbnailViewer(); + summaryViewer = new SummaryViewer(); proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); initComponents(); + tabPane.add(summaryViewer.getDisplayName(), summaryViewer); tabPane.add(messagesViewer.getDisplayName(), messagesViewer); tabPane.add(contactsViewer.getDisplayName(), contactsViewer); tabPane.add(thumbnailsViewer.getDisplayName(), thumbnailsViewer); diff --git a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java index d1a28eb2d6..a67b442f51 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java +++ b/Core/src/org/sleuthkit/autopsy/communications/SelectionInfo.java @@ -18,18 +18,35 @@ */ package org.sleuthkit.autopsy.communications; +import java.util.HashSet; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.util.Exceptions; +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 accountDeviceInstances; private final CommunicationsFilter communicationFilter; + private final Set accounts; + + private Set accountArtifacts = null; + private SelectionSummary summary = null; /** * Wraps the details of the currently selected accounts. @@ -40,6 +57,11 @@ public final class SelectionInfo { SelectionInfo(Set accountDeviceInstances, CommunicationsFilter communicationFilter) { this.accountDeviceInstances = accountDeviceInstances; this.communicationFilter = communicationFilter; + + accounts = new HashSet<>(); + accountDeviceInstances.forEach((instance) -> { + accounts.add(instance.getAccount()); + }); } /** @@ -59,5 +81,106 @@ public final class SelectionInfo { public CommunicationsFilter getCommunicationsFilter() { return communicationFilter; } + + public Set getAccounts() { + return accounts; + } + + public Set 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 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; + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form new file mode 100755 index 0000000000..2859fff954 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form @@ -0,0 +1,215 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java new file mode 100755 index 0000000000..19e7f9eb75 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java @@ -0,0 +1,312 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.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.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=" + }) + + /** + * 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", "Creation Date"); + + 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 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") + // //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.OutlineViewPanel(); + caseReferencesPanel = new org.sleuthkit.autopsy.communications.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)) + ); + }// //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.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.OutlineViewPanel fileReferencesPanel; + private javax.swing.JLabel messagesDataLabel; + private javax.swing.JLabel messagesLabel; + // End of variables declaration//GEN-END:variables + +} From 83f6f1ff849412dfe756cba1678123f11fa7e431 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 6 May 2019 10:45:10 -0400 Subject: [PATCH 36/78] Removed not needed exceptions and changed a panel title. --- .../AccountSourceContentChildNodeFactory.java | 3 +-- .../sleuthkit/autopsy/communications/Bundle.properties | 2 +- .../autopsy/communications/Bundle.properties-MERGED | 3 ++- .../communications/CorrelationCaseChildNodeFactory.java | 8 ++++---- .../sleuthkit/autopsy/communications/SummaryViewer.form | 2 +- .../sleuthkit/autopsy/communications/SummaryViewer.java | 5 +++-- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java index f7a5065476..0b91987a0b 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AccountSourceContentChildNodeFactory.java @@ -12,7 +12,6 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; @@ -89,7 +88,7 @@ final class AccountSourceContentChildNodeFactory extends ChildFactory { setDisplayName(content.getName()); } - setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon.png"); + setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon.png"); //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index 8430265e2e..54c65bfc8e 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -51,7 +51,7 @@ 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=Case References +SummaryViewer.caseReferencesPanel.border.title=Other Occurrences OutlineViewPanel.messageLabel.text= SummaryViewer.messagesDataLabel.text=messages SummaryViewer.callLogsDataLabel.text=callLogs diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index 9cd3694ba0..8739aacaed 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -53,6 +53,7 @@ ResetAndPinAccountsAction.pluralText=Visualize Only Selected Accounts ResetAndPinAccountsAction.singularText=Visualize Only Selected Account SummaryViewer_CaseRefNameColumn_Title=Case Name SummaryViewer_CentralRepository_Message= +SummaryViewer_Creation_Date_Title=Creation Date SummaryViewer_FileRefNameColumn_Title=Path SummaryViewer_TabTitle=Summary ThumbnailViewer_Name=Media @@ -122,7 +123,7 @@ 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=Case References +SummaryViewer.caseReferencesPanel.border.title=Other Occurrences OutlineViewPanel.messageLabel.text= SummaryViewer.messagesDataLabel.text=messages SummaryViewer.callLogsDataLabel.text=callLogs diff --git a/Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java index a539918078..539bc0e028 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CorrelationCaseChildNodeFactory.java @@ -67,7 +67,7 @@ final class CorrelationCaseChildNodeFactory extends ChildFactory("creationDate", + sheetSet.put(new NodeProperty<>("creationDate", //NON-NLS correlationCase.getTitleCreationDate(), correlationCase.getTitleCreationDate(), correlationCase.getCreationDate())); diff --git a/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form index 2859fff954..c9c708d871 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.form @@ -201,7 +201,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java index 19e7f9eb75..659dd1aac4 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/SummaryViewer.java @@ -45,7 +45,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi "SummaryViewer_TabTitle=Summary", "SummaryViewer_FileRefNameColumn_Title=Path", "SummaryViewer_CaseRefNameColumn_Title=Case Name", - "SummaryViewer_CentralRepository_Message=" + "SummaryViewer_CentralRepository_Message=", + "SummaryViewer_Creation_Date_Title=Creation Date" }) /** @@ -63,7 +64,7 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi outlineView = caseReferencesPanel.getOutlineView(); outline = outlineView.getOutline(); - outlineView.setPropertyColumns("creationDate", "Creation Date"); + outlineView.setPropertyColumns("creationDate", Bundle.SummaryViewer_Creation_Date_Title()); //NON-NLS outline.setRootVisible(false); ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.SummaryViewer_CaseRefNameColumn_Title()); From 5988b31063d9d4aff0ce2b2588779fffbe8d474b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 6 May 2019 11:39:53 -0400 Subject: [PATCH 37/78] Initial layout of the new API --- .../textextractors/HtmlTextExtractor.java | 83 ++++++++++--------- .../autopsy/textextractors/TextExtractor.java | 13 ++- .../textextractors/TikaTextExtractor.java | 36 +++++++- .../autopsy/keywordsearch/Ingester.java | 6 +- .../KeywordSearchIngestModule.java | 7 ++ 5 files changed, 98 insertions(+), 47 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/HtmlTextExtractor.java b/Core/src/org/sleuthkit/autopsy/textextractors/HtmlTextExtractor.java index defcdc23a5..3caf7202c9 100644 --- a/Core/src/org/sleuthkit/autopsy/textextractors/HtmlTextExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/HtmlTextExtractor.java @@ -23,6 +23,8 @@ import java.io.Reader; import java.io.StringReader; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.TreeMap; import java.util.logging.Level; import net.htmlparser.jericho.Attributes; import net.htmlparser.jericho.Config; @@ -71,7 +73,7 @@ final class HtmlTextExtractor implements TextExtractor { /** * Determines if this content type is supported by this extractor. * - * @param content Content instance to be analyzed + * @param content Content instance to be analyzed * @param detectedFormat Mimetype of content instance * * @return flag indicating support @@ -83,23 +85,11 @@ final class HtmlTextExtractor implements TextExtractor { && file.getSize() <= MAX_SIZE; } - /** - * Returns a reader that will iterate over the text of an HTML document. - * - * @param content Html document source - * - * @return A reader instance containing the document source text - * - * @throws TextExtractorException - */ @Override - public Reader getReader() throws InitReaderException { - //TODO JIRA-4467, there is only harm in excluding HTML documents greater - //than 50MB due to our troubled approach of extraction. - ReadContentInputStream stream = new ReadContentInputStream(file); - - //Parse the stream with Jericho and put the results in a Reader + public Map getMetadata() { + Map metadataMap = new TreeMap<>(); try { + ReadContentInputStream stream = new ReadContentInputStream(file); StringBuilder scripts = new StringBuilder(); StringBuilder links = new StringBuilder(); StringBuilder images = new StringBuilder(); @@ -113,17 +103,8 @@ final class HtmlTextExtractor implements TextExtractor { Source source = new Source(stream); source.fullSequentialParse(); - Renderer renderer = source.getRenderer(); - renderer.setNewLine("\n"); - renderer.setIncludeHyperlinkURLs(false); - renderer.setDecorateFontStyles(false); - renderer.setIncludeAlternateText(false); - String text = renderer.toString(); - // Get all the tags in the source List tags = source.getAllStartTags(); - - StringBuilder stringBuilder = new StringBuilder(); for (StartTag tag : tags) { if (tag.getName().equals("script")) { //NON-NLS // If the