Sleuth Kit Java Bindings (JNI)  4.11.0
Java bindings for using The Sleuth Kit
CommunicationArtifactsHelper.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2019-2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.datamodel.blackboardutils;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 import org.apache.commons.lang3.StringUtils;
49 
70 public final class CommunicationArtifactsHelper extends ArtifactHelperBase {
71 
72  private static final Logger LOGGER = Logger.getLogger(CommunicationArtifactsHelper.class.getName());
73 
74  private static final BlackboardArtifact.Type CONTACT_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_CONTACT);
75  private static final BlackboardArtifact.Type MESSAGE_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_MESSAGE);
76  private static final BlackboardArtifact.Type CALLOG_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_CALLLOG);
77  private static final BlackboardArtifact.Type ASSOCIATED_OBJ_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
78 
82  public enum MessageReadStatus {
83 
84  UNKNOWN("Unknown"),
85  UNREAD("Unread"),
86  READ("Read");
87 
88  private final String msgReadStr;
89 
90  MessageReadStatus(String readStatus) {
91  this.msgReadStr = readStatus;
92  }
93 
94  public String getDisplayName() {
95  return msgReadStr;
96  }
97  }
98 
103  UNKNOWN("Unknown"),
104  INCOMING("Incoming"),
105  OUTGOING("Outgoing");
106 
107  private final String dirStr;
108 
110  this.dirStr = dir;
111  }
112 
113  public String getDisplayName() {
114  return dirStr;
115  }
116  }
117 
121  public enum CallMediaType {
122  UNKNOWN("Unknown"),
123  AUDIO("Audio"), // Audio only call
124  VIDEO("Video"); // Video/multimedia call
125 
126  private final String typeStr;
127 
128  CallMediaType(String type) {
129  this.typeStr = type;
130  }
131 
132  public String getDisplayName() {
133  return typeStr;
134  }
135  }
136 
137  private static final BlackboardAttribute.Type ATTACHMENTS_ATTR_TYPE = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS);
138 
139  // 'self' account for the application being processed by the module.
140  private final Account.Type selfAccountType;
141  private final String selfAccountId;
142 
143  private AccountFileInstance selfAccountInstance = null;
144 
145  // Type of accounts to be created for the module using this helper.
146  private final Account.Type moduleAccountsType;
147 
166  String moduleName, Content srcContent, Account.Type accountsType) throws TskCoreException {
167 
168  super(caseDb, moduleName, srcContent);
169 
170  this.moduleAccountsType = accountsType;
171  this.selfAccountType = Account.Type.DEVICE;
172  this.selfAccountId = ((DataSource) getContent().getDataSource()).getDeviceId();
173  }
174 
194  public CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId) throws TskCoreException {
195 
196  super(caseDb, moduleName, srcContent);
197 
198  this.moduleAccountsType = accountsType;
199  this.selfAccountType = selfAccountType;
200  this.selfAccountId = selfAccountId;
201  }
202 
224  public BlackboardArtifact addContact(String contactName,
225  String phoneNumber, String homePhoneNumber,
226  String mobilePhoneNumber, String emailAddr) throws TskCoreException, BlackboardException {
227  return addContact(contactName, phoneNumber,
228  homePhoneNumber, mobilePhoneNumber, emailAddr,
229  Collections.emptyList());
230  }
231 
257  public BlackboardArtifact addContact(String contactName,
258  String phoneNumber, String homePhoneNumber,
259  String mobilePhoneNumber, String emailAddr,
260  Collection<BlackboardAttribute> additionalAttributes) throws TskCoreException, BlackboardException {
261 
262  // check if the caller has included any phone/email/id in addtional attributes
263  boolean hasAnyIdAttribute = false;
264  if (additionalAttributes != null) {
265  for (BlackboardAttribute attr : additionalAttributes) {
266  if ((attr.getAttributeType().getTypeName().startsWith("TSK_PHONE"))
267  || (attr.getAttributeType().getTypeName().startsWith("TSK_EMAIL"))
268  || (attr.getAttributeType().getTypeName().startsWith("TSK_ID"))) {
269  hasAnyIdAttribute = true;
270  break;
271  }
272  }
273  }
274 
275  // At least one phone number or email address
276  // or an optional attribute with phone/email/id must be provided
277  if (StringUtils.isEmpty(phoneNumber) && StringUtils.isEmpty(homePhoneNumber)
278  && StringUtils.isEmpty(mobilePhoneNumber) && StringUtils.isEmpty(emailAddr)
279  && (!hasAnyIdAttribute)) {
280  throw new IllegalArgumentException("At least one phone number or email address or an id must be provided.");
281  }
282 
283  BlackboardArtifact contactArtifact;
284  Collection<BlackboardAttribute> attributes = new ArrayList<>();
285 
286  // create TSK_CONTACT artifact and construct attributes
287  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_NAME, contactName, attributes);
288 
289  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, phoneNumber, attributes);
290  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME, homePhoneNumber, attributes);
291  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE, mobilePhoneNumber, attributes);
292  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_EMAIL, emailAddr, attributes);
293 
294  // add attributes
295  attributes.addAll(additionalAttributes);
296  Content content = getContent();
297 
298  contactArtifact = content.newDataArtifact(CONTACT_TYPE, attributes);
299 
300  // create an account for each specified contact method, and a relationship with self account
301  createContactMethodAccountAndRelationship(Account.Type.PHONE, phoneNumber, contactArtifact, 0);
302  createContactMethodAccountAndRelationship(Account.Type.PHONE, homePhoneNumber, contactArtifact, 0);
303  createContactMethodAccountAndRelationship(Account.Type.PHONE, mobilePhoneNumber, contactArtifact, 0);
304  createContactMethodAccountAndRelationship(Account.Type.EMAIL, emailAddr, contactArtifact, 0);
305 
306  // if the additional attribute list has any phone/email/id attributes, create accounts & relationships for those.
307  if ((additionalAttributes != null) && hasAnyIdAttribute) {
308  for (BlackboardAttribute bba : additionalAttributes) {
309  if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) {
310  createContactMethodAccountAndRelationship(Account.Type.PHONE, bba.getValueString(), contactArtifact, 0);
311  } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) {
312  createContactMethodAccountAndRelationship(Account.Type.EMAIL, bba.getValueString(), contactArtifact, 0);
313  } else if (bba.getAttributeType().getTypeName().startsWith("TSK_ID")) {
314  createContactMethodAccountAndRelationship(this.moduleAccountsType, bba.getValueString(), contactArtifact, 0);
315  }
316  }
317  }
318 
319  // post artifact
320  getSleuthkitCase().getBlackboard().postArtifact(contactArtifact, getModuleName());
321 
322  return contactArtifact;
323  }
324 
333  private void createContactMethodAccountAndRelationship(Account.Type accountType,
334  String accountUniqueID, BlackboardArtifact sourceArtifact,
335  long dateTime) throws TskCoreException {
336 
337  // Find/Create an account instance for each of the contact method
338  // Create a relationship between selfAccount and contactAccount
339  if (StringUtils.isNotBlank(accountUniqueID)) {
340  try {
341  AccountFileInstance contactAccountInstance = createAccountInstance(accountType, accountUniqueID);
342 
343  // Create a relationship between self account and the contact account
344  try {
345  getSleuthkitCase().getCommunicationsManager().addRelationships(getSelfAccountInstance(),
346  Collections.singletonList(contactAccountInstance), sourceArtifact, Relationship.Type.CONTACT, dateTime);
347  } catch (TskDataException ex) {
348  throw new TskCoreException(String.format("Failed to create relationship between account = %s and account = %s.",
349  getSelfAccountInstance().getAccount(), contactAccountInstance.getAccount()), ex);
350  }
351  } catch (InvalidAccountIDException ex) {
352  LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", accountUniqueID));
353  }
354  }
355  }
356 
369  private AccountFileInstance createAccountInstance(Account.Type accountType, String accountUniqueID) throws TskCoreException, InvalidAccountIDException {
370  return getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(accountType, accountUniqueID, getModuleName(), getContent());
371  }
372 
395  String messageType,
396  CommunicationDirection direction,
397  String senderId,
398  String recipientId,
399  long dateTime, MessageReadStatus readStatus,
400  String subject, String messageText, String threadId) throws TskCoreException, BlackboardException {
401  return addMessage(messageType, direction,
402  senderId, recipientId, dateTime, readStatus,
403  subject, messageText, threadId,
404  Collections.emptyList());
405  }
406 
429  public BlackboardArtifact addMessage(String messageType,
430  CommunicationDirection direction,
431  String senderId,
432  String recipientId,
433  long dateTime, MessageReadStatus readStatus, String subject,
434  String messageText, String threadId,
435  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
436 
437  return addMessage(messageType, direction,
438  senderId,
439  Arrays.asList(recipientId),
440  dateTime, readStatus,
441  subject, messageText, threadId,
442  otherAttributesList);
443  }
444 
467  public BlackboardArtifact addMessage(String messageType,
468  CommunicationDirection direction,
469  String senderId,
470  List<String> recipientIdsList,
471  long dateTime, MessageReadStatus readStatus,
472  String subject, String messageText, String threadId) throws TskCoreException, BlackboardException {
473  return addMessage(messageType, direction,
474  senderId, recipientIdsList,
475  dateTime, readStatus,
476  subject, messageText, threadId,
477  Collections.emptyList());
478  }
479 
502  public BlackboardArtifact addMessage(String messageType,
503  CommunicationDirection direction,
504  String senderId,
505  List<String> recipientIdsList,
506  long dateTime, MessageReadStatus readStatus,
507  String subject, String messageText,
508  String threadId,
509  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
510 
511  // Created message artifact.
512  Collection<BlackboardAttribute> attributes = new ArrayList<>();
513 
514  // construct attributes
515  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, getModuleName(), messageType));
516  addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME, dateTime, attributes);
517 
518  addMessageReadStatusIfKnown(readStatus, attributes);
519  addCommDirectionIfKnown(direction, attributes);
520 
521  // Get the self account instance
522  AccountFileInstance selfAccountInstanceLocal = null;
523  try {
524  selfAccountInstanceLocal = getSelfAccountInstance();
525  } catch (InvalidAccountIDException ex) {
526  LOGGER.log(Level.WARNING, String.format("Failed to get/create self account with id %s", selfAccountId), ex);
527  }
528 
529  // set sender attribute and create sender account
530  AccountFileInstance senderAccountInstance = null;
531  if (StringUtils.isNotBlank(senderId)) {
532  try {
533  senderAccountInstance = createAccountInstance(moduleAccountsType, senderId);
534  } catch (InvalidAccountIDException ex) {
535  LOGGER.log(Level.WARNING, String.format("Invalid account identifier %s", senderId));
536  }
537  }
538 
539  // set recipient attribute and create recipient accounts
540  List<AccountFileInstance> recipientAccountsList = new ArrayList<>();
541  String recipientsStr = "";
542  if (!isEffectivelyEmpty(recipientIdsList)) {
543  for (String recipient : recipientIdsList) {
544  if (StringUtils.isNotBlank(recipient)) {
545  try {
546  recipientAccountsList.add(createAccountInstance(moduleAccountsType, recipient));
547  } catch (InvalidAccountIDException ex) {
548  LOGGER.log(Level.WARNING, String.format("Invalid account identifier %s", recipient));
549  }
550  }
551  }
552  // Create a comma separated string of recipients
553  recipientsStr = addressListToString(recipientIdsList);
554  }
555 
556  switch (direction) {
557  case OUTGOING:
558  // if no sender, selfAccount substitutes caller.
559  if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
560  senderAccountInstance = selfAccountInstanceLocal;
561  }
562  // sender becomes PHONE_FROM
563  if (senderAccountInstance != null) {
564  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
565  }
566  // recipient becomes PHONE_TO
567  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, recipientsStr, attributes);
568  break;
569 
570  case INCOMING:
571  // if no recipeint specified, selfAccount substitutes recipient
572  if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
573  recipientsStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
574  recipientAccountsList.add(selfAccountInstanceLocal);
575  }
576  // caller becomes PHONE_FROM
577  if (senderAccountInstance != null) {
578  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
579  }
580  // callee becomes PHONE_TO
581  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, recipientsStr, attributes);
582  break;
583  default: // direction UNKNOWN
584  if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
585  // if no sender, selfAccount substitutes caller.
586  senderAccountInstance = selfAccountInstanceLocal;
587  } else if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
588  // else if no recipient specified, selfAccount substitutes recipient
589  recipientsStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
590  recipientAccountsList.add(selfAccountInstanceLocal);
591  }
592 
593  // save phone numbers in direction agnostic attributes
594  if (senderAccountInstance != null) {
595  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
596  } // callee becomes PHONE_TO
597  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, recipientsStr, attributes);
598  break;
599  }
600 
601  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_SUBJECT, subject, attributes);
602  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_TEXT, messageText, attributes);
603  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_THREAD_ID, threadId, attributes);
604 
605  // add attributes to artifact
606  attributes.addAll(otherAttributesList);
607 
608  // create TSK_MESSAGE artifact
609  Content content = getContent();
610  BlackboardArtifact msgArtifact = content.newDataArtifact(MESSAGE_TYPE, attributes);
611 
612  // create sender/recipient relationships
613  try {
614  getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance,
615  recipientAccountsList, msgArtifact, Relationship.Type.MESSAGE, dateTime);
616  } catch (TskDataException ex) {
617  throw new TskCoreException(String.format("Failed to create Message relationships between sender account = %s and recipients = %s.",
618  (senderAccountInstance != null) ? senderAccountInstance.getAccount().getTypeSpecificID() : "Unknown", recipientsStr), ex);
619  }
620 
621  // post artifact
622  getSleuthkitCase().getBlackboard().postArtifact(msgArtifact, getModuleName());
623 
624  // return the artifact
625  return msgArtifact;
626  }
627 
651  String callerId, String calleeId,
652  long startDateTime, long endDateTime, CallMediaType mediaType) throws TskCoreException, BlackboardException {
653  return addCalllog(direction, callerId, calleeId,
654  startDateTime, endDateTime, mediaType,
655  Collections.emptyList());
656  }
657 
682  String callerId,
683  String calleeId,
684  long startDateTime, long endDateTime,
685  CallMediaType mediaType,
686  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
687  return addCalllog(direction,
688  callerId,
689  Arrays.asList(calleeId),
690  startDateTime, endDateTime,
691  mediaType,
692  otherAttributesList);
693  }
694 
718  String callerId,
719  Collection<String> calleeIdsList,
720  long startDateTime, long endDateTime,
721  CallMediaType mediaType) throws TskCoreException, BlackboardException {
722 
723  return addCalllog(direction, callerId, calleeIdsList,
724  startDateTime, endDateTime,
725  mediaType,
726  Collections.emptyList());
727  }
728 
753  String callerId,
754  Collection<String> calleeIdsList,
755  long startDateTime, long endDateTime,
756  CallMediaType mediaType,
757  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
758 
759  // Either caller id or a callee id must be provided.
760  if (StringUtils.isEmpty(callerId) && (isEffectivelyEmpty(calleeIdsList))) {
761  throw new IllegalArgumentException("Either a caller id, or at least one callee id must be provided for a call log.");
762  }
763 
764  AccountFileInstance selfAccountInstanceLocal = null;
765  try {
766  selfAccountInstanceLocal = getSelfAccountInstance();
767  } catch (InvalidAccountIDException ex) {
768  LOGGER.log(Level.WARNING, String.format("Failed to get/create self account with id %s", selfAccountId), ex);
769  }
770 
771  Collection<BlackboardAttribute> attributes = new ArrayList<>();
772 
773  // Add basic attributes
774  addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME_START, startDateTime, attributes);
775  addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME_END, endDateTime, attributes);
776  addCommDirectionIfKnown(direction, attributes);
777 
778  AccountFileInstance callerAccountInstance = null;
779  if (StringUtils.isNotBlank(callerId)) {
780  try {
781  callerAccountInstance = createAccountInstance(moduleAccountsType, callerId);
782  } catch (InvalidAccountIDException ex) {
783  LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", callerId));
784  }
785  }
786 
787  // Create a comma separated string of callee
788  List<AccountFileInstance> recipientAccountsList = new ArrayList<>();
789  String calleesStr = "";
790  if (!isEffectivelyEmpty(calleeIdsList)) {
791  calleesStr = addressListToString(calleeIdsList);
792  for (String callee : calleeIdsList) {
793  if (StringUtils.isNotBlank(callee)) {
794  try {
795  recipientAccountsList.add(createAccountInstance(moduleAccountsType, callee));
796  } catch (InvalidAccountIDException ex) {
797  LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", callee));
798  }
799  }
800  }
801  }
802 
803  switch (direction) {
804  case OUTGOING:
805  // if no callee throw IllegalArg
806  if (isEffectivelyEmpty(calleeIdsList)) {
807  throw new IllegalArgumentException("Callee not provided for an outgoing call.");
808  }
809  // if no caller, selfAccount substitutes caller.
810  if (StringUtils.isEmpty(callerId) && selfAccountInstanceLocal != null) {
811  callerAccountInstance = selfAccountInstanceLocal;
812  }
813  // caller becomes PHONE_FROM
814  if (callerAccountInstance != null) {
815  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
816  }
817  // callee becomes PHONE_TO
818  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, calleesStr, attributes);
819  break;
820 
821  case INCOMING:
822  // if no caller throw IllegalArg
823  if (StringUtils.isEmpty(callerId)) {
824  throw new IllegalArgumentException("Caller Id not provided for incoming call.");
825  }
826  // if no callee specified, selfAccount substitutes callee
827  if (isEffectivelyEmpty(calleeIdsList) && selfAccountInstanceLocal != null) {
828  calleesStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
829  recipientAccountsList.add(selfAccountInstanceLocal);
830  }
831  // caller becomes PHONE_FROM
832  if (callerAccountInstance != null) {
833  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
834  }
835  // callee becomes PHONE_TO
836  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, calleesStr, attributes);
837  break;
838  default: // direction UNKNOWN
839 
840  // save phone numbers in direction agnostic attributes
841  if (callerAccountInstance != null) {
842  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
843  } // callee becomes PHONE_TO
844  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, calleesStr, attributes);
845  break;
846  }
847 
848  // add attributes to artifact
849  attributes.addAll(otherAttributesList);
850  // Create TSK_CALLLOG artifact
851  Content content = getContent();
852  BlackboardArtifact callLogArtifact = content.newDataArtifact(CALLOG_TYPE, attributes);
853 
854  callLogArtifact.addAttributes(attributes);
855 
856  // create relationships between caller/callees
857  try {
858  getSleuthkitCase().getCommunicationsManager().addRelationships(callerAccountInstance,
859  recipientAccountsList, callLogArtifact, Relationship.Type.CALL_LOG, startDateTime);
860  } catch (TskDataException ex) {
861  throw new TskCoreException(String.format("Failed to create Call log relationships between caller account = %s and callees = %s.",
862  (callerAccountInstance != null) ? callerAccountInstance.getAccount() : "", calleesStr), ex);
863  }
864 
865  // post artifact
866  getSleuthkitCase().getBlackboard().postArtifact(callLogArtifact, getModuleName());
867 
868  // return the artifact
869  return callLogArtifact;
870  }
871 
880  public void addAttachments(BlackboardArtifact message, MessageAttachments attachments) throws TskCoreException {
881  // Create attribute
882  BlackboardAttribute blackboardAttribute = BlackboardJsonAttrUtil.toAttribute(ATTACHMENTS_ATTR_TYPE, getModuleName(), attachments);
883  message.addAttribute(blackboardAttribute);
884 
885  // Associate each attachment file with the message.
886  Collection<FileAttachment> fileAttachments = attachments.getFileAttachments();
887  for (FileAttachment fileAttachment : fileAttachments) {
888  long attachedFileObjId = fileAttachment.getObjectId();
889  if (attachedFileObjId >= 0) {
890  AbstractFile attachedFile = message.getSleuthkitCase().getAbstractFileById(attachedFileObjId);
891  associateAttachmentWithMessage(message, attachedFile);
892  }
893  }
894  }
895 
908  private BlackboardArtifact associateAttachmentWithMessage(BlackboardArtifact message, AbstractFile attachedFile) throws TskCoreException {
909  Collection<BlackboardAttribute> attributes = new ArrayList<>();
910  attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, this.getModuleName(), message.getArtifactID()));
911 
912  return attachedFile.newDataArtifact(ASSOCIATED_OBJ_TYPE, attributes);
913  }
914 
918  private String addressListToString(Collection<String> addressList) {
919 
920  String toAddresses = "";
921  if (addressList != null && (!addressList.isEmpty())) {
922  StringBuilder toAddressesSb = new StringBuilder();
923  for (String address : addressList) {
924  if (!StringUtils.isEmpty(address)) {
925  toAddressesSb = toAddressesSb.length() > 0 ? toAddressesSb.append(", ").append(address) : toAddressesSb.append(address);
926  }
927  }
928  toAddresses = toAddressesSb.toString();
929  }
930 
931  return toAddresses;
932  }
933 
943  private boolean isEffectivelyEmpty(Collection<String> idList) {
944 
945  if (idList == null || idList.isEmpty()) {
946  return true;
947  }
948 
949  for (String id : idList) {
950  if (!StringUtils.isEmpty(id)) {
951  return false;
952  }
953  }
954 
955  return true;
956 
957  }
958 
962  private void addCommDirectionIfKnown(CommunicationDirection direction, Collection<BlackboardAttribute> attributes) {
963  if (direction != CommunicationDirection.UNKNOWN) {
964  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, getModuleName(), direction.getDisplayName()));
965  }
966  }
967 
971  private void addMessageReadStatusIfKnown(MessageReadStatus readStatus, Collection<BlackboardAttribute> attributes) {
972  if (readStatus != MessageReadStatus.UNKNOWN) {
973  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_READ_STATUS, getModuleName(), (readStatus == MessageReadStatus.READ) ? 1 : 0));
974  }
975  }
976 
985  private synchronized AccountFileInstance getSelfAccountInstance() throws TskCoreException, InvalidAccountIDException {
986  if (selfAccountInstance == null) {
987  selfAccountInstance = getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(selfAccountType, selfAccountId, this.getModuleName(), getContent());
988  }
989  return selfAccountInstance;
990  }
991 }
static< T > BlackboardAttribute toAttribute(BlackboardAttribute.Type attrType, String moduleName, T attrValue)
BlackboardArtifact addMessage(String messageType, CommunicationDirection direction, String senderId, List< String > recipientIdsList, long dateTime, MessageReadStatus readStatus, String subject, String messageText, String threadId, Collection< BlackboardAttribute > otherAttributesList)
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributesList, Long osAccountId)
BlackboardArtifact addContact(String contactName, String phoneNumber, String homePhoneNumber, String mobilePhoneNumber, String emailAddr)
void addAttributes(Collection< BlackboardAttribute > attributes)
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType)
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributesList)
BlackboardArtifact addContact(String contactName, String phoneNumber, String homePhoneNumber, String mobilePhoneNumber, String emailAddr, Collection< BlackboardAttribute > additionalAttributes)
static final Account.Type PHONE
Definition: Account.java:49
BlackboardArtifact addMessage(String messageType, CommunicationDirection direction, String senderId, String recipientId, long dateTime, MessageReadStatus readStatus, String subject, String messageText, String threadId)
BlackboardArtifact addMessage(String messageType, CommunicationDirection direction, String senderId, String recipientId, long dateTime, MessageReadStatus readStatus, String subject, String messageText, String threadId, Collection< BlackboardAttribute > otherAttributesList)
static final Relationship.Type CALL_LOG
BlackboardArtifact addCalllog(CommunicationDirection direction, String callerId, Collection< String > calleeIdsList, long startDateTime, long endDateTime, CallMediaType mediaType, Collection< BlackboardAttribute > otherAttributesList)
BlackboardArtifact addCalllog(CommunicationDirection direction, String callerId, Collection< String > calleeIdsList, long startDateTime, long endDateTime, CallMediaType mediaType)
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId)
BlackboardArtifact addCalllog(CommunicationDirection direction, String callerId, String calleeId, long startDateTime, long endDateTime, CallMediaType mediaType, Collection< BlackboardAttribute > otherAttributesList)
static final Account.Type DEVICE
Definition: Account.java:48
static final Relationship.Type MESSAGE
BlackboardArtifact addMessage(String messageType, CommunicationDirection direction, String senderId, List< String > recipientIdsList, long dateTime, MessageReadStatus readStatus, String subject, String messageText, String threadId)
static final Relationship.Type CONTACT
BlackboardArtifact addCalllog(CommunicationDirection direction, String callerId, String calleeId, long startDateTime, long endDateTime, CallMediaType mediaType)
void addAttachments(BlackboardArtifact message, MessageAttachments attachments)
static final Account.Type EMAIL
Definition: Account.java:50

Copyright © 2011-2021 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.