From 2c5e115d24083033c64b15edb4715a2b80711d9b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 3 Jul 2019 10:23:36 -0400 Subject: [PATCH 1/9] Added call log tab cvt and removed the code from the message tab for call logs --- .../BlackboardArtifactDateComparator.java | 101 ++++++++++++ .../relationships/Bundle.properties-MERGED | 2 + .../relationships/CallLogNode.java | 55 +++++++ .../relationships/CallLogViewer.form | 26 +++ .../relationships/CallLogViewer.java | 148 ++++++++++++++++++ .../CallLogsChildNodeFactory.java | 88 +++++++++++ .../relationships/MessageNode.java | 125 +++++---------- .../relationships/MessageViewer.java | 6 +- .../MessagesChildNodeFactory.java | 17 +- .../relationships/RelationshipBrowser.form | 1 + .../relationships/RelationshipBrowser.java | 3 + .../RelationshipsNodeUtilities.java | 53 +++++++ .../relationships/ThreadChildNodeFactory.java | 46 +----- 13 files changed, 523 insertions(+), 148 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.form create mode 100755 Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java create mode 100755 Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.java new file mode 100755 index 0000000000..cef2ddd3d9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.java @@ -0,0 +1,101 @@ +/* + * 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.relationships; + +import java.util.Comparator; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.TskCoreException; + + /** +* A comparator class for comparing BlackboardArtifacts of type +* TSK_EMAIL_MSG, TSK_MESSAGE, and TSK_CALLLOG by their respective creation +* date-time. +*/ +class BlackboardArtifactDateComparator implements Comparator { + static final int ACCENDING = 1; + static final int DECENDING = -1; + + private static final Logger logger = Logger.getLogger(BlackboardArtifactDateComparator.class.getName()); + + private final int direction; + + BlackboardArtifactDateComparator(int direction) { + this.direction = direction; + } + + @Override + public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) { + + BlackboardAttribute attribute1 = null; + BlackboardAttribute attribute2 = null; + // Inializing to Long.MAX_VALUE so that if a BlackboardArtifact of + // any unexpected type is passed in, it will bubble to the top of + // the list. + long dateTime1 = Long.MAX_VALUE; + long dateTime2 = Long.MAX_VALUE; + + if (bba1 != null) { + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID()); + if (fromID != null) { + try { + switch (fromID) { + case TSK_EMAIL_MSG: + attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT)); + break; + case TSK_MESSAGE: + attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME)); + break; + case TSK_CALLLOG: + attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START)); + break; + default: + attribute1 = null; + break; + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex); + } + } + } + + if (bba2 != null) { + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID()); + if (fromID != null) { + try { + switch (fromID) { + case TSK_EMAIL_MSG: + attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT)); + break; + case TSK_MESSAGE: + attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME)); + break; + case TSK_CALLLOG: + attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START)); + break; + default: + attribute2 = null; + break; + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex); + } + } + } + + if (attribute1 != null) { + dateTime1 = attribute1.getValueLong(); + } + + if (attribute2 != null) { + dateTime2 = attribute2.getValueLong(); + } + + return Long.compare(dateTime1, dateTime2) * direction; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED index f82411bf9d..9cfcae847e 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED @@ -1,3 +1,5 @@ +CallLogViewer_noCallLogs= +CallLogViewer_title=Call Logs ContactDetailsPane.nameLabel.text=Placeholder ContactNode_Email=Email Address ContactNode_Home_Number=Home Number diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java new file mode 100755 index 0000000000..787f6ed9d4 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java @@ -0,0 +1,55 @@ +/* + * 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.relationships; + +import org.openide.nodes.Sheet; +import static org.sleuthkit.autopsy.communications.relationships.RelationshipsNodeUtilities.getAttributeDisplayString; +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_CALLLOG; +import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO; + +/** + * + * + */ +public class CallLogNode extends BlackboardArtifactNode { + + CallLogNode(BlackboardArtifact artifact) { + super(artifact); + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); + if (sheetSet == null) { + sheetSet = Sheet.createPropertiesSet(); + sheet.put(sheetSet); + } + + final BlackboardArtifact artifact = getArtifact(); + + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); + if (null != fromID && fromID != TSK_CALLLOG) { + return sheet; + } + + sheetSet.put(createNode(TSK_PHONE_NUMBER_FROM, artifact)); + sheetSet.put(createNode(TSK_PHONE_NUMBER_TO, artifact)); + sheetSet.put(createNode(TSK_DATETIME_START, artifact)); + + return sheet; + } + + NodeProperty createNode(BlackboardAttribute.ATTRIBUTE_TYPE type, BlackboardArtifact artifact) { + return new NodeProperty<>(type.getLabel(), type.getDisplayName(), "", getAttributeDisplayString(artifact, type)); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.form new file mode 100755 index 0000000000..18ea7b177a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.form @@ -0,0 +1,26 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java new file mode 100755 index 0000000000..c421609fdc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java @@ -0,0 +1,148 @@ +/* + * 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.relationships; + +import javax.swing.JPanel; +import javax.swing.table.TableColumnModel; +import org.netbeans.swing.etable.ETableColumn; +import org.netbeans.swing.etable.ETableColumnModel; +import org.netbeans.swing.outline.DefaultOutlineModel; +import org.netbeans.swing.outline.Outline; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.NodeAdapter; +import org.openide.nodes.NodeMemberEvent; +import org.openide.util.Lookup; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.corecomponents.TableFilterNode; +import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; +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_DATETIME_START; + +/** + * + * + */ +final class CallLogViewer extends javax.swing.JPanel implements RelationshipsViewer { + + private final CallLogsChildNodeFactory nodeFactory; + + @Messages({ + "CallLogViewer_title=Call Logs", + "CallLogViewer_noCallLogs=" + }) + + /** + * Creates new form CallLogViewer + */ + public CallLogViewer() { + initComponents(); + + nodeFactory = new CallLogsChildNodeFactory(null); + outlineViewPanel.hideOutlineView(Bundle.CallLogViewer_noCallLogs()); + + outlineViewPanel.getOutlineView().setPropertyColumns( + TSK_PHONE_NUMBER_FROM.getLabel(), TSK_PHONE_NUMBER_FROM.getDisplayName(), + TSK_PHONE_NUMBER_TO.getLabel(), TSK_PHONE_NUMBER_TO.getDisplayName(), + TSK_DATETIME_START.getLabel(), TSK_DATETIME_START.getDisplayName() + ); + + Outline outline = outlineViewPanel.getOutlineView().getOutline(); + outline.setRootVisible(false); + + TableColumnModel columnModel = outline.getColumnModel(); + ETableColumn column = (ETableColumn) columnModel.getColumn(0); + ((ETableColumnModel) columnModel).setColumnHidden(column, true); + + outlineViewPanel.getExplorerManager().setRootContext( + new TableFilterNode( + new DataResultFilterNode( + new AbstractNode(Children.create(nodeFactory, true)), outlineViewPanel.getExplorerManager()), true)); + + outlineViewPanel.getExplorerManager().getRootContext().addNodeListener(new NodeAdapter(){ + @Override + public void childrenAdded(NodeMemberEvent nme) { + updateOutlineViewPanel(); + } + + @Override + public void childrenRemoved(NodeMemberEvent nme) { + updateOutlineViewPanel(); + } + }); + + } + + /** + * 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() { + java.awt.GridBagConstraints gridBagConstraints; + + outlineViewPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel(); + + setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(15, 15, 15, 15); + add(outlineViewPanel, gridBagConstraints); + }// //GEN-END:initComponents + + @Override + public String getDisplayName() { + return Bundle.CallLogViewer_title(); + } + + @Override + public JPanel getPanel() { + return this; + } + + @Override + public void setSelectionInfo(SelectionInfo info) { + nodeFactory.refresh(info); + } + + @Override + public Lookup getLookup() { + return outlineViewPanel.getLookup(); + } + + private void updateOutlineViewPanel() { + int nodeCount = outlineViewPanel.getExplorerManager().getRootContext().getChildren().getNodesCount(); + if(nodeCount == 0) { + outlineViewPanel.hideOutlineView(Bundle.ContactsViewer_noContacts_message()); + } else { + outlineViewPanel.showOutlineView(); + } + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java new file mode 100755 index 0000000000..567ed2d65c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.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.relationships; + +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Node; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * + * + */ +final class CallLogsChildNodeFactory extends ChildFactory{ + + private static final Logger logger = Logger.getLogger(CallLogsChildNodeFactory.class.getName()); + + private SelectionInfo selectionInfo; + + CallLogsChildNodeFactory(SelectionInfo selectionInfo) { + this.selectionInfo = selectionInfo; + } + + void refresh(SelectionInfo selectionInfo) { + this.selectionInfo = selectionInfo; + refresh(true); + } + + @Override + protected boolean createKeys(List list) { + + if(selectionInfo == null) { + return true; + } + + final Set relationshipSources; + try { + relationshipSources = selectionInfo.getRelationshipSources(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS + return false; + } + + + for(Content content: relationshipSources) { + if( !(content instanceof BlackboardArtifact)){ + continue; + } + + BlackboardArtifact bba = (BlackboardArtifact) content; + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID()); + + if ( fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) { + list.add(bba); + } + } + + list.sort(new BlackboardArtifactDateComparator(BlackboardArtifactDateComparator.ACCENDING)); + + return true; + } + + @Override + protected Node createNodeForKey(BlackboardArtifact key) { + return new CallLogNode(key); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java index d34bc084da..1c18ba5952 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.communications.relationships; -import java.util.TimeZone; import java.util.logging.Level; import javax.swing.Action; import org.apache.commons.lang3.StringUtils; @@ -27,20 +26,18 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; 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; -import org.sleuthkit.autopsy.communications.Utils; +import static org.sleuthkit.autopsy.communications.relationships.RelationshipsNodeUtilities.getAttributeDisplayString; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE; /** * Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView @@ -48,7 +45,6 @@ import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; class MessageNode extends BlackboardArtifactNode { public static final String UNTHREADED_ID = ""; - public static final String CALL_LOG_ID = ""; private static final Logger logger = Logger.getLogger(MessageNode.class.getName()); @@ -87,93 +83,46 @@ class MessageNode extends BlackboardArtifactNode { } sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS - - final BlackboardArtifact artifact = getArtifact(); - if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) { - sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",CALL_LOG_ID)); //NON-NLS - } else { - sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",threadID == null ? UNTHREADED_ID : threadID)); //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", Bundle.MessageNode_Node_Property_From(), "", - StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS - sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "", - StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS - sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", - getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS - sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "", - getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS - try { - sheetSet.put(new NodeProperty<>("Attms", 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", Bundle.MessageNode_Node_Property_From(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS - sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS - sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", - getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS - sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "", - getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS - try { - sheetSet.put(new NodeProperty<>("Attms", 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", Bundle.MessageNode_Node_Property_From(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS - sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "", - getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS - sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", - getAttributeDisplayString(artifact, TSK_DATETIME_START))); //NON-NLS - break; - default: - break; - } + + if(fromID == null || + (fromID != TSK_EMAIL_MSG && + fromID != TSK_MESSAGE)) { + return sheet; } - - 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) { + + sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",threadID == null ? UNTHREADED_ID : threadID)); //NON-NLS + sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "", + getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS 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 ""; + 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 } + + switch (fromID) { + case TSK_EMAIL_MSG: + sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "", + StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS + sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "", + StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS + sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", + getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS + break; + case TSK_MESSAGE: + sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS + sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "", + getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS + sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "", + getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS + break; + default: + break; + } + return sheet; } /** diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java index 4c7be60e80..617992dab5 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java @@ -229,11 +229,7 @@ public class MessageViewer extends JPanel implements RelationshipsViewer { if (!subject.isEmpty()) { threadNameLabel.setText(subject); } else { - if (threadIDList.contains(MessageNode.CALL_LOG_ID)) { - threadNameLabel.setText(Bundle.MessageViewer_viewMessage_calllogs()); - } else { - threadNameLabel.setText(Bundle.MessageViewer_viewMessage_unthreaded()); - } + threadNameLabel.setText(Bundle.MessageViewer_viewMessage_unthreaded()); } showMessagesPane(); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesChildNodeFactory.java index 5039ce225e..a68b95e9e4 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesChildNodeFactory.java @@ -23,12 +23,9 @@ 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.BlackboardAttribute; -import org.sleuthkit.datamodel.CommunicationsManager; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; @@ -92,8 +89,7 @@ public class MessagesChildNodeFactory extends ChildFactory{ 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 + if (fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG && fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) { continue; } @@ -102,12 +98,8 @@ public class MessagesChildNodeFactory extends ChildFactory{ // To achive this assign any artifact that does not have a threadID // the "UNTHREADED_ID" // All call logs will default to a single call logs thread - String artifactThreadID; - if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) { - artifactThreadID = MessageNode.CALL_LOG_ID; - } else { - artifactThreadID = MessageNode.UNTHREADED_ID; - } + String artifactThreadID = MessageNode.UNTHREADED_ID; + BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID)); if(attribute != null) { @@ -116,8 +108,7 @@ public class MessagesChildNodeFactory extends ChildFactory{ if(threadIDs == null || threadIDs.contains(artifactThreadID)) { list.add(bba); - } - + } } } catch (TskCoreException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form index ef5a5d1357..3289340e2c 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form @@ -11,6 +11,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java index 1431bb9fa1..9f6309d6af 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java @@ -35,6 +35,7 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider private final ContactsViewer contactsViewer; private final SummaryViewer summaryViewer; private final MediaViewer mediaViewer; + private final CallLogViewer callLogViewer; private final ModifiableProxyLookup proxyLookup; @@ -47,11 +48,13 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider contactsViewer = new ContactsViewer(); summaryViewer = new SummaryViewer(); mediaViewer = new MediaViewer(); + callLogViewer = new CallLogViewer(); proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); tabPane.add(summaryViewer.getDisplayName(), summaryViewer); tabPane.add(messagesViewer.getDisplayName(), messagesViewer); + tabPane.add(callLogViewer.getDisplayName(), callLogViewer); tabPane.add(contactsViewer.getDisplayName(), contactsViewer); tabPane.add(mediaViewer.getDisplayName(), mediaViewer); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java new file mode 100755 index 0000000000..2d2aaef0de --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java @@ -0,0 +1,53 @@ +/* + * 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.relationships; + +import java.util.Comparator; +import java.util.TimeZone; +import java.util.logging.Level; +import org.sleuthkit.autopsy.communications.Utils; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME; +import org.sleuthkit.datamodel.TimeUtilities; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * + * + */ +public class RelationshipsNodeUtilities { + + private static final Logger logger = Logger.getLogger(RelationshipsNodeUtilities.class.getName()); + /** + * + * 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. + */ + 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/relationships/ThreadChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java index 1cf987d132..8f3afd5519 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java @@ -126,13 +126,8 @@ final class ThreadChildNodeFactory extends ChildFactory { // We want email and message artifacts that do not have "threadIDs" to appear as one thread in the UI // To achive this assign any artifact that does not have a threadID // the "UNTHREADED_ID" - // All call logs will default to a single call logs thread - String threadID; - if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) { - threadID = MessageNode.CALL_LOG_ID; - } else { - threadID = MessageNode.UNTHREADED_ID; - } + String threadID = MessageNode.UNTHREADED_ID; + BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID)); if(attribute != null) { @@ -176,44 +171,11 @@ final class ThreadChildNodeFactory extends ChildFactory { if (attribute != null) { return new ThreadNode(bba, attribute.getValueString(), preferredAction); } else { - if (bba.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) { - return new CallLogNode(); - } else { - // Only one of these should occur. - return new UnthreadedNode(); - } + // Only one of these should occur. + return new UnthreadedNode(); } } - /** - * This node represents the "call log" thread. - */ - final class CallLogNode extends AbstractNode { - /** - * Construct an instance of a CallLogNode. - */ - CallLogNode() { - super(Children.LEAF); - setDisplayName("Call Logs"); - this.setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/unthreaded.png" ); - } - - @Override - protected Sheet createSheet() { - Sheet sheet = super.createSheet(); - Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); - if (sheetSet == null) { - sheetSet = Sheet.createPropertiesSet(); - sheet.put(sheetSet); - } - - // Give this node a threadID of "CALL_LOG_ID" - sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",MessageNode.CALL_LOG_ID)); - - return sheet; - } - } - /** * This node represents the "unthreaded" thread. */ From 0013c31977304174fbba9f2e68f3ee898a6056be Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 3 Jul 2019 10:36:51 -0400 Subject: [PATCH 2/9] cleaned up imports in ThreadChildNodeFactory --- .../communications/relationships/ThreadChildNodeFactory.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java index 8f3afd5519..6d66c0b032 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java @@ -29,13 +29,10 @@ import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.CommunicationsManager; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; From 44b08f6a3a7796f1557f7db20e0aaafcc677323f Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 3 Jul 2019 14:39:24 -0400 Subject: [PATCH 3/9] Made adjustments based on comments from Brian --- .../relationships/Bundle.properties-MERGED | 3 + .../relationships/CallLogNode.java | 71 ++++++++++++++++--- .../relationships/CallLogViewer.form | 3 +- .../relationships/CallLogViewer.java | 26 ++++--- .../CallLogsChildNodeFactory.java | 3 +- .../RelationshipsNodeUtilities.java | 1 - 6 files changed, 79 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED index 9cfcae847e..58eafd7bff 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED @@ -1,4 +1,7 @@ +CallLogViewer_device_label=Device +CallLogViewer_duration_label=Duration(seconds) CallLogViewer_noCallLogs= +CallLogViewer_recipient_label=Recipient CallLogViewer_title=Call Logs ContactDetailsPane.nameLabel.text=Placeholder ContactNode_Email=Email Address diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java index 787f6ed9d4..c3531ef591 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java @@ -6,24 +6,38 @@ package org.sleuthkit.autopsy.communications.relationships; import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.communications.Utils; import static org.sleuthkit.autopsy.communications.relationships.RelationshipsNodeUtilities.getAttributeDisplayString; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.NodeProperty; +import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG; import org.sleuthkit.datamodel.BlackboardAttribute; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END; 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_DIRECTION; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER; +import org.sleuthkit.datamodel.TskCoreException; /** - * - * + * A BlackboardArtifactNode for Calllogs. */ -public class CallLogNode extends BlackboardArtifactNode { +final class CallLogNode extends BlackboardArtifactNode { - CallLogNode(BlackboardArtifact artifact) { - super(artifact); + final static String DURATION_PROP = "duration"; + + CallLogNode(BlackboardArtifact artifact) { + super(artifact, Utils.getIconFilePath(Account.Type.DEVICE)); + + try { + setDisplayName(artifact.getDataSource().getName()); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } } @Override @@ -41,15 +55,52 @@ public class CallLogNode extends BlackboardArtifactNode { if (null != fromID && fromID != TSK_CALLLOG) { return sheet; } - - sheetSet.put(createNode(TSK_PHONE_NUMBER_FROM, artifact)); - sheetSet.put(createNode(TSK_PHONE_NUMBER_TO, artifact)); - sheetSet.put(createNode(TSK_DATETIME_START, artifact)); + String phoneNumber = getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM); + if(phoneNumber == null || phoneNumber.isEmpty()) { + phoneNumber = getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO); + } + + long duration = -1; + try{ + duration = getCallDuration(artifact); + } catch(TskCoreException ex) { + + } + + sheetSet.put(createNode(TSK_DATETIME_START, artifact)); + sheetSet.put(createNode(TSK_DIRECTION, artifact)); + sheetSet.put(new NodeProperty<>(TSK_PHONE_NUMBER.getLabel(), TSK_PHONE_NUMBER.getDisplayName(), "", phoneNumber)); + if(duration != -1) { + sheetSet.put(new NodeProperty<>("duration", "Duration", "", Long.toString(duration))); + } + return sheet; } NodeProperty createNode(BlackboardAttribute.ATTRIBUTE_TYPE type, BlackboardArtifact artifact) { - return new NodeProperty<>(type.getLabel(), type.getDisplayName(), "", getAttributeDisplayString(artifact, type)); + return new NodeProperty<>(type.getLabel(), type.getDisplayName(), type.getDisplayName(), getAttributeDisplayString(artifact, type)); + } + + long getCallDuration(BlackboardArtifact artifact) throws TskCoreException { + BlackboardAttribute startAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(TSK_DATETIME_START.getTypeID()))); + BlackboardAttribute endAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(TSK_DATETIME_END.getTypeID()))); + + if(startAttribute == null || endAttribute == null) { + return -1; + } + + return endAttribute.getValueLong() - startAttribute.getValueLong(); + } + + /** + * 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/relationships/CallLogViewer.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.form index 18ea7b177a..cab67d7f86 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.form @@ -1,6 +1,6 @@ -
+ @@ -11,6 +11,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java index c421609fdc..344335aeea 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java @@ -19,9 +19,6 @@ package org.sleuthkit.autopsy.communications.relationships; import javax.swing.JPanel; -import javax.swing.table.TableColumnModel; -import org.netbeans.swing.etable.ETableColumn; -import org.netbeans.swing.etable.ETableColumnModel; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; import org.openide.nodes.AbstractNode; @@ -32,13 +29,13 @@ import org.openide.util.Lookup; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; -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_PHONE_NUMBER; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION; /** * - * + * CallLogViewer Panel */ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsViewer { @@ -46,7 +43,10 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie @Messages({ "CallLogViewer_title=Call Logs", - "CallLogViewer_noCallLogs=" + "CallLogViewer_noCallLogs=", + "CallLogViewer_recipient_label=Recipient", + "CallLogViewer_duration_label=Duration(seconds)", + "CallLogViewer_device_label=Device" }) /** @@ -59,17 +59,15 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie outlineViewPanel.hideOutlineView(Bundle.CallLogViewer_noCallLogs()); outlineViewPanel.getOutlineView().setPropertyColumns( - TSK_PHONE_NUMBER_FROM.getLabel(), TSK_PHONE_NUMBER_FROM.getDisplayName(), - TSK_PHONE_NUMBER_TO.getLabel(), TSK_PHONE_NUMBER_TO.getDisplayName(), - TSK_DATETIME_START.getLabel(), TSK_DATETIME_START.getDisplayName() + TSK_DIRECTION.getLabel(), TSK_DIRECTION.getDisplayName(), + TSK_PHONE_NUMBER.getLabel(), Bundle.CallLogViewer_recipient_label(), + TSK_DATETIME_START.getLabel(), TSK_DATETIME_START.getDisplayName(), + CallLogNode.DURATION_PROP, Bundle.CallLogViewer_duration_label() ); Outline outline = outlineViewPanel.getOutlineView().getOutline(); outline.setRootVisible(false); - - TableColumnModel columnModel = outline.getColumnModel(); - ETableColumn column = (ETableColumn) columnModel.getColumn(0); - ((ETableColumnModel) columnModel).setColumnHidden(column, true); + ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CallLogViewer_device_label()); outlineViewPanel.getExplorerManager().setRootContext( new TableFilterNode( diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java index 567ed2d65c..326522dd47 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java @@ -29,8 +29,7 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** - * - * + *A ChildFactory for CallLog artifacts. */ final class CallLogsChildNodeFactory extends ChildFactory{ diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java index 2d2aaef0de..fd2509aba9 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java @@ -5,7 +5,6 @@ */ package org.sleuthkit.autopsy.communications.relationships; -import java.util.Comparator; import java.util.TimeZone; import java.util.logging.Level; import org.sleuthkit.autopsy.communications.Utils; From 632d3275d10ed394edbd2a36832c89f6d5913fa4 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 5 Jul 2019 16:15:51 -0400 Subject: [PATCH 4/9] Fixed bug in the cvt threads tab --- .../communications/relationships/ThreadChildNodeFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java index 6d66c0b032..bf8eb5c509 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadChildNodeFactory.java @@ -117,7 +117,6 @@ final class ThreadChildNodeFactory extends ChildFactory { 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) { // We want email and message artifacts that do not have "threadIDs" to appear as one thread in the UI From d83a5b9c958411dea02162ecf79994c1cbacdf44 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 8 Jul 2019 13:02:38 -0400 Subject: [PATCH 5/9] replaced the device name with the device id --- .../relationships/CallLogNode.java | 11 ++--- .../CallLogsChildNodeFactory.java | 49 ++++++++++++++++++- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java index c3531ef591..9d13c55ce4 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java @@ -30,14 +30,9 @@ final class CallLogNode extends BlackboardArtifactNode { final static String DURATION_PROP = "duration"; - CallLogNode(BlackboardArtifact artifact) { - super(artifact, Utils.getIconFilePath(Account.Type.DEVICE)); - - try { - setDisplayName(artifact.getDataSource().getName()); - } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); - } + CallLogNode(BlackboardArtifact artifact, String deviceID) { + super(artifact, Utils.getIconFilePath(Account.Type.PHONE)); + setDisplayName(deviceID); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java index 326522dd47..a22f8f14cf 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java @@ -18,13 +18,21 @@ */ package org.sleuthkit.autopsy.communications.relationships; +import java.util.ArrayList; +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.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.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; @@ -37,6 +45,8 @@ final class CallLogsChildNodeFactory extends ChildFactory{ private SelectionInfo selectionInfo; + private Map deviceIDMap = new HashMap(); + CallLogsChildNodeFactory(SelectionInfo selectionInfo) { this.selectionInfo = selectionInfo; } @@ -70,7 +80,7 @@ final class CallLogsChildNodeFactory extends ChildFactory{ BlackboardArtifact bba = (BlackboardArtifact) content; BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID()); - if ( fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) { + if ( fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) { list.add(bba); } } @@ -82,6 +92,41 @@ final class CallLogsChildNodeFactory extends ChildFactory{ @Override protected Node createNodeForKey(BlackboardArtifact key) { - return new CallLogNode(key); + String deviceID = ""; + try { + deviceID = getDeviceIDForDataSource(key.getDataSource().getName()); + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to get account for artifact data source: artifactID = %d", key.getId()), ex); + } + + return new CallLogNode(key, deviceID); + } + + private String getDeviceIDForDataSource(String dataSourceName) throws NoCurrentCaseException, TskCoreException{ + + String deviceID = deviceIDMap.get(dataSourceName); + + if(deviceID == null) { + CommunicationsManager manager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); + CommunicationsFilter filter = new CommunicationsFilter(); + + List list = new ArrayList<>(); + list.add(dataSourceName); + + filter.addAndFilter(new CommunicationsFilter.DeviceFilter(list)); + + // This list should just have 1 item in it + List adiList = manager.getAccountDeviceInstancesWithRelationships(filter); + + if(adiList != null && adiList.size() > 0) { + deviceID = adiList.get(0).getDeviceId(); + } else { + deviceID = ""; + } + + deviceIDMap.put(dataSourceName, deviceID); + } + + return deviceID; } } From 800b1345fdd5bedee0193f1edca4dd5fd862dad9 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 8 Jul 2019 13:51:59 -0400 Subject: [PATCH 6/9] fixed bug with device id --- .../autopsy/communications/relationships/CallLogNode.java | 1 - .../relationships/CallLogsChildNodeFactory.java | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java index 9d13c55ce4..508421c58a 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java @@ -6,7 +6,6 @@ package org.sleuthkit.autopsy.communications.relationships; import org.openide.nodes.Sheet; -import org.openide.util.Exceptions; import org.sleuthkit.autopsy.communications.Utils; import static org.sleuthkit.autopsy.communications.relationships.RelationshipsNodeUtilities.getAttributeDisplayString; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java index a22f8f14cf..37c483fe2a 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java @@ -29,6 +29,7 @@ import org.openide.nodes.Node; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.AccountDeviceInstance; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.CommunicationsFilter; @@ -112,8 +113,13 @@ final class CallLogsChildNodeFactory extends ChildFactory{ List list = new ArrayList<>(); list.add(dataSourceName); + + List typeList = new ArrayList(); + typeList.add(Account.Type.DEVICE); filter.addAndFilter(new CommunicationsFilter.DeviceFilter(list)); + filter.addAndFilter(new CommunicationsFilter.AccountTypeFilter(typeList)); + // This list should just have 1 item in it List adiList = manager.getAccountDeviceInstancesWithRelationships(filter); From 6a2837af8107d101f0cb32c34b7483ecb9e44716 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 8 Jul 2019 14:44:24 -0400 Subject: [PATCH 7/9] created a calllogkey and moved the retrival of the deviceID to createKeys --- .../CallLogsChildNodeFactory.java | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java index 37c483fe2a..427b6ff1e5 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.communications.relationships; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,6 +29,7 @@ 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.communications.relationships.CallLogsChildNodeFactory.CallLogNodeKey; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.AccountDeviceInstance; @@ -40,7 +42,7 @@ import org.sleuthkit.datamodel.TskCoreException; /** *A ChildFactory for CallLog artifacts. */ -final class CallLogsChildNodeFactory extends ChildFactory{ +final class CallLogsChildNodeFactory extends ChildFactory{ private static final Logger logger = Logger.getLogger(CallLogsChildNodeFactory.class.getName()); @@ -58,7 +60,7 @@ final class CallLogsChildNodeFactory extends ChildFactory{ } @Override - protected boolean createKeys(List list) { + protected boolean createKeys(List list) { if(selectionInfo == null) { return true; @@ -81,26 +83,28 @@ final class CallLogsChildNodeFactory extends ChildFactory{ BlackboardArtifact bba = (BlackboardArtifact) content; BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID()); - if ( fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) { - list.add(bba); + if ( fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) { + + String deviceID = ""; + try { + deviceID = getDeviceIDForDataSource(bba.getDataSource().getName()); + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to get account for artifact data source: artifactID = %d", bba.getId()), ex); + } + + list.add(new CallLogNodeKey(bba, deviceID)); } } - list.sort(new BlackboardArtifactDateComparator(BlackboardArtifactDateComparator.ACCENDING)); + list.sort(new CallLogComparator(BlackboardArtifactDateComparator.ACCENDING)); return true; } - + @Override - protected Node createNodeForKey(BlackboardArtifact key) { - String deviceID = ""; - try { - deviceID = getDeviceIDForDataSource(key.getDataSource().getName()); - } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.WARNING, String.format("Unable to get account for artifact data source: artifactID = %d", key.getId()), ex); - } + protected Node createNodeForKey(CallLogNodeKey key) { - return new CallLogNode(key, deviceID); + return new CallLogNode(key.getArtifact(), key.getDeviceID()); } private String getDeviceIDForDataSource(String dataSourceName) throws NoCurrentCaseException, TskCoreException{ @@ -135,4 +139,36 @@ final class CallLogsChildNodeFactory extends ChildFactory{ return deviceID; } + + final class CallLogNodeKey{ + private final BlackboardArtifact artifact; + private final String deviceID; + + private CallLogNodeKey(BlackboardArtifact artifact, String deviceID) { + this.artifact = artifact; + this.deviceID = deviceID; + } + + BlackboardArtifact getArtifact() { + return artifact; + } + + String getDeviceID() { + return deviceID; + } + } + + final class CallLogComparator implements Comparator{ + + final BlackboardArtifactDateComparator comparator; + + CallLogComparator(int direction) { + comparator = new BlackboardArtifactDateComparator(direction); + } + + @Override + public int compare(CallLogNodeKey key1, CallLogNodeKey key2) { + return comparator.compare(key1.getArtifact(), key2.getArtifact()); + } + } } From d31719b217bc63c326a52785deb4127f12b6641b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 15 Jul 2019 15:58:08 -0400 Subject: [PATCH 8/9] addressed review comments --- .../BlackboardArtifactDateComparator.java | 103 +++++++++--------- .../relationships/Bundle.properties-MERGED | 2 +- .../relationships/CallLogNode.java | 25 ++++- .../relationships/CallLogViewer.java | 2 +- .../RelationshipsNodeUtilities.java | 24 +++- 5 files changed, 92 insertions(+), 64 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.java index cef2ddd3d9..b4279c8193 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/BlackboardArtifactDateComparator.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 obt ain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.communications.relationships; @@ -32,62 +45,14 @@ class BlackboardArtifactDateComparator implements Comparator @Override public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) { - BlackboardAttribute attribute1 = null; - BlackboardAttribute attribute2 = null; + BlackboardAttribute attribute1 = getTimeAttributeForArtifact(bba1); + BlackboardAttribute attribute2 = getTimeAttributeForArtifact(bba2); // Inializing to Long.MAX_VALUE so that if a BlackboardArtifact of // any unexpected type is passed in, it will bubble to the top of // the list. long dateTime1 = Long.MAX_VALUE; long dateTime2 = Long.MAX_VALUE; - if (bba1 != null) { - BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID()); - if (fromID != null) { - try { - switch (fromID) { - case TSK_EMAIL_MSG: - attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT)); - break; - case TSK_MESSAGE: - attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME)); - break; - case TSK_CALLLOG: - attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START)); - break; - default: - attribute1 = null; - break; - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex); - } - } - } - - if (bba2 != null) { - BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID()); - if (fromID != null) { - try { - switch (fromID) { - case TSK_EMAIL_MSG: - attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT)); - break; - case TSK_MESSAGE: - attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME)); - break; - case TSK_CALLLOG: - attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START)); - break; - default: - attribute2 = null; - break; - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex); - } - } - } - if (attribute1 != null) { dateTime1 = attribute1.getValueLong(); } @@ -98,4 +63,36 @@ class BlackboardArtifactDateComparator implements Comparator return Long.compare(dateTime1, dateTime2) * direction; } + + private BlackboardAttribute getTimeAttributeForArtifact(BlackboardArtifact artifact) { + if(artifact == null) { + return null; + } + + BlackboardAttribute attribute = null; + + BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); + if (fromID != null) { + try { + switch (fromID) { + case TSK_EMAIL_MSG: + attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT)); + break; + case TSK_MESSAGE: + attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME)); + break; + case TSK_CALLLOG: + attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START)); + break; + default: + attribute = null; + break; + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", artifact.getArtifactID()), ex); + } + } + + return attribute; + } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED index 58eafd7bff..f2aa0df8e1 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED @@ -1,7 +1,7 @@ CallLogViewer_device_label=Device CallLogViewer_duration_label=Duration(seconds) CallLogViewer_noCallLogs= -CallLogViewer_recipient_label=Recipient +CallLogViewer_recipient_label=To/From CallLogViewer_title=Call Logs ContactDetailsPane.nameLabel.text=Placeholder ContactNode_Email=Email Address diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java index 508421c58a..a9e92d6451 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java @@ -1,13 +1,28 @@ /* - * 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.relationships; +import java.util.logging.Level; import org.openide.nodes.Sheet; import org.sleuthkit.autopsy.communications.Utils; import static org.sleuthkit.autopsy.communications.relationships.RelationshipsNodeUtilities.getAttributeDisplayString; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.datamodel.Account; @@ -27,6 +42,8 @@ import org.sleuthkit.datamodel.TskCoreException; */ final class CallLogNode extends BlackboardArtifactNode { + private static final Logger logger = Logger.getLogger(CallLogNode.class.getName()); + final static String DURATION_PROP = "duration"; CallLogNode(BlackboardArtifact artifact, String deviceID) { @@ -59,7 +76,7 @@ final class CallLogNode extends BlackboardArtifactNode { try{ duration = getCallDuration(artifact); } catch(TskCoreException ex) { - + logger.log(Level.WARNING, String.format("Unable to get calllog duration for artifact: %d", artifact.getArtifactID()), ex); } sheetSet.put(createNode(TSK_DATETIME_START, artifact)); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java index 344335aeea..cb5d34d7f9 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java @@ -44,7 +44,7 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie @Messages({ "CallLogViewer_title=Call Logs", "CallLogViewer_noCallLogs=", - "CallLogViewer_recipient_label=Recipient", + "CallLogViewer_recipient_label=To/From", "CallLogViewer_duration_label=Duration(seconds)", "CallLogViewer_device_label=Device" }) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java index fd2509aba9..361eb1d7ad 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java @@ -1,8 +1,22 @@ /* - * 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.relationships; import java.util.TimeZone; @@ -16,10 +30,10 @@ import org.sleuthkit.datamodel.TimeUtilities; import org.sleuthkit.datamodel.TskCoreException; /** - * + * A set of reusable utility functions for the Relationships package. * */ -public class RelationshipsNodeUtilities { +final class RelationshipsNodeUtilities { private static final Logger logger = Logger.getLogger(RelationshipsNodeUtilities.class.getName()); /** From 7adc8a6a2afa418484f1d35b07b5d1b11e0fd3c1 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 16 Jul 2019 12:33:37 -0400 Subject: [PATCH 9/9] addressed codacy issues --- .../CallLogsChildNodeFactory.java | 36 +++++++++++++++++-- .../relationships/RelationshipBrowser.java | 18 ++++------ .../RelationshipsNodeUtilities.java | 5 +++ 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java index 427b6ff1e5..5bfd1bdb96 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogsChildNodeFactory.java @@ -48,7 +48,7 @@ final class CallLogsChildNodeFactory extends ChildFactory{ private SelectionInfo selectionInfo; - private Map deviceIDMap = new HashMap(); + private final Map deviceIDMap = new HashMap<>(); CallLogsChildNodeFactory(SelectionInfo selectionInfo) { this.selectionInfo = selectionInfo; @@ -107,6 +107,19 @@ final class CallLogsChildNodeFactory extends ChildFactory{ return new CallLogNode(key.getArtifact(), key.getDeviceID()); } + /** + * Gets the device ID for the given data source. + * + * To reduce lookup calls to the DB unique dataSourceName\deviceID pairs + * are stored in deviceIDMap. + * + * @param dataSourceName String name of data source + * + * @return device ID for given dataSourceName or empty string if non is found. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + */ private String getDeviceIDForDataSource(String dataSourceName) throws NoCurrentCaseException, TskCoreException{ String deviceID = deviceIDMap.get(dataSourceName); @@ -128,7 +141,7 @@ final class CallLogsChildNodeFactory extends ChildFactory{ // This list should just have 1 item in it List adiList = manager.getAccountDeviceInstancesWithRelationships(filter); - if(adiList != null && adiList.size() > 0) { + if( adiList != null && !adiList.isEmpty() ) { deviceID = adiList.get(0).getDeviceId(); } else { deviceID = ""; @@ -137,9 +150,13 @@ final class CallLogsChildNodeFactory extends ChildFactory{ deviceIDMap.put(dataSourceName, deviceID); } - return deviceID; + return (deviceID != null ? deviceID : ""); } + /** + * ChildFactory key class which contains a BlackboardArtifact and its + * data source deviceID + */ final class CallLogNodeKey{ private final BlackboardArtifact artifact; private final String deviceID; @@ -149,15 +166,28 @@ final class CallLogsChildNodeFactory extends ChildFactory{ this.deviceID = deviceID; } + /** + * Get the BlackboardArtifact for this key + * + * @return BlackboardArtifact instance + */ BlackboardArtifact getArtifact() { return artifact; } + /** + * Gets the BlackboardArtifact data source device ID. + * + * @return String device id. + */ String getDeviceID() { return deviceID; } } + /** + * A comparator for CallLogNodeKey objects + */ final class CallLogComparator implements Comparator{ final BlackboardArtifactDateComparator comparator; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java index 9f6309d6af..f1ef86d244 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java @@ -30,13 +30,6 @@ import org.sleuthkit.autopsy.communications.ModifiableProxyLookup; public final class RelationshipBrowser extends JPanel implements Lookup.Provider { private SelectionInfo currentSelection; - - private final MessageViewer messagesViewer; - private final ContactsViewer contactsViewer; - private final SummaryViewer summaryViewer; - private final MediaViewer mediaViewer; - private final CallLogViewer callLogViewer; - private final ModifiableProxyLookup proxyLookup; /** @@ -44,11 +37,12 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider */ public RelationshipBrowser() { initComponents(); - messagesViewer = new MessageViewer(); - contactsViewer = new ContactsViewer(); - summaryViewer = new SummaryViewer(); - mediaViewer = new MediaViewer(); - callLogViewer = new CallLogViewer(); + + MessageViewer messagesViewer = new MessageViewer(); + ContactsViewer contactsViewer = new ContactsViewer(); + SummaryViewer summaryViewer = new SummaryViewer(); + MediaViewer mediaViewer = new MediaViewer(); + CallLogViewer callLogViewer = new CallLogViewer(); proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java index 361eb1d7ad..db2f6f6ebd 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipsNodeUtilities.java @@ -36,6 +36,11 @@ import org.sleuthkit.datamodel.TskCoreException; final class RelationshipsNodeUtilities { private static final Logger logger = Logger.getLogger(RelationshipsNodeUtilities.class.getName()); + + // Here to make codacy happy + private RelationshipsNodeUtilities(){ + } + /** * * Get the display string for the attribute of the given type from the given