mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 19:14: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
|
||||
ContactNode_Email=Email Address
|
||||
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;
|
||||
|
||||
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 = "<UNTHREADED>";
|
||||
public static final String CALL_LOG_ID = "<CALLLOG>";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -90,8 +90,7 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
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;
|
||||
}
|
||||
@ -100,12 +99,8 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
// 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) {
|
||||
@ -114,8 +109,7 @@ public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
|
||||
if(threadIDs == null || threadIDs.contains(artifactThreadID)) {
|
||||
list.add(bba);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
<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"/>
|
||||
|
@ -30,12 +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 ModifiableProxyLookup proxyLookup;
|
||||
|
||||
/**
|
||||
@ -43,15 +37,18 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
*/
|
||||
public RelationshipBrowser() {
|
||||
initComponents();
|
||||
messagesViewer = new MessageViewer();
|
||||
contactsViewer = new ContactsViewer();
|
||||
summaryViewer = new SummaryViewer();
|
||||
mediaViewer = new MediaViewer();
|
||||
|
||||
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());
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
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
|
||||
// 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) {
|
||||
@ -202,44 +196,11 @@ final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
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.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user