Sleuth Kit Java Bindings (JNI)  4.10.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.logging.Level;
27 import java.util.logging.Logger;
28 import org.apache.commons.lang3.StringUtils;
47 
68 public final class CommunicationArtifactsHelper extends ArtifactHelperBase {
69 
70  private static final Logger LOGGER = Logger.getLogger(CommunicationArtifactsHelper.class.getName());
74  public enum MessageReadStatus {
75 
76  UNKNOWN("Unknown"),
77  UNREAD("Unread"),
78  READ("Read");
79 
80  private final String msgReadStr;
81 
82  MessageReadStatus(String readStatus) {
83  this.msgReadStr = readStatus;
84  }
85 
86  public String getDisplayName() {
87  return msgReadStr;
88  }
89  }
90 
94  public enum CommunicationDirection {
95  UNKNOWN("Unknown"),
96  INCOMING("Incoming"),
97  OUTGOING("Outgoing");
98 
99  private final String dirStr;
100 
102  this.dirStr = dir;
103  }
104 
105  public String getDisplayName() {
106  return dirStr;
107  }
108  }
109 
113  public enum CallMediaType {
114  UNKNOWN("Unknown"),
115  AUDIO("Audio"), // Audio only call
116  VIDEO("Video"); // Video/multimedia call
117 
118  private final String typeStr;
119 
120  CallMediaType(String type) {
121  this.typeStr = type;
122  }
123 
124  public String getDisplayName() {
125  return typeStr;
126  }
127  }
128 
129  private static final BlackboardAttribute.Type ATTACHMENTS_ATTR_TYPE = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS);
130 
131 
132  // 'self' account for the application being processed by the module.
133  private final Account.Type selfAccountType;
134  private final String selfAccountId;
135 
136  private AccountFileInstance selfAccountInstance = null;
137 
138  // Type of accounts to be created for the module using this helper.
139  private final Account.Type moduleAccountsType;
140 
159  String moduleName, Content srcContent, Account.Type accountsType) throws TskCoreException {
160 
161  super(caseDb, moduleName, srcContent);
162 
163  this.moduleAccountsType = accountsType;
164  this.selfAccountType = Account.Type.DEVICE;
165  this.selfAccountId = ((DataSource) getContent().getDataSource()).getDeviceId();
166  }
167 
187  public CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId) throws TskCoreException {
188 
189  super(caseDb, moduleName, srcContent);
190 
191  this.moduleAccountsType = accountsType;
192  this.selfAccountType = selfAccountType;
193  this.selfAccountId = selfAccountId;
194  }
195 
217  public BlackboardArtifact addContact(String contactName,
218  String phoneNumber, String homePhoneNumber,
219  String mobilePhoneNumber, String emailAddr) throws TskCoreException, BlackboardException {
220  return addContact(contactName, phoneNumber,
221  homePhoneNumber, mobilePhoneNumber, emailAddr,
222  Collections.emptyList());
223  }
224 
250  public BlackboardArtifact addContact(String contactName,
251  String phoneNumber, String homePhoneNumber,
252  String mobilePhoneNumber, String emailAddr,
253  Collection<BlackboardAttribute> additionalAttributes) throws TskCoreException, BlackboardException {
254 
255  // check if the caller has included any phone/email/id in addtional attributes
256  boolean hasAnyIdAttribute = false;
257  if (additionalAttributes != null) {
258  for (BlackboardAttribute attr : additionalAttributes) {
259  if ((attr.getAttributeType().getTypeName().startsWith("TSK_PHONE"))
260  || (attr.getAttributeType().getTypeName().startsWith("TSK_EMAIL"))
261  || (attr.getAttributeType().getTypeName().startsWith("TSK_ID"))) {
262  hasAnyIdAttribute = true;
263  break;
264  }
265  }
266  }
267 
268  // At least one phone number or email address
269  // or an optional attribute with phone/email/id must be provided
270  if (StringUtils.isEmpty(phoneNumber) && StringUtils.isEmpty(homePhoneNumber)
271  && StringUtils.isEmpty(mobilePhoneNumber) && StringUtils.isEmpty(emailAddr)
272  && (!hasAnyIdAttribute)) {
273  throw new IllegalArgumentException("At least one phone number or email address or an id must be provided.");
274  }
275 
276  BlackboardArtifact contactArtifact;
277  Collection<BlackboardAttribute> attributes = new ArrayList<>();
278 
279  // create TSK_CONTACT artifact
280  contactArtifact = getContent().newArtifact(ARTIFACT_TYPE.TSK_CONTACT);
281 
282  // construct attributes
283  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_NAME, contactName, attributes);
284 
285  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, phoneNumber, attributes);
286  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME, homePhoneNumber, attributes);
287  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE, mobilePhoneNumber, attributes);
288  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_EMAIL, emailAddr, attributes);
289 
290  // add attributes
291  attributes.addAll(additionalAttributes);
292  contactArtifact.addAttributes(attributes);
293 
294  // create an account for each specified contact method, and a relationship with self account
295  createContactMethodAccountAndRelationship(Account.Type.PHONE, phoneNumber, contactArtifact, 0);
296  createContactMethodAccountAndRelationship(Account.Type.PHONE, homePhoneNumber, contactArtifact, 0);
297  createContactMethodAccountAndRelationship(Account.Type.PHONE, mobilePhoneNumber, contactArtifact, 0);
298  createContactMethodAccountAndRelationship(Account.Type.EMAIL, emailAddr, contactArtifact, 0);
299 
300  // if the additional attribute list has any phone/email/id attributes, create accounts & relationships for those.
301  if ((additionalAttributes != null) && hasAnyIdAttribute) {
302  for (BlackboardAttribute bba : additionalAttributes) {
303  if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) {
304  createContactMethodAccountAndRelationship(Account.Type.PHONE, bba.getValueString(), contactArtifact, 0);
305  } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) {
306  createContactMethodAccountAndRelationship(Account.Type.EMAIL, bba.getValueString(), contactArtifact, 0);
307  } else if (bba.getAttributeType().getTypeName().startsWith("TSK_ID")) {
308  createContactMethodAccountAndRelationship(this.moduleAccountsType, bba.getValueString(), contactArtifact, 0);
309  }
310  }
311  }
312 
313  // post artifact
314  getSleuthkitCase().getBlackboard().postArtifact(contactArtifact, getModuleName());
315 
316  return contactArtifact;
317  }
318 
326  private void createContactMethodAccountAndRelationship(Account.Type accountType,
327  String accountUniqueID, BlackboardArtifact sourceArtifact,
328  long dateTime) throws TskCoreException {
329 
330  // Find/Create an account instance for each of the contact method
331  // Create a relationship between selfAccount and contactAccount
332  if (StringUtils.isNotBlank(accountUniqueID)) {
333  try {
334  AccountFileInstance contactAccountInstance = createAccountInstance(accountType, accountUniqueID);
335 
336  // Create a relationship between self account and the contact account
337  try {
338  getSleuthkitCase().getCommunicationsManager().addRelationships(getSelfAccountInstance(),
339  Collections.singletonList(contactAccountInstance), sourceArtifact, Relationship.Type.CONTACT, dateTime);
340  } catch (TskDataException ex) {
341  throw new TskCoreException(String.format("Failed to create relationship between account = %s and account = %s.",
342  getSelfAccountInstance().getAccount(), contactAccountInstance.getAccount()), ex);
343  }
344  }
345  catch (InvalidAccountIDException ex) {
346  LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", accountUniqueID));
347  }
348  }
349  }
350 
363  private AccountFileInstance createAccountInstance(Account.Type accountType, String accountUniqueID) throws TskCoreException, InvalidAccountIDException {
364  return getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(accountType, accountUniqueID, getModuleName(), getContent());
365  }
366 
389  String messageType,
390  CommunicationDirection direction,
391  String senderId,
392  String recipientId,
393  long dateTime, MessageReadStatus readStatus,
394  String subject, String messageText, String threadId) throws TskCoreException, BlackboardException {
395  return addMessage(messageType, direction,
396  senderId, recipientId, dateTime, readStatus,
397  subject, messageText, threadId,
398  Collections.emptyList());
399  }
400 
423  public BlackboardArtifact addMessage(String messageType,
424  CommunicationDirection direction,
425  String senderId,
426  String recipientId,
427  long dateTime, MessageReadStatus readStatus, String subject,
428  String messageText, String threadId,
429  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
430 
431  return addMessage(messageType, direction,
432  senderId,
433  Arrays.asList(recipientId),
434  dateTime, readStatus,
435  subject, messageText, threadId,
436  otherAttributesList);
437  }
438 
461  public BlackboardArtifact addMessage(String messageType,
462  CommunicationDirection direction,
463  String senderId,
464  List<String> recipientIdsList,
465  long dateTime, MessageReadStatus readStatus,
466  String subject, String messageText, String threadId) throws TskCoreException, BlackboardException {
467  return addMessage(messageType, direction,
468  senderId, recipientIdsList,
469  dateTime, readStatus,
470  subject, messageText, threadId,
471  Collections.emptyList());
472  }
473 
496  public BlackboardArtifact addMessage(String messageType,
497  CommunicationDirection direction,
498  String senderId,
499  List<String> recipientIdsList,
500  long dateTime, MessageReadStatus readStatus,
501  String subject, String messageText,
502  String threadId,
503  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
504 
505  // Created message artifact.
506  BlackboardArtifact msgArtifact;
507  Collection<BlackboardAttribute> attributes = new ArrayList<>();
508 
509  // create TSK_MESSAGE artifact
510  msgArtifact = getContent().newArtifact(ARTIFACT_TYPE.TSK_MESSAGE);
511 
512  // construct attributes
513  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, getModuleName(), messageType));
514  addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME, dateTime, attributes);
515 
516  addMessageReadStatusIfKnown(readStatus, attributes);
517  addCommDirectionIfKnown(direction, attributes);
518 
519  // Get the self account instance
520  AccountFileInstance selfAccountInstanceLocal = null;
521  try {
522  selfAccountInstanceLocal = getSelfAccountInstance();
523  } catch (InvalidAccountIDException ex) {
524  LOGGER.log(Level.WARNING, String.format("Failed to get/create self account with id %s", selfAccountId), ex);
525  }
526 
527  // set sender attribute and create sender account
528  AccountFileInstance senderAccountInstance = null;
529  if (StringUtils.isNotBlank(senderId)) {
530  try {
531  senderAccountInstance = createAccountInstance(moduleAccountsType, senderId);
532  } catch (InvalidAccountIDException ex) {
533  LOGGER.log(Level.WARNING, String.format("Invalid account identifier %s", senderId));
534  }
535  }
536 
537 
538  // set recipient attribute and create recipient accounts
539  List<AccountFileInstance> recipientAccountsList = new ArrayList<>();
540  String recipientsStr = "";
541  if (!isEffectivelyEmpty(recipientIdsList)) {
542  for (String recipient : recipientIdsList) {
543  if (StringUtils.isNotBlank(recipient)) {
544  try {
545  recipientAccountsList.add(createAccountInstance(moduleAccountsType, recipient));
546  } catch (InvalidAccountIDException ex) {
547  LOGGER.log(Level.WARNING, String.format("Invalid account identifier %s", senderId));
548  }
549  }
550  }
551  // Create a comma separated string of recipients
552  recipientsStr = addressListToString(recipientIdsList);
553  }
554 
555  switch (direction) {
556  case OUTGOING:
557  // if no sender, selfAccount substitutes caller.
558  if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
559  senderAccountInstance = selfAccountInstanceLocal;
560  }
561  // sender becomes PHONE_FROM
562  if (senderAccountInstance != null) {
563  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
564  }
565  // recipient becomes PHONE_TO
566  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, recipientsStr, attributes);
567  break;
568 
569  case INCOMING:
570  // if no recipeint specified, selfAccount substitutes recipient
571  if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null ) {
572  recipientsStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
573  recipientAccountsList.add(selfAccountInstanceLocal);
574  }
575  // caller becomes PHONE_FROM
576  if (senderAccountInstance != null) {
577  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
578  }
579  // callee becomes PHONE_TO
580  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, recipientsStr, attributes);
581  break;
582  default: // direction UNKNOWN
583  if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null ) {
584  // if no sender, selfAccount substitutes caller.
585  senderAccountInstance = selfAccountInstanceLocal;
586  }
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  msgArtifact.addAttributes(attributes);
608 
609  // create sender/recipient relationships
610  try {
611  getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance,
612  recipientAccountsList, msgArtifact, Relationship.Type.MESSAGE, dateTime);
613  } catch (TskDataException ex) {
614  throw new TskCoreException(String.format("Failed to create Message relationships between sender account = %s and recipients = %s.",
615  (senderAccountInstance != null) ? senderAccountInstance.getAccount().getTypeSpecificID() : "Unknown", recipientsStr), ex);
616  }
617 
618  // post artifact
619  getSleuthkitCase().getBlackboard().postArtifact(msgArtifact, getModuleName());
620 
621  // return the artifact
622  return msgArtifact;
623  }
624 
648  String callerId, String calleeId,
649  long startDateTime, long endDateTime, CallMediaType mediaType) throws TskCoreException, BlackboardException {
650  return addCalllog(direction, callerId, calleeId,
651  startDateTime, endDateTime, mediaType,
652  Collections.emptyList());
653  }
654 
679  String callerId,
680  String calleeId,
681  long startDateTime, long endDateTime,
682  CallMediaType mediaType,
683  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
684  return addCalllog(direction,
685  callerId,
686  Arrays.asList(calleeId),
687  startDateTime, endDateTime,
688  mediaType,
689  otherAttributesList);
690  }
691 
715  String callerId,
716  Collection<String> calleeIdsList,
717  long startDateTime, long endDateTime,
718  CallMediaType mediaType) throws TskCoreException, BlackboardException {
719 
720  return addCalllog(direction, callerId, calleeIdsList,
721  startDateTime, endDateTime,
722  mediaType,
723  Collections.emptyList());
724  }
725 
750  String callerId,
751  Collection<String> calleeIdsList,
752  long startDateTime, long endDateTime,
753  CallMediaType mediaType,
754  Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
755 
756  // Either caller id or a callee id must be provided.
757  if (StringUtils.isEmpty(callerId) && (isEffectivelyEmpty(calleeIdsList))) {
758  throw new IllegalArgumentException("Either a caller id, or at least one callee id must be provided for a call log.");
759  }
760 
761  AccountFileInstance selfAccountInstanceLocal = null;
762  try {
763  selfAccountInstanceLocal = getSelfAccountInstance();
764  } catch (InvalidAccountIDException ex) {
765  LOGGER.log(Level.WARNING, String.format("Failed to get/create self account with id %s", selfAccountId), ex);
766  }
767 
768  BlackboardArtifact callLogArtifact;
769  Collection<BlackboardAttribute> attributes = new ArrayList<>();
770 
771  // Create TSK_CALLLOG artifact
772  callLogArtifact = getContent().newArtifact(ARTIFACT_TYPE.TSK_CALLLOG);
773 
774  // Add basic attributes
775  addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME_START, startDateTime, attributes);
776  addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME_END, endDateTime, attributes);
777  addCommDirectionIfKnown(direction, attributes);
778 
779  AccountFileInstance callerAccountInstance = null;
780  if (StringUtils.isNotBlank(callerId)) {
781  try {
782  callerAccountInstance = createAccountInstance(moduleAccountsType, callerId);
783  } catch (InvalidAccountIDException ex) {
784  LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", callerId));
785  }
786  }
787 
788  // Create a comma separated string of callee
789  List<AccountFileInstance> recipientAccountsList = new ArrayList<>();
790  String calleesStr = "";
791  if (!isEffectivelyEmpty(calleeIdsList)) {
792  calleesStr = addressListToString(calleeIdsList);
793  for (String callee : calleeIdsList) {
794  if (StringUtils.isNotBlank(callee)) {
795  try{
796  recipientAccountsList.add(createAccountInstance(moduleAccountsType, callee));
797  }
798  catch (InvalidAccountIDException ex) {
799  LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", callerId));
800  }
801  }
802  }
803  }
804 
805  switch (direction) {
806  case OUTGOING:
807  // if no callee throw IllegalArg
808  if (isEffectivelyEmpty(calleeIdsList)) {
809  throw new IllegalArgumentException("Callee not provided for an outgoing call.");
810  }
811  // if no caller, selfAccount substitutes caller.
812  if (StringUtils.isEmpty(callerId) && selfAccountInstanceLocal != null ) {
813  callerAccountInstance = selfAccountInstanceLocal;
814  }
815  // caller becomes PHONE_FROM
816  if (callerAccountInstance != null) {
817  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
818  }
819  // callee becomes PHONE_TO
820  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, calleesStr, attributes);
821  break;
822 
823  case INCOMING:
824  // if no caller throw IllegalArg
825  if (StringUtils.isEmpty(callerId)) {
826  throw new IllegalArgumentException("Caller Id not provided for incoming call.");
827  }
828  // if no callee specified, selfAccount substitutes callee
829  if (isEffectivelyEmpty(calleeIdsList) && selfAccountInstanceLocal != null) {
830  calleesStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
831  recipientAccountsList.add(selfAccountInstanceLocal);
832  }
833  // caller becomes PHONE_FROM
834  if (callerAccountInstance != null) {
835  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
836  }
837  // callee becomes PHONE_TO
838  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, calleesStr, attributes);
839  break;
840  default: // direction UNKNOWN
841 
842  // save phone numbers in direction agnostic attributes
843  if (callerAccountInstance != null) {
844  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
845  } // callee becomes PHONE_TO
846  addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, calleesStr, attributes);
847  break;
848  }
849 
850  // add attributes to artifact
851  attributes.addAll(otherAttributesList);
852  callLogArtifact.addAttributes(attributes);
853 
854  // create relationships between caller/callees
855  try {
856  getSleuthkitCase().getCommunicationsManager().addRelationships(callerAccountInstance,
857  recipientAccountsList, callLogArtifact, Relationship.Type.CALL_LOG, startDateTime);
858  } catch (TskDataException ex) {
859  throw new TskCoreException(String.format("Failed to create Call log relationships between caller account = %s and callees = %s.",
860  (callerAccountInstance!= null) ? callerAccountInstance.getAccount() : "", calleesStr), ex);
861  }
862 
863  // post artifact
864  getSleuthkitCase().getBlackboard().postArtifact(callLogArtifact, getModuleName());
865 
866  // return the artifact
867  return callLogArtifact;
868  }
869 
870 
879  public void addAttachments(BlackboardArtifact message, MessageAttachments attachments) throws TskCoreException {
880  // Create attribute
881  BlackboardAttribute blackboardAttribute = BlackboardJsonAttrUtil.toAttribute(ATTACHMENTS_ATTR_TYPE, getModuleName(), attachments);
882  message.addAttribute(blackboardAttribute);
883 
884  // Associate each attachment file with the message.
885  Collection<FileAttachment> fileAttachments = attachments.getFileAttachments();
886  for (FileAttachment fileAttachment : fileAttachments) {
887  long attachedFileObjId = fileAttachment.getObjectId();
888  if (attachedFileObjId >= 0) {
889  AbstractFile attachedFile = message.getSleuthkitCase().getAbstractFileById(attachedFileObjId);
890  associateAttachmentWithMessage(message, attachedFile);
891  }
892  }
893  }
894 
907  private BlackboardArtifact associateAttachmentWithMessage(BlackboardArtifact message, AbstractFile attachedFile) throws TskCoreException {
908  Collection<BlackboardAttribute> attributes = new ArrayList<>();
909  attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, this.getModuleName(), message.getArtifactID()));
910 
912  bba.addAttributes(attributes); //write out to bb
913  return bba;
914  }
915 
919  private String addressListToString(Collection<String> addressList) {
920 
921  String toAddresses = "";
922  if (addressList != null && (!addressList.isEmpty())) {
923  StringBuilder toAddressesSb = new StringBuilder();
924  for (String address : addressList) {
925  if (!StringUtils.isEmpty(address)) {
926  toAddressesSb = toAddressesSb.length() > 0 ? toAddressesSb.append(", ").append(address) : toAddressesSb.append(address);
927  }
928  }
929  toAddresses = toAddressesSb.toString();
930  }
931 
932  return toAddresses;
933  }
934 
944  private boolean isEffectivelyEmpty(Collection<String> idList) {
945 
946  if (idList == null || idList.isEmpty()) {
947  return true;
948  }
949 
950  for (String id : idList) {
951  if (!StringUtils.isEmpty(id)) {
952  return false;
953  }
954  }
955 
956  return true;
957 
958  }
959 
963  private void addCommDirectionIfKnown(CommunicationDirection direction, Collection<BlackboardAttribute> attributes) {
964  if (direction != CommunicationDirection.UNKNOWN) {
965  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, getModuleName(), direction.getDisplayName()));
966  }
967  }
968 
972  private void addMessageReadStatusIfKnown(MessageReadStatus readStatus, Collection<BlackboardAttribute> attributes) {
973  if (readStatus != MessageReadStatus.UNKNOWN) {
974  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_READ_STATUS, getModuleName(), (readStatus == MessageReadStatus.READ) ? 1 : 0));
975  }
976  }
977 
984  private synchronized AccountFileInstance getSelfAccountInstance() throws TskCoreException, InvalidAccountIDException {
985  if (selfAccountInstance == null) {
986  selfAccountInstance = getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(selfAccountType, selfAccountId, this.getModuleName(), getContent());
987  }
988  return selfAccountInstance;
989  }
990 }
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)
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)
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 newArtifact(int artifactTypeID)
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-2020 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.