19 package org.sleuthkit.datamodel.blackboardutils;
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;
88 private final String msgReadStr;
91 this.msgReadStr = readStatus;
107 private final String dirStr;
126 private final String typeStr;
141 private final String selfAccountId;
168 super(caseDb, moduleName, srcContent);
170 this.moduleAccountsType = accountsType;
172 this.selfAccountId = ((
DataSource) getContent().getDataSource()).getDeviceId();
196 super(caseDb, moduleName, srcContent);
198 this.moduleAccountsType = accountsType;
199 this.selfAccountType = selfAccountType;
200 this.selfAccountId = selfAccountId;
225 String phoneNumber, String homePhoneNumber,
228 homePhoneNumber, mobilePhoneNumber, emailAddr,
229 Collections.emptyList());
258 String phoneNumber, String homePhoneNumber,
259 String mobilePhoneNumber, String emailAddr,
260 Collection<BlackboardAttribute> additionalAttributes)
throws TskCoreException,
BlackboardException {
263 boolean hasAnyIdAttribute =
false;
264 if (additionalAttributes != null) {
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;
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.");
284 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
295 attributes.addAll(additionalAttributes);
296 Content content = getContent();
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);
307 if ((additionalAttributes != null) && hasAnyIdAttribute) {
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);
320 getSleuthkitCase().getBlackboard().postArtifact(contactArtifact, getModuleName());
322 return contactArtifact;
333 private void createContactMethodAccountAndRelationship(
Account.
Type accountType,
335 long dateTime)
throws TskCoreException {
339 if (StringUtils.isNotBlank(accountUniqueID)) {
341 AccountFileInstance contactAccountInstance = createAccountInstance(accountType, accountUniqueID);
345 getSleuthkitCase().getCommunicationsManager().addRelationships(getSelfAccountInstance(),
348 throw new TskCoreException(String.format(
"Failed to create relationship between account = %s and account = %s.",
349 getSelfAccountInstance().getAccount(), contactAccountInstance.
getAccount()), ex);
351 }
catch (InvalidAccountIDException ex) {
352 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", accountUniqueID));
369 private AccountFileInstance createAccountInstance(Account.Type accountType, String accountUniqueID)
throws TskCoreException, InvalidAccountIDException {
370 return getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(accountType, accountUniqueID, getModuleName(), getContent());
400 String subject, String messageText, String threadId)
throws TskCoreException,
BlackboardException {
402 senderId, recipientId, dateTime, readStatus,
403 subject, messageText, threadId,
404 Collections.emptyList());
434 String messageText, String threadId,
435 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
439 Arrays.asList(recipientId),
440 dateTime, readStatus,
441 subject, messageText, threadId,
442 otherAttributesList);
470 List<String> recipientIdsList,
472 String subject, String messageText, String threadId)
throws TskCoreException,
BlackboardException {
474 senderId, recipientIdsList,
475 dateTime, readStatus,
476 subject, messageText, threadId,
477 Collections.emptyList());
505 List<String> recipientIdsList,
507 String subject, String messageText,
509 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
512 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
518 addMessageReadStatusIfKnown(readStatus, attributes);
519 addCommDirectionIfKnown(direction, attributes);
524 selfAccountInstanceLocal = getSelfAccountInstance();
526 LOGGER.log(Level.WARNING, String.format(
"Failed to get/create self account with id %s", selfAccountId), ex);
531 if (StringUtils.isNotBlank(senderId)) {
533 senderAccountInstance = createAccountInstance(moduleAccountsType, senderId);
535 LOGGER.log(Level.WARNING, String.format(
"Invalid account identifier %s", senderId));
540 List<AccountFileInstance> recipientAccountsList =
new ArrayList<>();
541 String recipientsStr =
"";
542 if (!isEffectivelyEmpty(recipientIdsList)) {
543 for (String recipient : recipientIdsList) {
544 if (StringUtils.isNotBlank(recipient)) {
546 recipientAccountsList.add(createAccountInstance(moduleAccountsType, recipient));
548 LOGGER.log(Level.WARNING, String.format(
"Invalid account identifier %s", senderId));
553 recipientsStr = addressListToString(recipientIdsList);
559 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
560 senderAccountInstance = selfAccountInstanceLocal;
563 if (senderAccountInstance != null) {
572 if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
574 recipientAccountsList.add(selfAccountInstanceLocal);
577 if (senderAccountInstance != null) {
584 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
586 senderAccountInstance = selfAccountInstanceLocal;
587 }
else if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
590 recipientAccountsList.add(selfAccountInstanceLocal);
594 if (senderAccountInstance != null) {
606 attributes.addAll(otherAttributesList);
609 Content content = getContent();
614 getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance,
617 throw new TskCoreException(String.format(
"Failed to create Message relationships between sender account = %s and recipients = %s.",
622 getSleuthkitCase().getBlackboard().postArtifact(msgArtifact, getModuleName());
651 String callerId, String calleeId,
653 return addCalllog(direction, callerId, calleeId,
654 startDateTime, endDateTime, mediaType,
655 Collections.emptyList());
684 long startDateTime,
long endDateTime,
686 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
689 Arrays.asList(calleeId),
690 startDateTime, endDateTime,
692 otherAttributesList);
719 Collection<String> calleeIdsList,
720 long startDateTime,
long endDateTime,
723 return addCalllog(direction, callerId, calleeIdsList,
724 startDateTime, endDateTime,
726 Collections.emptyList());
754 Collection<String> calleeIdsList,
755 long startDateTime,
long endDateTime,
757 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
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.");
766 selfAccountInstanceLocal = getSelfAccountInstance();
768 LOGGER.log(Level.WARNING, String.format(
"Failed to get/create self account with id %s", selfAccountId), ex);
771 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
776 addCommDirectionIfKnown(direction, attributes);
779 if (StringUtils.isNotBlank(callerId)) {
781 callerAccountInstance = createAccountInstance(moduleAccountsType, callerId);
783 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", callerId));
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)) {
795 recipientAccountsList.add(createAccountInstance(moduleAccountsType, callee));
797 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", callerId));
806 if (isEffectivelyEmpty(calleeIdsList)) {
807 throw new IllegalArgumentException(
"Callee not provided for an outgoing call.");
810 if (StringUtils.isEmpty(callerId) && selfAccountInstanceLocal != null) {
811 callerAccountInstance = selfAccountInstanceLocal;
814 if (callerAccountInstance != null) {
823 if (StringUtils.isEmpty(callerId)) {
824 throw new IllegalArgumentException(
"Caller Id not provided for incoming call.");
827 if (isEffectivelyEmpty(calleeIdsList) && selfAccountInstanceLocal != null) {
829 recipientAccountsList.add(selfAccountInstanceLocal);
832 if (callerAccountInstance != null) {
841 if (callerAccountInstance != null) {
849 attributes.addAll(otherAttributesList);
851 Content content = getContent();
858 getSleuthkitCase().getCommunicationsManager().addRelationships(callerAccountInstance,
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);
866 getSleuthkitCase().getBlackboard().postArtifact(callLogArtifact, getModuleName());
869 return callLogArtifact;
883 message.addAttribute(blackboardAttribute);
886 Collection<FileAttachment> fileAttachments = attachments.getFileAttachments();
888 long attachedFileObjId = fileAttachment.getObjectId();
889 if (attachedFileObjId >= 0) {
891 associateAttachmentWithMessage(message, attachedFile);
909 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
918 private String addressListToString(Collection<String> addressList) {
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);
928 toAddresses = toAddressesSb.toString();
943 private boolean isEffectivelyEmpty(Collection<String> idList) {
945 if (idList == null || idList.isEmpty()) {
949 for (String
id : idList) {
950 if (!StringUtils.isEmpty(
id)) {
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()));
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));
985 private synchronized AccountFileInstance getSelfAccountInstance() throws TskCoreException, InvalidAccountIDException {
986 if (selfAccountInstance == null) {
987 selfAccountInstance = getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(selfAccountType, selfAccountId, this.getModuleName(), getContent());
989 return selfAccountInstance;
READ
message has not been read
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)
CommunicationDirection(String dir)
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)
UNREAD
read status is unknown
String getTypeSpecificID()
static final Account.Type PHONE
AbstractFile getAbstractFileById(long id)
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)
SleuthkitCase getSleuthkitCase()
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
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)
MessageReadStatus(String readStatus)
void addAttachments(BlackboardArtifact message, MessageAttachments attachments)
static final Account.Type EMAIL