Sleuth Kit Java Bindings (JNI) 4.14.0
Java bindings for using The Sleuth Kit
Loading...
Searching...
No Matches
CommunicationArtifactsHelper.java
Go to the documentation of this file.
1/*
2 * Sleuth Kit Data Model
3 *
4 * Copyright 2019-2021 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 */
19package org.sleuthkit.datamodel.blackboardutils;
20
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.Collection;
24import java.util.Collections;
25import java.util.List;
26import java.util.Optional;
27import java.util.logging.Level;
28import java.util.logging.Logger;
29import org.apache.commons.lang3.StringUtils;
30import org.sleuthkit.datamodel.AbstractFile;
31import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
32import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
33import org.sleuthkit.datamodel.Account;
34import org.sleuthkit.datamodel.AccountFileInstance;
35import org.sleuthkit.datamodel.Blackboard.BlackboardException;
36import org.sleuthkit.datamodel.BlackboardArtifact;
37import org.sleuthkit.datamodel.BlackboardAttribute;
38import org.sleuthkit.datamodel.Content;
39import org.sleuthkit.datamodel.DataArtifact;
40import org.sleuthkit.datamodel.DataSource;
41import org.sleuthkit.datamodel.InvalidAccountIDException;
42import org.sleuthkit.datamodel.Relationship;
43import org.sleuthkit.datamodel.SleuthkitCase;
44import org.sleuthkit.datamodel.TskCoreException;
45import org.sleuthkit.datamodel.TskDataException;
46import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil;
47import org.sleuthkit.datamodel.blackboardutils.attributes.MessageAttachments;
48import org.sleuthkit.datamodel.blackboardutils.attributes.MessageAttachments.FileAttachment;
49
69public final class CommunicationArtifactsHelper extends ArtifactHelperBase {
70
71 private static final Logger LOGGER = Logger.getLogger(CommunicationArtifactsHelper.class.getName());
72
73 private static final BlackboardArtifact.Type CONTACT_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_CONTACT);
74 private static final BlackboardArtifact.Type MESSAGE_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_MESSAGE);
75 private static final BlackboardArtifact.Type CALLOG_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_CALLLOG);
76 private static final BlackboardArtifact.Type ASSOCIATED_OBJ_TYPE = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
77
81 public enum MessageReadStatus {
82
83 UNKNOWN("Unknown"),
84 UNREAD("Unread"),
85 READ("Read");
86
87 private final String msgReadStr;
88
89 MessageReadStatus(String readStatus) {
90 this.msgReadStr = readStatus;
91 }
92
93 public String getDisplayName() {
94 return msgReadStr;
95 }
96 }
97
102 UNKNOWN("Unknown"),
103 INCOMING("Incoming"),
104 OUTGOING("Outgoing");
105
106 private final String dirStr;
107
109 this.dirStr = dir;
110 }
111
112 public String getDisplayName() {
113 return dirStr;
114 }
115 }
116
120 public enum CallMediaType {
121 UNKNOWN("Unknown"),
122 AUDIO("Audio"), // Audio only call
123 VIDEO("Video"); // Video/multimedia call
124
125 private final String typeStr;
126
127 CallMediaType(String type) {
128 this.typeStr = type;
129 }
130
131 public String getDisplayName() {
132 return typeStr;
133 }
134 }
135
137
138 // 'self' account for the application being processed by the module.
139 private final Account.Type selfAccountType;
140 private final String selfAccountId;
141
142 private AccountFileInstance selfAccountInstance = null;
143
144 // Type of accounts to be created for the module using this helper.
145 private final Account.Type moduleAccountsType;
146
165 public CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Long ingestJobId) throws TskCoreException {
166 super(caseDb, moduleName, srcContent, ingestJobId);
167 this.moduleAccountsType = accountsType;
168 this.selfAccountType = Account.Type.DEVICE;
169 this.selfAccountId = ((DataSource) getContent().getDataSource()).getDeviceId();
170 }
171
194 public CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId, Long ingestJobId) throws TskCoreException {
195 super(caseDb, moduleName, srcContent, ingestJobId);
196 this.moduleAccountsType = accountsType;
197 this.selfAccountType = selfAccountType;
198 this.selfAccountId = selfAccountId;
199 }
200
220 @Deprecated
221 public CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType) throws TskCoreException {
222 this(caseDb, moduleName, srcContent, accountsType, null);
223 }
224
247 @Deprecated
248 public CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId) throws TskCoreException {
249 this(caseDb, moduleName, srcContent, accountsType, selfAccountType, selfAccountId, null);
250 }
251
273 public BlackboardArtifact addContact(String contactName,
274 String phoneNumber, String homePhoneNumber,
275 String mobilePhoneNumber, String emailAddr) throws TskCoreException, BlackboardException {
276 return addContact(contactName, phoneNumber,
277 homePhoneNumber, mobilePhoneNumber, emailAddr,
278 Collections.emptyList());
279 }
280
306 public BlackboardArtifact addContact(String contactName,
307 String phoneNumber, String homePhoneNumber,
308 String mobilePhoneNumber, String emailAddr,
309 Collection<BlackboardAttribute> additionalAttributes) throws TskCoreException, BlackboardException {
310
311 // check if the caller has included any phone/email/id in addtional attributes
312 boolean hasAnyIdAttribute = false;
313 if (additionalAttributes != null) {
314 for (BlackboardAttribute attr : additionalAttributes) {
315 if ((attr.getAttributeType().getTypeName().startsWith("TSK_PHONE"))
316 || (attr.getAttributeType().getTypeName().startsWith("TSK_EMAIL"))
317 || (attr.getAttributeType().getTypeName().startsWith("TSK_ID"))) {
318 hasAnyIdAttribute = true;
319 break;
320 }
321 }
322 }
323
324 // At least one phone number or email address
325 // or an optional attribute with phone/email/id must be provided
326 if (StringUtils.isEmpty(phoneNumber) && StringUtils.isEmpty(homePhoneNumber)
327 && StringUtils.isEmpty(mobilePhoneNumber) && StringUtils.isEmpty(emailAddr)
328 && (!hasAnyIdAttribute)) {
329 throw new IllegalArgumentException("At least one phone number or email address or an id must be provided.");
330 }
331
332 BlackboardArtifact contactArtifact;
333 Collection<BlackboardAttribute> attributes = new ArrayList<>();
334
335 // create TSK_CONTACT artifact and construct attributes
336 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_NAME, contactName, attributes);
337
338 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, phoneNumber, attributes);
339 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME, homePhoneNumber, attributes);
340 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE, mobilePhoneNumber, attributes);
341 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_EMAIL, emailAddr, attributes);
342
343 // add attributes
344 attributes.addAll(additionalAttributes);
345 Content content = getContent();
346
347 contactArtifact = content.newDataArtifact(CONTACT_TYPE, attributes);
348
349 // create an account for each specified contact method, and a relationship with self account
350 createContactMethodAccountAndRelationship(Account.Type.PHONE, phoneNumber, contactArtifact, 0);
351 createContactMethodAccountAndRelationship(Account.Type.PHONE, homePhoneNumber, contactArtifact, 0);
352 createContactMethodAccountAndRelationship(Account.Type.PHONE, mobilePhoneNumber, contactArtifact, 0);
353 createContactMethodAccountAndRelationship(Account.Type.EMAIL, emailAddr, contactArtifact, 0);
354
355 // if the additional attribute list has any phone/email/id attributes, create accounts & relationships for those.
356 if ((additionalAttributes != null) && hasAnyIdAttribute) {
357 for (BlackboardAttribute bba : additionalAttributes) {
358 if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) {
359 createContactMethodAccountAndRelationship(Account.Type.PHONE, bba.getValueString(), contactArtifact, 0);
360 } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) {
361 createContactMethodAccountAndRelationship(Account.Type.EMAIL, bba.getValueString(), contactArtifact, 0);
362 } else if (bba.getAttributeType().getTypeName().startsWith("TSK_ID")) {
363 createContactMethodAccountAndRelationship(this.moduleAccountsType, bba.getValueString(), contactArtifact, 0);
364 }
365 }
366 }
367
368 // post artifact
369 Optional<Long> ingestJobId = getIngestJobId();
370 getSleuthkitCase().getBlackboard().postArtifact(contactArtifact, getModuleName(), ingestJobId.orElse(null));
371
372 return contactArtifact;
373 }
374
383 private void createContactMethodAccountAndRelationship(Account.Type accountType,
384 String accountUniqueID, BlackboardArtifact sourceArtifact,
385 long dateTime) throws TskCoreException {
386
387 // Find/Create an account instance for each of the contact method
388 // Create a relationship between selfAccount and contactAccount
389 if (StringUtils.isNotBlank(accountUniqueID)) {
390 try {
391 AccountFileInstance contactAccountInstance = createAccountInstance(accountType, accountUniqueID);
392
393 // Create a relationship between self account and the contact account
394 try {
395 getSleuthkitCase().getCommunicationsManager().addRelationships(getSelfAccountInstance(),
396 Collections.singletonList(contactAccountInstance), sourceArtifact, Relationship.Type.CONTACT, dateTime);
397 } catch (TskDataException ex) {
398 throw new TskCoreException(String.format("Failed to create relationship between account = %s and account = %s.",
399 getSelfAccountInstance().getAccount(), contactAccountInstance.getAccount()), ex);
400 }
401 } catch (InvalidAccountIDException ex) {
402 LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", accountUniqueID));
403 }
404 }
405 }
406
419 private AccountFileInstance createAccountInstance(Account.Type accountType, String accountUniqueID) throws TskCoreException, InvalidAccountIDException {
420 Optional<Long> ingestJobId = getIngestJobId();
421 return getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(accountType, accountUniqueID, getModuleName(), getContent(), null, ingestJobId.orElse(null));
422 }
423
446 String messageType,
447 CommunicationDirection direction,
448 String senderId,
449 String recipientId,
450 long dateTime, MessageReadStatus readStatus,
451 String subject, String messageText, String threadId) throws TskCoreException, BlackboardException {
452 return addMessage(messageType, direction,
453 senderId, recipientId, dateTime, readStatus,
454 subject, messageText, threadId,
455 Collections.emptyList());
456 }
457
480 public BlackboardArtifact addMessage(String messageType,
481 CommunicationDirection direction,
482 String senderId,
483 String recipientId,
484 long dateTime, MessageReadStatus readStatus, String subject,
485 String messageText, String threadId,
486 Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
487
488 return addMessage(messageType, direction,
489 senderId,
490 Arrays.asList(recipientId),
491 dateTime, readStatus,
492 subject, messageText, threadId,
493 otherAttributesList);
494 }
495
518 public BlackboardArtifact addMessage(String messageType,
519 CommunicationDirection direction,
520 String senderId,
521 List<String> recipientIdsList,
522 long dateTime, MessageReadStatus readStatus,
523 String subject, String messageText, String threadId) throws TskCoreException, BlackboardException {
524 return addMessage(messageType, direction,
525 senderId, recipientIdsList,
526 dateTime, readStatus,
527 subject, messageText, threadId,
528 Collections.emptyList());
529 }
530
553 public BlackboardArtifact addMessage(String messageType,
554 CommunicationDirection direction,
555 String senderId,
556 List<String> recipientIdsList,
557 long dateTime, MessageReadStatus readStatus,
558 String subject, String messageText,
559 String threadId,
560 Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
561
562 // Created message artifact.
563 Collection<BlackboardAttribute> attributes = new ArrayList<>();
564
565 // construct attributes
566 attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, getModuleName(), messageType));
567 addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME, dateTime, attributes);
568
569 addMessageReadStatusIfKnown(readStatus, attributes);
570 addCommDirectionIfKnown(direction, attributes);
571
572 // Get the self account instance
573 AccountFileInstance selfAccountInstanceLocal = null;
574 try {
575 selfAccountInstanceLocal = getSelfAccountInstance();
576 } catch (InvalidAccountIDException ex) {
577 LOGGER.log(Level.WARNING, String.format("Failed to get/create self account with id %s", selfAccountId), ex);
578 }
579
580 // set sender attribute and create sender account
581 AccountFileInstance senderAccountInstance = null;
582 if (StringUtils.isNotBlank(senderId)) {
583 try {
584 senderAccountInstance = createAccountInstance(moduleAccountsType, senderId);
585 } catch (InvalidAccountIDException ex) {
586 LOGGER.log(Level.WARNING, String.format("Invalid account identifier %s", senderId));
587 }
588 }
589
590 // set recipient attribute and create recipient accounts
591 List<AccountFileInstance> recipientAccountsList = new ArrayList<>();
592 String recipientsStr = "";
593 if (!isEffectivelyEmpty(recipientIdsList)) {
594 for (String recipient : recipientIdsList) {
595 if (StringUtils.isNotBlank(recipient)) {
596 try {
597 recipientAccountsList.add(createAccountInstance(moduleAccountsType, recipient));
598 } catch (InvalidAccountIDException ex) {
599 LOGGER.log(Level.WARNING, String.format("Invalid account identifier %s", recipient));
600 }
601 }
602 }
603 // Create a comma separated string of recipients
604 recipientsStr = addressListToString(recipientIdsList);
605 }
606
607 switch (direction) {
608 case OUTGOING:
609 // if no sender, selfAccount substitutes caller.
610 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
611 senderAccountInstance = selfAccountInstanceLocal;
612 }
613 // sender becomes PHONE_FROM
614 if (senderAccountInstance != null) {
615 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
616 }
617 // recipient becomes PHONE_TO
618 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, recipientsStr, attributes);
619 break;
620
621 case INCOMING:
622 // if no recipeint specified, selfAccount substitutes recipient
623 if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
624 recipientsStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
625 recipientAccountsList.add(selfAccountInstanceLocal);
626 }
627 // caller becomes PHONE_FROM
628 if (senderAccountInstance != null) {
629 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
630 }
631 // callee becomes PHONE_TO
632 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, recipientsStr, attributes);
633 break;
634 default: // direction UNKNOWN
635 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
636 // if no sender, selfAccount substitutes caller.
637 senderAccountInstance = selfAccountInstanceLocal;
638 } else if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
639 // else if no recipient specified, selfAccount substitutes recipient
640 recipientsStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
641 recipientAccountsList.add(selfAccountInstanceLocal);
642 }
643
644 // save phone numbers in direction agnostic attributes
645 if (senderAccountInstance != null) {
646 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, senderAccountInstance.getAccount().getTypeSpecificID(), attributes);
647 } // callee becomes PHONE_TO
648 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, recipientsStr, attributes);
649 break;
650 }
651
652 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_SUBJECT, subject, attributes);
653 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_TEXT, messageText, attributes);
654 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_THREAD_ID, threadId, attributes);
655
656 // add attributes to artifact
657 attributes.addAll(otherAttributesList);
658
659 // create TSK_MESSAGE artifact
660 Content content = getContent();
661 BlackboardArtifact msgArtifact = content.newDataArtifact(MESSAGE_TYPE, attributes);
662
663 // create sender/recipient relationships
664 try {
665 getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance,
666 recipientAccountsList, msgArtifact, Relationship.Type.MESSAGE, dateTime);
667 } catch (TskDataException ex) {
668 throw new TskCoreException(String.format("Failed to create Message relationships between sender account = %s and recipients = %s.",
669 (senderAccountInstance != null) ? senderAccountInstance.getAccount().getTypeSpecificID() : "Unknown", recipientsStr), ex);
670 }
671
672 // post artifact
673 Optional<Long> ingestJobId = getIngestJobId();
674 getSleuthkitCase().getBlackboard().postArtifact(msgArtifact, getModuleName(), ingestJobId.orElse(null));
675
676 // return the artifact
677 return msgArtifact;
678 }
679
703 String callerId, String calleeId,
704 long startDateTime, long endDateTime, CallMediaType mediaType) throws TskCoreException, BlackboardException {
705 return addCalllog(direction, callerId, calleeId,
706 startDateTime, endDateTime, mediaType,
707 Collections.emptyList());
708 }
709
734 String callerId,
735 String calleeId,
736 long startDateTime, long endDateTime,
737 CallMediaType mediaType,
738 Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
739 return addCalllog(direction,
740 callerId,
741 Arrays.asList(calleeId),
742 startDateTime, endDateTime,
743 mediaType,
744 otherAttributesList);
745 }
746
770 String callerId,
771 Collection<String> calleeIdsList,
772 long startDateTime, long endDateTime,
774
775 return addCalllog(direction, callerId, calleeIdsList,
776 startDateTime, endDateTime,
777 mediaType,
778 Collections.emptyList());
779 }
780
805 String callerId,
806 Collection<String> calleeIdsList,
807 long startDateTime, long endDateTime,
808 CallMediaType mediaType,
809 Collection<BlackboardAttribute> otherAttributesList) throws TskCoreException, BlackboardException {
810
811 // Either caller id or a callee id must be provided.
812 if (StringUtils.isEmpty(callerId) && (isEffectivelyEmpty(calleeIdsList))) {
813 throw new IllegalArgumentException("Either a caller id, or at least one callee id must be provided for a call log.");
814 }
815
816 AccountFileInstance selfAccountInstanceLocal = null;
817 try {
818 selfAccountInstanceLocal = getSelfAccountInstance();
819 } catch (InvalidAccountIDException ex) {
820 LOGGER.log(Level.WARNING, String.format("Failed to get/create self account with id %s", selfAccountId), ex);
821 }
822
823 Collection<BlackboardAttribute> attributes = new ArrayList<>();
824
825 // Add basic attributes
826 addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME_START, startDateTime, attributes);
827 addAttributeIfNotZero(ATTRIBUTE_TYPE.TSK_DATETIME_END, endDateTime, attributes);
828 addCommDirectionIfKnown(direction, attributes);
829
830 AccountFileInstance callerAccountInstance = null;
831 if (StringUtils.isNotBlank(callerId)) {
832 try {
833 callerAccountInstance = createAccountInstance(moduleAccountsType, callerId);
834 } catch (InvalidAccountIDException ex) {
835 LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", callerId));
836 }
837 }
838
839 // Create a comma separated string of callee
840 List<AccountFileInstance> recipientAccountsList = new ArrayList<>();
841 String calleesStr = "";
842 if (!isEffectivelyEmpty(calleeIdsList)) {
843 calleesStr = addressListToString(calleeIdsList);
844 for (String callee : calleeIdsList) {
845 if (StringUtils.isNotBlank(callee)) {
846 try {
847 recipientAccountsList.add(createAccountInstance(moduleAccountsType, callee));
848 } catch (InvalidAccountIDException ex) {
849 LOGGER.log(Level.WARNING, String.format("Failed to create account with id %s", callee));
850 }
851 }
852 }
853 }
854
855 switch (direction) {
856 case OUTGOING:
857 // if no callee throw IllegalArg
858 if (isEffectivelyEmpty(calleeIdsList)) {
859 throw new IllegalArgumentException("Callee not provided for an outgoing call.");
860 }
861 // if no caller, selfAccount substitutes caller.
862 if (StringUtils.isEmpty(callerId) && selfAccountInstanceLocal != null) {
863 callerAccountInstance = selfAccountInstanceLocal;
864 }
865 // caller becomes PHONE_FROM
866 if (callerAccountInstance != null) {
867 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
868 }
869 // callee becomes PHONE_TO
870 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, calleesStr, attributes);
871 break;
872
873 case INCOMING:
874 // if no caller throw IllegalArg
875 if (StringUtils.isEmpty(callerId)) {
876 throw new IllegalArgumentException("Caller Id not provided for incoming call.");
877 }
878 // if no callee specified, selfAccount substitutes callee
879 if (isEffectivelyEmpty(calleeIdsList) && selfAccountInstanceLocal != null) {
880 calleesStr = selfAccountInstanceLocal.getAccount().getTypeSpecificID();
881 recipientAccountsList.add(selfAccountInstanceLocal);
882 }
883 // caller becomes PHONE_FROM
884 if (callerAccountInstance != null) {
885 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
886 }
887 // callee becomes PHONE_TO
888 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, calleesStr, attributes);
889 break;
890 default: // direction UNKNOWN
891
892 // save phone numbers in direction agnostic attributes
893 if (callerAccountInstance != null) {
894 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, callerAccountInstance.getAccount().getTypeSpecificID(), attributes);
895 } // callee becomes PHONE_TO
896 addAttributeIfNotNull(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, calleesStr, attributes);
897 break;
898 }
899
900 // add attributes to artifact
901 attributes.addAll(otherAttributesList);
902 // Create TSK_CALLLOG artifact
903 Content content = getContent();
904 BlackboardArtifact callLogArtifact = content.newDataArtifact(CALLOG_TYPE, attributes);
905
906 callLogArtifact.addAttributes(attributes);
907
908 // create relationships between caller/callees
909 try {
910 getSleuthkitCase().getCommunicationsManager().addRelationships(callerAccountInstance,
911 recipientAccountsList, callLogArtifact, Relationship.Type.CALL_LOG, startDateTime);
912 } catch (TskDataException ex) {
913 throw new TskCoreException(String.format("Failed to create Call log relationships between caller account = %s and callees = %s.",
914 (callerAccountInstance != null) ? callerAccountInstance.getAccount() : "", calleesStr), ex);
915 }
916
917 // post artifact
918 Optional<Long> ingestJobId = getIngestJobId();
919 getSleuthkitCase().getBlackboard().postArtifact(callLogArtifact, getModuleName(), ingestJobId.orElse(null));
920
921 // return the artifact
922 return callLogArtifact;
923 }
924
933 public void addAttachments(BlackboardArtifact message, MessageAttachments attachments) throws TskCoreException {
934 // Create attribute
935 BlackboardAttribute blackboardAttribute = BlackboardJsonAttrUtil.toAttribute(ATTACHMENTS_ATTR_TYPE, getModuleName(), attachments);
936 message.addAttribute(blackboardAttribute);
937
938 // Associate each attachment file with the message.
939 List<BlackboardArtifact> assocObjectArtifacts = new ArrayList<>();
940 Collection<FileAttachment> fileAttachments = attachments.getFileAttachments();
941 for (FileAttachment fileAttachment : fileAttachments) {
942 long attachedFileObjId = fileAttachment.getObjectId();
943 if (attachedFileObjId >= 0) {
944 AbstractFile attachedFile = message.getSleuthkitCase().getAbstractFileById(attachedFileObjId);
945 DataArtifact artifact = associateAttachmentWithMessage(message, attachedFile);
946 assocObjectArtifacts.add(artifact);
947 }
948 }
949
950 try {
951 Optional<Long> ingestJobId = getIngestJobId();
952 getSleuthkitCase().getBlackboard().postArtifacts(assocObjectArtifacts, getModuleName(), ingestJobId.orElse(null));
953 } catch (BlackboardException ex) {
954 throw new TskCoreException("Error posting TSK_ASSOCIATED_ARTIFACT artifacts for attachments", ex);
955 }
956 }
957
970 private DataArtifact associateAttachmentWithMessage(BlackboardArtifact message, AbstractFile attachedFile) throws TskCoreException {
971 Collection<BlackboardAttribute> attributes = new ArrayList<>();
972 attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, this.getModuleName(), message.getArtifactID()));
973 return attachedFile.newDataArtifact(ASSOCIATED_OBJ_TYPE, attributes);
974 }
975
979 private String addressListToString(Collection<String> addressList) {
980
981 String toAddresses = "";
982 if (addressList != null && (!addressList.isEmpty())) {
983 StringBuilder toAddressesSb = new StringBuilder();
984 for (String address : addressList) {
985 if (!StringUtils.isEmpty(address)) {
986 toAddressesSb = toAddressesSb.length() > 0 ? toAddressesSb.append(", ").append(address) : toAddressesSb.append(address);
987 }
988 }
989 toAddresses = toAddressesSb.toString();
990 }
991
992 return toAddresses;
993 }
994
1004 private boolean isEffectivelyEmpty(Collection<String> idList) {
1005
1006 if (idList == null || idList.isEmpty()) {
1007 return true;
1008 }
1009
1010 for (String id : idList) {
1011 if (!StringUtils.isEmpty(id)) {
1012 return false;
1013 }
1014 }
1015
1016 return true;
1017
1018 }
1019
1023 private void addCommDirectionIfKnown(CommunicationDirection direction, Collection<BlackboardAttribute> attributes) {
1024 if (direction != CommunicationDirection.UNKNOWN) {
1025 attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, getModuleName(), direction.getDisplayName()));
1026 }
1027 }
1028
1032 private void addMessageReadStatusIfKnown(MessageReadStatus readStatus, Collection<BlackboardAttribute> attributes) {
1033 if (readStatus != MessageReadStatus.UNKNOWN) {
1034 attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_READ_STATUS, getModuleName(), (readStatus == MessageReadStatus.READ) ? 1 : 0));
1035 }
1036 }
1037
1046 private synchronized AccountFileInstance getSelfAccountInstance() throws TskCoreException, InvalidAccountIDException {
1047 if (selfAccountInstance == null) {
1048 Optional<Long> ingestJobId = getIngestJobId();
1049 selfAccountInstance = getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(selfAccountType, selfAccountId, this.getModuleName(), getContent(), null, ingestJobId.orElse(null));
1050 }
1051 return selfAccountInstance;
1052 }
1053}
static final Account.Type PHONE
Definition Account.java:49
static final Account.Type DEVICE
Definition Account.java:48
static final Account.Type EMAIL
Definition Account.java:50
void addAttributes(Collection< BlackboardAttribute > attributes)
void addRelationships(AccountFileInstance sender, List< AccountFileInstance > recipients, BlackboardArtifact sourceArtifact, org.sleuthkit.datamodel.Relationship.Type relationshipType, long dateTime)
static final Relationship.Type CALL_LOG
static final Relationship.Type MESSAGE
static final Relationship.Type CONTACT
CommunicationsManager getCommunicationsManager()
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId, Long ingestJobId)
BlackboardArtifact addContact(String contactName, String phoneNumber, String homePhoneNumber, String mobilePhoneNumber, String emailAddr, Collection< BlackboardAttribute > additionalAttributes)
BlackboardArtifact addCalllog(CommunicationDirection direction, String callerId, Collection< String > calleeIdsList, long startDateTime, long endDateTime, CallMediaType mediaType, Collection< BlackboardAttribute > otherAttributesList)
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType)
BlackboardArtifact addCalllog(CommunicationDirection direction, String callerId, Collection< String > calleeIdsList, long startDateTime, long endDateTime, CallMediaType mediaType)
BlackboardArtifact addMessage(String messageType, CommunicationDirection direction, String senderId, List< String > recipientIdsList, 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)
void addAttachments(BlackboardArtifact message, MessageAttachments attachments)
BlackboardArtifact addCalllog(CommunicationDirection direction, String callerId, String calleeId, long startDateTime, long endDateTime, CallMediaType mediaType)
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 addCalllog(CommunicationDirection direction, String callerId, String calleeId, long startDateTime, long endDateTime, CallMediaType mediaType, Collection< BlackboardAttribute > otherAttributesList)
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Long ingestJobId)
BlackboardArtifact addMessage(String messageType, CommunicationDirection direction, String senderId, String recipientId, long dateTime, MessageReadStatus readStatus, String subject, String messageText, String threadId)
BlackboardArtifact addContact(String contactName, String phoneNumber, String homePhoneNumber, String mobilePhoneNumber, String emailAddr)
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId)
static< T > BlackboardAttribute toAttribute(BlackboardAttribute.Type attrType, String moduleName, T attrValue)
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributesList)

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