19 package org.sleuthkit.autopsy.contentviewers.artifactviewers;
21 import java.awt.Component;
22 import java.awt.GridBagConstraints;
23 import java.awt.GridBagLayout;
24 import java.awt.Insets;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
31 import java.util.Optional;
33 import java.util.logging.Level;
34 import javax.swing.JScrollPane;
35 import javax.swing.border.EmptyBorder;
36 import org.apache.commons.lang3.ObjectUtils;
37 import org.apache.commons.lang3.StringUtils;
38 import org.openide.util.NbBundle;
39 import org.openide.util.lookup.ServiceProvider;
57 @ServiceProvider(service = ArtifactContentViewer.class)
61 private static final long serialVersionUID = 1L;
63 private static final Set<Integer> HANDLED_ATTRIBUTE_TYPES =
new HashSet<Integer>(Arrays.asList(
64 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(),
65 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO.getTypeID(),
66 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM.getTypeID(),
67 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID.getTypeID(),
68 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(),
69 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
70 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(),
71 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()
74 private GridBagLayout m_gridBagLayout =
new GridBagLayout();
75 private GridBagConstraints m_constraints =
new GridBagConstraints();
77 private PersonaAccountFetcher currentAccountFetcher = null;
92 @SuppressWarnings(
"unchecked")
94 private
void initComponents() {
96 setLayout(
new java.awt.GridBagLayout());
103 CallLogViewData callLogViewData = null;
105 callLogViewData = getCallLogViewData(artifact);
107 logger.log(Level.SEVERE, String.format(
"Error getting attributes for Calllog artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
109 List<AccountPersonaSearcherData> personaSearchDataList =
new ArrayList<>();
111 if (callLogViewData != null) {
112 personaSearchDataList.addAll(updateView(callLogViewData));
115 if (!personaSearchDataList.isEmpty()) {
116 currentAccountFetcher =
new PersonaAccountFetcher(artifact, personaSearchDataList,
this);
117 currentAccountFetcher.execute();
119 currentAccountFetcher = null;
138 if (artifact == null) {
142 BlackboardAttribute directionAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION));
143 BlackboardAttribute toAccountAttr = null;
144 BlackboardAttribute fromAccountAttr = null;
145 BlackboardAttribute localAccountAttr = null;
147 CallLogViewData callLogViewData = null;
149 String direction = null;
150 String fromAccountIdentifier = null;
151 String toAccountIdentifier = null;
152 List<String> otherParties = null;
153 List<String> toContactNames = null;
154 List<String> fromContactNames = null;
156 Content dataSource = artifact.getDataSource();
157 String deviceId = ((DataSource) dataSource).getDeviceId();
159 if (directionAttr != null) {
160 direction = directionAttr.getValueString();
161 if (direction.equalsIgnoreCase(
"Incoming")) {
162 fromAccountAttr = ObjectUtils.firstNonNull(
163 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)),
164 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)),
165 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID))
168 toAccountAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO));
169 localAccountAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO));
170 }
else if (direction.equalsIgnoreCase(
"Outgoing")) {
171 toAccountAttr = ObjectUtils.firstNonNull(
172 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)),
173 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)),
174 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID))
177 fromAccountAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM));
178 localAccountAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM));
183 if (fromAccountAttr == null) {
184 fromAccountAttr = ObjectUtils.firstNonNull(
185 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)),
186 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)),
187 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)),
188 artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID))
194 if (fromAccountAttr != null) {
195 String fromAccountAttrValue = fromAccountAttr.getValueString();
196 if (fromAccountAttrValue.equalsIgnoreCase(deviceId) ==
false) {
197 fromAccountIdentifier = fromAccountAttrValue;
202 if (toAccountAttr != null) {
204 String[] numbers = toAccountAttr.getValueString().split(
",");
205 String toAccountAttrValue = StringUtils.trim(numbers[0]);
206 if (toAccountAttrValue.equalsIgnoreCase(deviceId) ==
false) {
207 toAccountIdentifier = toAccountAttrValue;
213 if (numbers.length > 1) {
214 otherParties =
new ArrayList<>();
215 for (
int i = 1; i < numbers.length; i++) {
216 otherParties.add(StringUtils.trim(numbers[i]));
222 if (null != fromAccountAttr || null != toAccountAttr) {
223 callLogViewData =
new CallLogViewData(fromAccountIdentifier, toAccountIdentifier);
224 callLogViewData.setDirection(direction);
226 callLogViewData.setOtherParties(otherParties);
228 extractTimeAndDuration(artifact, callLogViewData);
230 callLogViewData.setDataSourceName(dataSource.getName());
233 if (localAccountAttr != null) {
234 String attrValue = localAccountAttr.getValueString();
236 if (attrValue.equalsIgnoreCase(deviceId) ==
false && attrValue.contains(
",") ==
false) {
237 callLogViewData.setLocalAccountId(attrValue);
241 callLogViewData.setOtherAttributes(extractOtherAttributes(artifact));
243 callLogViewData.setFromContactNameList(fromContactNames);
244 callLogViewData.setToContactNameList(toContactNames);
247 .map(h -> h.getName())
250 callLogViewData.setHostName(hostName);
253 return callLogViewData;
266 private void extractTimeAndDuration(BlackboardArtifact artifact, CallLogViewData callLogViewData)
throws TskCoreException {
268 BlackboardAttribute startTimeAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
269 if (startTimeAttr == null) {
270 startTimeAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
272 if (startTimeAttr != null) {
273 long startTime = startTimeAttr.getValueLong();
274 callLogViewData.setDateTimeStr(startTimeAttr.getDisplayString());
276 BlackboardAttribute endTimeAttr = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END));
277 if (endTimeAttr != null) {
278 long endTime = endTimeAttr.getValueLong();
279 if (endTime > 0 && (endTime - startTime) > 0) {
280 callLogViewData.setDuration(String.format(
"%d seconds", (endTime - startTime)));
297 List<BlackboardAttribute> attributes = artifact.getAttributes();
298 Map<String, String> otherAttributes =
new HashMap<>();
300 for (BlackboardAttribute attr : attributes) {
301 if (HANDLED_ATTRIBUTE_TYPES.contains(attr.getAttributeType().getTypeID()) ==
false) {
302 otherAttributes.put(attr.getAttributeType().getDisplayName(), attr.getDisplayString());
306 return otherAttributes;
317 "CallLogArtifactViewer_heading_parties=Parties",
318 "CallLogArtifactViewer_value_unknown=Unknown",
319 "CallLogArtifactViewer_label_from=From",
320 "CallLogArtifactViewer_label_to=To"
322 private List<AccountPersonaSearcherData>
updateView(CallLogViewData callLogViewData) {
324 CommunicationArtifactViewerHelper.addHeader(
this, m_gridBagLayout, this.m_constraints, 0, Bundle.CallLogArtifactViewer_heading_parties());
326 List<AccountPersonaSearcherData> dataList =
new ArrayList<>();
328 if (callLogViewData.getFromAccount() != null) {
329 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_from());
332 String accountDisplayString = getAccountDisplayString(callLogViewData.getFromAccount(), callLogViewData);
333 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, accountDisplayString);
335 List<String> contactNames = callLogViewData.getFromContactNameList();
336 for (String name : contactNames) {
337 CommunicationArtifactViewerHelper.addContactRow(
this, m_gridBagLayout, m_constraints, name);
341 dataList.addAll(CommunicationArtifactViewerHelper.addPersonaRow(
this, m_gridBagLayout,
this.m_constraints, callLogViewData.getFromAccount()));
345 if (callLogViewData.getToAccount() != null) {
346 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_to());
347 String accountDisplayString = getAccountDisplayString(callLogViewData.getToAccount(), callLogViewData);
348 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, accountDisplayString);
350 List<String> contactNames = callLogViewData.getToContactNameList();
351 for (String name : contactNames) {
352 CommunicationArtifactViewerHelper.addContactRow(
this, m_gridBagLayout, m_constraints, name);
355 dataList.addAll(CommunicationArtifactViewerHelper.addPersonaRow(
this, m_gridBagLayout,
this.m_constraints, callLogViewData.getToAccount()));
360 for (String otherParty : callLogViewData.getOtherParties()) {
361 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_to());
362 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, otherParty);
364 dataList.addAll(CommunicationArtifactViewerHelper.addPersonaRow(
this, m_gridBagLayout,
this.m_constraints, otherParty));
367 updateMetadataView(callLogViewData);
369 updateOtherAttributesView(callLogViewData);
371 updateSourceView(callLogViewData);
374 showCRDisabledMessage();
377 CommunicationArtifactViewerHelper.addPageEndGlue(
this, m_gridBagLayout, this.m_constraints);
379 this.setLayout(m_gridBagLayout);
390 "CallLogArtifactViewer_heading_metadata=Metadata",
391 "CallLogArtifactViewer_label_direction=Direction",
392 "CallLogArtifactViewer_label_date=Date",
393 "CallLogArtifactViewer_label_duration=Duration"
399 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_direction());
400 if (callLogViewData.getDirection() != null) {
401 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, callLogViewData.getDirection());
403 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_value_unknown());
406 if (callLogViewData.getDateTimeStr() != null) {
407 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_date());
408 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, callLogViewData.getDateTimeStr());
411 if (callLogViewData.getDuration() != null) {
412 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_duration());
413 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, callLogViewData.getDuration());
424 "CallLogArtifactViewer_heading_Source=Source",
425 "CallLogArtifactViewer_label_datasource=Data Source",
426 "CallLogArtifactViewer_label_hostName=Host"})
430 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_hostName());
431 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, StringUtils.defaultString(callLogViewData.getHostName()));
433 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_datasource());
434 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, callLogViewData.getDataSourceName());
443 "CallLogArtifactViewer_heading_others=Other Attributes"
447 if (callLogViewData.getOtherAttributes().isEmpty()) {
452 for (Map.Entry<String, String> entry : callLogViewData.getOtherAttributes().entrySet()) {
453 CommunicationArtifactViewerHelper.addKey(
this, m_gridBagLayout, this.m_constraints, entry.getKey());
454 CommunicationArtifactViewerHelper.addValue(
this, m_gridBagLayout, this.m_constraints, entry.getValue());
459 "CalllogArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas."
463 CommunicationArtifactViewerHelper.addMessageRow(
this, m_gridBagLayout, messageInsets, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message());
464 m_constraints.gridy++;
478 "CallLogArtifactViewer_suffix_local=(Local)",})
480 String accountDisplayValue = accountIdentifier;
481 if (callLogViewDataNew.getLocalAccountId() != null && callLogViewDataNew.getLocalAccountId().equalsIgnoreCase(accountIdentifier)) {
482 accountDisplayValue +=
" " + Bundle.CallLogArtifactViewer_suffix_local();
484 return accountDisplayValue;
489 return new JScrollPane(
this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
495 return (artifact != null)
496 && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID());
505 if (currentAccountFetcher != null && !currentAccountFetcher.isDone()) {
506 currentAccountFetcher.cancel(
true);
507 currentAccountFetcher = null;
512 this.setLayout(null);
514 m_gridBagLayout =
new GridBagLayout();
515 m_constraints =
new GridBagConstraints();
517 m_constraints.anchor = GridBagConstraints.FIRST_LINE_START;
518 m_constraints.gridy = 0;
519 m_constraints.gridx = 0;
520 m_constraints.weighty = 0.0;
521 m_constraints.weightx = 0.0;
523 m_constraints.fill = GridBagConstraints.NONE;
boolean isSupported(BlackboardArtifact artifact)
CallLogViewData getCallLogViewData(BlackboardArtifact artifact)
static Integer getLineSpacing()
void extractTimeAndDuration(BlackboardArtifact artifact, CallLogViewData callLogViewData)
static Insets getPanelInsets()
static Integer getSectionIndent()
void updateMetadataView(CallLogViewData callLogViewData)
List< AccountPersonaSearcherData > updateView(CallLogViewData callLogViewData)
void updateSourceView(CallLogViewData callLogViewData)
String getAccountDisplayString(String accountIdentifier, CallLogViewData callLogViewDataNew)
SleuthkitCase getSleuthkitCase()
void showCRDisabledMessage()
void updateOtherAttributesView(CallLogViewData callLogViewData)
Map< String, String > extractOtherAttributes(BlackboardArtifact artifact)
void setArtifact(BlackboardArtifact artifact)
static Integer getSectionSpacing()
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
static boolean isEnabled()