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.logging.Level;
27 import java.util.logging.Logger;
28 import org.apache.commons.lang3.StringUtils;
80 private final String msgReadStr;
83 this.msgReadStr = readStatus;
99 private final String dirStr;
118 private final String typeStr;
134 private final String selfAccountId;
161 super(caseDb, moduleName, srcContent);
163 this.moduleAccountsType = accountsType;
165 this.selfAccountId = ((
DataSource) getContent().getDataSource()).getDeviceId();
189 super(caseDb, moduleName, srcContent);
191 this.moduleAccountsType = accountsType;
192 this.selfAccountType = selfAccountType;
193 this.selfAccountId = selfAccountId;
218 String phoneNumber, String homePhoneNumber,
221 homePhoneNumber, mobilePhoneNumber, emailAddr,
222 Collections.emptyList());
251 String phoneNumber, String homePhoneNumber,
252 String mobilePhoneNumber, String emailAddr,
253 Collection<BlackboardAttribute> additionalAttributes)
throws TskCoreException,
BlackboardException {
256 boolean hasAnyIdAttribute =
false;
257 if (additionalAttributes != null) {
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;
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.");
277 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
291 attributes.addAll(additionalAttributes);
292 contactArtifact.addAttributes(attributes);
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);
301 if ((additionalAttributes != null) && hasAnyIdAttribute) {
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);
314 getSleuthkitCase().getBlackboard().postArtifact(contactArtifact, getModuleName());
316 return contactArtifact;
326 private void createContactMethodAccountAndRelationship(
Account.
Type accountType,
328 long dateTime)
throws TskCoreException {
332 if (StringUtils.isNotBlank(accountUniqueID)) {
334 AccountFileInstance contactAccountInstance = createAccountInstance(accountType, accountUniqueID);
338 getSleuthkitCase().getCommunicationsManager().addRelationships(getSelfAccountInstance(),
341 throw new TskCoreException(String.format(
"Failed to create relationship between account = %s and account = %s.",
342 getSelfAccountInstance().getAccount(), contactAccountInstance.
getAccount()), ex);
345 catch (InvalidAccountIDException ex) {
346 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", accountUniqueID), ex);
363 private AccountFileInstance createAccountInstance(Account.Type accountType, String accountUniqueID)
throws TskCoreException, InvalidAccountIDException {
364 return getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(accountType, accountUniqueID, getModuleName(), getContent());
394 String subject, String messageText, String threadId)
throws TskCoreException,
BlackboardException {
396 senderId, recipientId, dateTime, readStatus,
397 subject, messageText, threadId,
398 Collections.emptyList());
428 String messageText, String threadId,
429 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
433 Arrays.asList(recipientId),
434 dateTime, readStatus,
435 subject, messageText, threadId,
436 otherAttributesList);
464 List<String> recipientIdsList,
466 String subject, String messageText, String threadId)
throws TskCoreException,
BlackboardException {
468 senderId, recipientIdsList,
469 dateTime, readStatus,
470 subject, messageText, threadId,
471 Collections.emptyList());
499 List<String> recipientIdsList,
501 String subject, String messageText,
503 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
507 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
516 addMessageReadStatusIfKnown(readStatus, attributes);
517 addCommDirectionIfKnown(direction, attributes);
522 selfAccountInstanceLocal = getSelfAccountInstance();
524 LOGGER.log(Level.WARNING, String.format(
"Failed to get/create self account with id %s", selfAccountId), ex);
529 if (StringUtils.isNotBlank(senderId)) {
531 senderAccountInstance = createAccountInstance(moduleAccountsType, senderId);
533 LOGGER.log(Level.WARNING, String.format(
"Invalid account identifier %s", senderId), ex);
539 List<AccountFileInstance> recipientAccountsList =
new ArrayList<>();
540 String recipientsStr =
"";
541 if (!isEffectivelyEmpty(recipientIdsList)) {
542 for (String recipient : recipientIdsList) {
543 if (StringUtils.isNotBlank(recipient)) {
545 recipientAccountsList.add(createAccountInstance(moduleAccountsType, recipient));
547 LOGGER.log(Level.WARNING, String.format(
"Invalid account identifier %s", senderId), ex);
552 recipientsStr = addressListToString(recipientIdsList);
558 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
559 senderAccountInstance = selfAccountInstanceLocal;
562 if (senderAccountInstance != null) {
571 if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null ) {
573 recipientAccountsList.add(selfAccountInstanceLocal);
576 if (senderAccountInstance != null) {
583 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null ) {
585 senderAccountInstance = selfAccountInstanceLocal;
587 else if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
590 recipientAccountsList.add(selfAccountInstanceLocal);
594 if (senderAccountInstance != null) {
606 attributes.addAll(otherAttributesList);
607 msgArtifact.addAttributes(attributes);
611 getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance,
614 throw new TskCoreException(String.format(
"Failed to create Message relationships between sender account = %s and recipients = %s.",
619 getSleuthkitCase().getBlackboard().postArtifact(msgArtifact, getModuleName());
648 String callerId, String calleeId,
650 return addCalllog(direction, callerId, calleeId,
651 startDateTime, endDateTime, mediaType,
652 Collections.emptyList());
681 long startDateTime,
long endDateTime,
683 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
686 Arrays.asList(calleeId),
687 startDateTime, endDateTime,
689 otherAttributesList);
716 Collection<String> calleeIdsList,
717 long startDateTime,
long endDateTime,
720 return addCalllog(direction, callerId, calleeIdsList,
721 startDateTime, endDateTime,
723 Collections.emptyList());
751 Collection<String> calleeIdsList,
752 long startDateTime,
long endDateTime,
754 Collection<BlackboardAttribute> otherAttributesList)
throws TskCoreException,
BlackboardException {
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.");
763 selfAccountInstanceLocal = getSelfAccountInstance();
765 LOGGER.log(Level.WARNING, String.format(
"Failed to get/create self account with id %s", selfAccountId), ex);
769 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
777 addCommDirectionIfKnown(direction, attributes);
780 if (StringUtils.isNotBlank(callerId)) {
782 callerAccountInstance = createAccountInstance(moduleAccountsType, callerId);
784 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", callerId), ex);
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)) {
796 recipientAccountsList.add(createAccountInstance(moduleAccountsType, callee));
799 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", callerId), ex);
808 if (isEffectivelyEmpty(calleeIdsList)) {
809 throw new IllegalArgumentException(
"Callee not provided for an outgoing call.");
812 if (StringUtils.isEmpty(callerId) && selfAccountInstanceLocal != null ) {
813 callerAccountInstance = selfAccountInstanceLocal;
816 if (callerAccountInstance != null) {
825 if (StringUtils.isEmpty(callerId)) {
826 throw new IllegalArgumentException(
"Caller Id not provided for incoming call.");
829 if (isEffectivelyEmpty(calleeIdsList) && selfAccountInstanceLocal != null) {
831 recipientAccountsList.add(selfAccountInstanceLocal);
834 if (callerAccountInstance != null) {
843 if (callerAccountInstance != null) {
851 attributes.addAll(otherAttributesList);
852 callLogArtifact.addAttributes(attributes);
856 getSleuthkitCase().getCommunicationsManager().addRelationships(callerAccountInstance,
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);
864 getSleuthkitCase().getBlackboard().postArtifact(callLogArtifact, getModuleName());
867 return callLogArtifact;
882 message.addAttribute(blackboardAttribute);
885 Collection<FileAttachment> fileAttachments = attachments.getFileAttachments();
887 long attachedFileObjId = fileAttachment.getObjectId();
888 if (attachedFileObjId >= 0) {
890 associateAttachmentWithMessage(message, attachedFile);
908 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
919 private String addressListToString(Collection<String> addressList) {
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);
929 toAddresses = toAddressesSb.toString();
944 private boolean isEffectivelyEmpty(Collection<String> idList) {
946 if (idList == null || idList.isEmpty()) {
950 for (String
id : idList) {
951 if (!StringUtils.isEmpty(
id)) {
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()));
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));
984 private synchronized AccountFileInstance getSelfAccountInstance() throws TskCoreException, InvalidAccountIDException {
985 if (selfAccountInstance == null) {
986 selfAccountInstance = getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(selfAccountType, selfAccountId, this.getModuleName(), getContent());
988 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)
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)
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 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)
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