mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 03:24:55 +00:00
Merge pull request #5008 from kellykelly3/1263-cvt-calllog-tab
1263 - CVT Call Log Tab
This commit is contained in:
commit
46c4067db9
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obt ain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
|
import java.util.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<BlackboardArtifact> {
|
||||||
|
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 = 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 (attribute1 != null) {
|
||||||
|
dateTime1 = attribute1.getValueLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute2 != null) {
|
||||||
|
dateTime2 = attribute2.getValueLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
CallLogViewer_device_label=Device
|
||||||
|
CallLogViewer_duration_label=Duration(seconds)
|
||||||
|
CallLogViewer_noCallLogs=<No call logs found for selected account>
|
||||||
|
CallLogViewer_recipient_label=To/From
|
||||||
|
CallLogViewer_title=Call Logs
|
||||||
ContactDetailsPane.nameLabel.text=Placeholder
|
ContactDetailsPane.nameLabel.text=Placeholder
|
||||||
ContactNode_Email=Email Address
|
ContactNode_Email=Email Address
|
||||||
ContactNode_Home_Number=Home Number
|
ContactNode_Home_Number=Home Number
|
||||||
|
117
Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java
Executable file
117
Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogNode.java
Executable file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
|
import java.util.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;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
|
super(artifact, Utils.getIconFilePath(Account.Type.PHONE));
|
||||||
|
setDisplayName(deviceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
logger.log(Level.WARNING, String.format("Unable to get calllog duration for artifact: %d", artifact.getArtifactID()), 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(), 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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="15" insetsBottom="15" insetsRight="15" anchor="12" weightX="1.0" weightY="1.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
146
Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java
Executable file
146
Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java
Executable file
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
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;
|
||||||
|
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 {
|
||||||
|
|
||||||
|
private final CallLogsChildNodeFactory nodeFactory;
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"CallLogViewer_title=Call Logs",
|
||||||
|
"CallLogViewer_noCallLogs=<No call logs found for selected account>",
|
||||||
|
"CallLogViewer_recipient_label=To/From",
|
||||||
|
"CallLogViewer_duration_label=Duration(seconds)",
|
||||||
|
"CallLogViewer_device_label=Device"
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form CallLogViewer
|
||||||
|
*/
|
||||||
|
public CallLogViewer() {
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
nodeFactory = new CallLogsChildNodeFactory(null);
|
||||||
|
outlineViewPanel.hideOutlineView(Bundle.CallLogViewer_noCallLogs());
|
||||||
|
|
||||||
|
outlineViewPanel.getOutlineView().setPropertyColumns(
|
||||||
|
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);
|
||||||
|
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CallLogViewer_device_label());
|
||||||
|
|
||||||
|
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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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);
|
||||||
|
}// </editor-fold>//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
|
||||||
|
}
|
@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obt ain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
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.communications.relationships.CallLogsChildNodeFactory.CallLogNodeKey;
|
||||||
|
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;
|
||||||
|
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*A ChildFactory for CallLog artifacts.
|
||||||
|
*/
|
||||||
|
final class CallLogsChildNodeFactory extends ChildFactory<CallLogNodeKey>{
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(CallLogsChildNodeFactory.class.getName());
|
||||||
|
|
||||||
|
private SelectionInfo selectionInfo;
|
||||||
|
|
||||||
|
private final Map<String, String> deviceIDMap = new HashMap<>();
|
||||||
|
|
||||||
|
CallLogsChildNodeFactory(SelectionInfo selectionInfo) {
|
||||||
|
this.selectionInfo = selectionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh(SelectionInfo selectionInfo) {
|
||||||
|
this.selectionInfo = selectionInfo;
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<CallLogNodeKey> list) {
|
||||||
|
|
||||||
|
if(selectionInfo == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Set<Content> 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) {
|
||||||
|
|
||||||
|
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 CallLogComparator(BlackboardArtifactDateComparator.ACCENDING));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(CallLogNodeKey key) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if(deviceID == null) {
|
||||||
|
CommunicationsManager manager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||||
|
CommunicationsFilter filter = new CommunicationsFilter();
|
||||||
|
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
list.add(dataSourceName);
|
||||||
|
|
||||||
|
List<Account.Type> typeList = new ArrayList<Account.Type>();
|
||||||
|
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<AccountDeviceInstance> adiList = manager.getAccountDeviceInstancesWithRelationships(filter);
|
||||||
|
|
||||||
|
if( adiList != null && !adiList.isEmpty() ) {
|
||||||
|
deviceID = adiList.get(0).getDeviceId();
|
||||||
|
} else {
|
||||||
|
deviceID = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceIDMap.put(dataSourceName, 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;
|
||||||
|
|
||||||
|
private CallLogNodeKey(BlackboardArtifact artifact, String deviceID) {
|
||||||
|
this.artifact = artifact;
|
||||||
|
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<CallLogNodeKey>{
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.communications.relationships;
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM;
|
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_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_FROM;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO;
|
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.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.datamodel.TskCoreException;
|
||||||
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.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
|
* 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 {
|
class MessageNode extends BlackboardArtifactNode {
|
||||||
|
|
||||||
public static final String UNTHREADED_ID = "<UNTHREADED>";
|
public static final String UNTHREADED_ID = "<UNTHREADED>";
|
||||||
public static final String CALL_LOG_ID = "<CALLLOG>";
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(MessageNode.class.getName());
|
private static final Logger logger = Logger.getLogger(MessageNode.class.getName());
|
||||||
|
|
||||||
@ -88,18 +84,24 @@ class MessageNode extends BlackboardArtifactNode {
|
|||||||
|
|
||||||
sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS
|
sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final BlackboardArtifact artifact = getArtifact();
|
final BlackboardArtifact artifact = getArtifact();
|
||||||
if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) {
|
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
||||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",CALL_LOG_ID)); //NON-NLS
|
|
||||||
} else {
|
if(fromID == null ||
|
||||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",threadID == null ? UNTHREADED_ID : threadID)); //NON-NLS
|
(fromID != TSK_EMAIL_MSG &&
|
||||||
|
fromID != TSK_MESSAGE)) {
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
|
||||||
if (null != fromID) {
|
|
||||||
//Consider refactoring this to reduce boilerplate
|
|
||||||
switch (fromID) {
|
switch (fromID) {
|
||||||
case TSK_EMAIL_MSG:
|
case TSK_EMAIL_MSG:
|
||||||
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||||
@ -108,14 +110,6 @@ class MessageNode extends BlackboardArtifactNode {
|
|||||||
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS
|
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS
|
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;
|
break;
|
||||||
case TSK_MESSAGE:
|
case TSK_MESSAGE:
|
||||||
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||||
@ -124,58 +118,13 @@ class MessageNode extends BlackboardArtifactNode {
|
|||||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
|
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
|
||||||
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||||
getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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
|
* Circumvent DataResultFilterNode's slightly odd delegation to
|
||||||
* BlackboardArtifactNode.getSourceName().
|
* BlackboardArtifactNode.getSourceName().
|
||||||
|
@ -228,13 +228,9 @@ public class MessageViewer extends JPanel implements RelationshipsViewer {
|
|||||||
|
|
||||||
if (!subject.isEmpty()) {
|
if (!subject.isEmpty()) {
|
||||||
threadNameLabel.setText(subject);
|
threadNameLabel.setText(subject);
|
||||||
} else {
|
|
||||||
if (threadIDList.contains(MessageNode.CALL_LOG_ID)) {
|
|
||||||
threadNameLabel.setText(Bundle.MessageViewer_viewMessage_calllogs());
|
|
||||||
} else {
|
} else {
|
||||||
threadNameLabel.setText(Bundle.MessageViewer_viewMessage_unthreaded());
|
threadNameLabel.setText(Bundle.MessageViewer_viewMessage_unthreaded());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
showMessagesPane();
|
showMessagesPane();
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,6 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
|||||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||||
|
|
||||||
if (fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
if (fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||||
&& fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
|
||||||
&& fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
&& fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -100,12 +99,8 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
|||||||
// To achive this assign any artifact that does not have a threadID
|
// To achive this assign any artifact that does not have a threadID
|
||||||
// the "UNTHREADED_ID"
|
// the "UNTHREADED_ID"
|
||||||
// All call logs will default to a single call logs thread
|
// All call logs will default to a single call logs thread
|
||||||
String artifactThreadID;
|
String artifactThreadID = MessageNode.UNTHREADED_ID;
|
||||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) {
|
|
||||||
artifactThreadID = MessageNode.CALL_LOG_ID;
|
|
||||||
} else {
|
|
||||||
artifactThreadID = MessageNode.UNTHREADED_ID;
|
|
||||||
}
|
|
||||||
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||||
|
|
||||||
if(attribute != null) {
|
if(attribute != null) {
|
||||||
@ -115,7 +110,6 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
|||||||
if(threadIDs == null || threadIDs.contains(artifactThreadID)) {
|
if(threadIDs == null || threadIDs.contains(artifactThreadID)) {
|
||||||
list.add(bba);
|
list.add(bba);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
@ -30,12 +30,6 @@ import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
|
|||||||
public final class RelationshipBrowser extends JPanel implements Lookup.Provider {
|
public final class RelationshipBrowser extends JPanel implements Lookup.Provider {
|
||||||
|
|
||||||
private SelectionInfo currentSelection;
|
private SelectionInfo currentSelection;
|
||||||
|
|
||||||
private final MessageViewer messagesViewer;
|
|
||||||
private final ContactsViewer contactsViewer;
|
|
||||||
private final SummaryViewer summaryViewer;
|
|
||||||
private final MediaViewer mediaViewer;
|
|
||||||
|
|
||||||
private final ModifiableProxyLookup proxyLookup;
|
private final ModifiableProxyLookup proxyLookup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,15 +37,18 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
|||||||
*/
|
*/
|
||||||
public RelationshipBrowser() {
|
public RelationshipBrowser() {
|
||||||
initComponents();
|
initComponents();
|
||||||
messagesViewer = new MessageViewer();
|
|
||||||
contactsViewer = new ContactsViewer();
|
MessageViewer messagesViewer = new MessageViewer();
|
||||||
summaryViewer = new SummaryViewer();
|
ContactsViewer contactsViewer = new ContactsViewer();
|
||||||
mediaViewer = new MediaViewer();
|
SummaryViewer summaryViewer = new SummaryViewer();
|
||||||
|
MediaViewer mediaViewer = new MediaViewer();
|
||||||
|
CallLogViewer callLogViewer = new CallLogViewer();
|
||||||
|
|
||||||
proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup());
|
proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup());
|
||||||
|
|
||||||
tabPane.add(summaryViewer.getDisplayName(), summaryViewer);
|
tabPane.add(summaryViewer.getDisplayName(), summaryViewer);
|
||||||
tabPane.add(messagesViewer.getDisplayName(), messagesViewer);
|
tabPane.add(messagesViewer.getDisplayName(), messagesViewer);
|
||||||
|
tabPane.add(callLogViewer.getDisplayName(), callLogViewer);
|
||||||
tabPane.add(contactsViewer.getDisplayName(), contactsViewer);
|
tabPane.add(contactsViewer.getDisplayName(), contactsViewer);
|
||||||
tabPane.add(mediaViewer.getDisplayName(), mediaViewer);
|
tabPane.add(mediaViewer.getDisplayName(), mediaViewer);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.sleuthkit.autopsy.communications.relationships;
|
||||||
|
|
||||||
|
import java.util.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of reusable utility functions for the Relationships package.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* 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 "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -118,19 +118,13 @@ final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
|||||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||||
|
|
||||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
|
||||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
|| 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
|
// 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
|
// To achive this assign any artifact that does not have a threadID
|
||||||
// the "UNTHREADED_ID"
|
// the "UNTHREADED_ID"
|
||||||
// All call logs will default to a single call logs thread
|
String threadID = MessageNode.UNTHREADED_ID;
|
||||||
String threadID;
|
|
||||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) {
|
|
||||||
threadID = MessageNode.CALL_LOG_ID;
|
|
||||||
} else {
|
|
||||||
threadID = MessageNode.UNTHREADED_ID;
|
|
||||||
}
|
|
||||||
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||||
|
|
||||||
if(attribute != null) {
|
if(attribute != null) {
|
||||||
@ -201,44 +195,11 @@ final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
|||||||
|
|
||||||
if (attribute != null) {
|
if (attribute != null) {
|
||||||
return new ThreadNode(bba, attribute.getValueString(), preferredAction);
|
return new ThreadNode(bba, attribute.getValueString(), preferredAction);
|
||||||
} else {
|
|
||||||
if (bba.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) {
|
|
||||||
return new CallLogNode();
|
|
||||||
} else {
|
} else {
|
||||||
// Only one of these should occur.
|
// Only one of these should occur.
|
||||||
return new UnthreadedNode();
|
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.
|
* This node represents the "unthreaded" thread.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user