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;
 
   87                 private final String msgReadStr;
 
   90                         this.msgReadStr = readStatus;
 
  106                 private final String dirStr;
 
  125                 private final String typeStr;
 
  140         private final String selfAccountId;
 
  166                 super(caseDb, moduleName, srcContent, ingestJobId);
 
  167                 this.moduleAccountsType = accountsType;
 
  169                 this.selfAccountId = ((
DataSource) getContent().getDataSource()).getDeviceId();
 
  195                 super(caseDb, moduleName, srcContent, ingestJobId);
 
  196                 this.moduleAccountsType = accountsType;
 
  197                 this.selfAccountType = selfAccountType;
 
  198                 this.selfAccountId = selfAccountId;
 
  222                 this(caseDb, moduleName, srcContent, accountsType, null);
 
  249                 this(caseDb, moduleName, srcContent, accountsType, selfAccountType, selfAccountId, null);
 
  274                         String phoneNumber, String homePhoneNumber,
 
  277                                 homePhoneNumber, mobilePhoneNumber, emailAddr,
 
  278                                 Collections.emptyList());
 
  307                         String phoneNumber, String homePhoneNumber,
 
  308                         String mobilePhoneNumber, String emailAddr,
 
  309                         Collection<BlackboardAttribute> additionalAttributes) 
throws TskCoreException, 
BlackboardException {
 
  312                 boolean hasAnyIdAttribute = 
false;
 
  313                 if (additionalAttributes != null) {
 
  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;
 
  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.");
 
  333                 Collection<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  344                 attributes.addAll(additionalAttributes);
 
  345                 Content content = getContent();
 
  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);
 
  356                 if ((additionalAttributes != null) && hasAnyIdAttribute) {
 
  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);
 
  369                 Optional<Long> ingestJobId = getIngestJobId();
 
  370                 getSleuthkitCase().getBlackboard().postArtifact(contactArtifact, getModuleName(), ingestJobId.orElse(null));
 
  372                 return contactArtifact;
 
  383         private void createContactMethodAccountAndRelationship(
Account.
Type accountType,
 
  385                         long dateTime) 
throws TskCoreException {
 
  389                 if (StringUtils.isNotBlank(accountUniqueID)) {
 
  391                                 AccountFileInstance contactAccountInstance = createAccountInstance(accountType, accountUniqueID);
 
  395                                         getSleuthkitCase().getCommunicationsManager().addRelationships(getSelfAccountInstance(),
 
  398                                         throw new TskCoreException(String.format(
"Failed to create relationship between account = %s and account = %s.",
 
  399                                                         getSelfAccountInstance().getAccount(), contactAccountInstance.
getAccount()), ex);
 
  401                         } 
catch (InvalidAccountIDException ex) {
 
  402                                 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", accountUniqueID));
 
  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));
 
  451                         String subject, String messageText, String threadId) 
throws TskCoreException, 
BlackboardException {
 
  453                                 senderId, recipientId, dateTime, readStatus,
 
  454                                 subject, messageText, threadId,
 
  455                                 Collections.emptyList());
 
  485                         String messageText, String threadId,
 
  486                         Collection<BlackboardAttribute> otherAttributesList) 
throws TskCoreException, 
BlackboardException {
 
  490                                 Arrays.asList(recipientId),
 
  491                                 dateTime, readStatus,
 
  492                                 subject, messageText, threadId,
 
  493                                 otherAttributesList);
 
  521                         List<String> recipientIdsList,
 
  523                         String subject, String messageText, String threadId) 
throws TskCoreException, 
BlackboardException {
 
  525                                 senderId, recipientIdsList,
 
  526                                 dateTime, readStatus,
 
  527                                 subject, messageText, threadId,
 
  528                                 Collections.emptyList());
 
  556                         List<String> recipientIdsList,
 
  558                         String subject, String messageText,
 
  560                         Collection<BlackboardAttribute> otherAttributesList) 
throws TskCoreException, 
BlackboardException {
 
  563                 Collection<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  569                 addMessageReadStatusIfKnown(readStatus, attributes);
 
  570                 addCommDirectionIfKnown(direction, attributes);
 
  575                         selfAccountInstanceLocal = getSelfAccountInstance();
 
  577                         LOGGER.log(Level.WARNING, String.format(
"Failed to get/create self account with id %s", selfAccountId), ex);
 
  582                 if (StringUtils.isNotBlank(senderId)) {
 
  584                                 senderAccountInstance = createAccountInstance(moduleAccountsType, senderId);
 
  586                                 LOGGER.log(Level.WARNING, String.format(
"Invalid account identifier %s", senderId));
 
  591                 List<AccountFileInstance> recipientAccountsList = 
new ArrayList<>();
 
  592                 String recipientsStr = 
"";
 
  593                 if (!isEffectivelyEmpty(recipientIdsList)) {
 
  594                         for (String recipient : recipientIdsList) {
 
  595                                 if (StringUtils.isNotBlank(recipient)) {
 
  597                                                 recipientAccountsList.add(createAccountInstance(moduleAccountsType, recipient));
 
  599                                                 LOGGER.log(Level.WARNING, String.format(
"Invalid account identifier %s", recipient));
 
  604                         recipientsStr = addressListToString(recipientIdsList);
 
  610                                 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
 
  611                                         senderAccountInstance = selfAccountInstanceLocal;
 
  614                                 if (senderAccountInstance != null) {
 
  623                                 if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
 
  625                                         recipientAccountsList.add(selfAccountInstanceLocal);
 
  628                                 if (senderAccountInstance != null) {
 
  635                                 if (StringUtils.isEmpty(senderId) && selfAccountInstanceLocal != null) {
 
  637                                         senderAccountInstance = selfAccountInstanceLocal;
 
  638                                 } 
else if (isEffectivelyEmpty(recipientIdsList) && selfAccountInstanceLocal != null) {
 
  641                                         recipientAccountsList.add(selfAccountInstanceLocal);
 
  645                                 if (senderAccountInstance != null) {
 
  657                 attributes.addAll(otherAttributesList);
 
  660                 Content content = getContent();
 
  665                         getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance,
 
  668                         throw new TskCoreException(String.format(
"Failed to create Message relationships between sender account = %s and recipients = %s.",
 
  673                 Optional<Long> ingestJobId = getIngestJobId();
 
  674                 getSleuthkitCase().getBlackboard().postArtifact(msgArtifact, getModuleName(), ingestJobId.orElse(null));
 
  703                         String callerId, String calleeId,
 
  705                 return addCalllog(direction, callerId, calleeId,
 
  706                                 startDateTime, endDateTime, mediaType,
 
  707                                 Collections.emptyList());
 
  736                         long startDateTime, 
long endDateTime,
 
  738                         Collection<BlackboardAttribute> otherAttributesList) 
throws TskCoreException, 
BlackboardException {
 
  741                                 Arrays.asList(calleeId),
 
  742                                 startDateTime, endDateTime,
 
  744                                 otherAttributesList);
 
  771                         Collection<String> calleeIdsList,
 
  772                         long startDateTime, 
long endDateTime,
 
  775                 return addCalllog(direction, callerId, calleeIdsList,
 
  776                                 startDateTime, endDateTime,
 
  778                                 Collections.emptyList());
 
  806                         Collection<String> calleeIdsList,
 
  807                         long startDateTime, 
long endDateTime,
 
  809                         Collection<BlackboardAttribute> otherAttributesList) 
throws TskCoreException, 
BlackboardException {
 
  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.");
 
  818                         selfAccountInstanceLocal = getSelfAccountInstance();
 
  820                         LOGGER.log(Level.WARNING, String.format(
"Failed to get/create self account with id %s", selfAccountId), ex);
 
  823                 Collection<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  828                 addCommDirectionIfKnown(direction, attributes);
 
  831                 if (StringUtils.isNotBlank(callerId)) {
 
  833                                 callerAccountInstance = createAccountInstance(moduleAccountsType, callerId);
 
  835                                 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", callerId));
 
  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)) {
 
  847                                                 recipientAccountsList.add(createAccountInstance(moduleAccountsType, callee));
 
  849                                                 LOGGER.log(Level.WARNING, String.format(
"Failed to create account with id %s", callee));
 
  858                                 if (isEffectivelyEmpty(calleeIdsList)) {
 
  859                                         throw new IllegalArgumentException(
"Callee not provided for an outgoing call.");
 
  862                                 if (StringUtils.isEmpty(callerId) && selfAccountInstanceLocal != null) {
 
  863                                         callerAccountInstance = selfAccountInstanceLocal;
 
  866                                 if (callerAccountInstance != null) {
 
  875                                 if (StringUtils.isEmpty(callerId)) {
 
  876                                         throw new IllegalArgumentException(
"Caller Id not provided for incoming call.");
 
  879                                 if (isEffectivelyEmpty(calleeIdsList) && selfAccountInstanceLocal != null) {
 
  881                                         recipientAccountsList.add(selfAccountInstanceLocal);
 
  884                                 if (callerAccountInstance != null) {
 
  893                                 if (callerAccountInstance != null) {
 
  901                 attributes.addAll(otherAttributesList);
 
  903                 Content content = getContent();
 
  910                         getSleuthkitCase().getCommunicationsManager().addRelationships(callerAccountInstance,
 
  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);
 
  918                 Optional<Long> ingestJobId = getIngestJobId();
 
  919                 getSleuthkitCase().getBlackboard().postArtifact(callLogArtifact, getModuleName(), ingestJobId.orElse(null));
 
  922                 return callLogArtifact;
 
  936                 message.addAttribute(blackboardAttribute);
 
  939                 List<BlackboardArtifact> assocObjectArtifacts = 
new ArrayList<>();
 
  940                 Collection<FileAttachment> fileAttachments = attachments.getFileAttachments();
 
  942                         long attachedFileObjId = fileAttachment.getObjectId();
 
  943                         if (attachedFileObjId >= 0) {
 
  945                                 DataArtifact artifact = associateAttachmentWithMessage(message, attachedFile);
 
  946                                 assocObjectArtifacts.add(artifact);
 
  951                         Optional<Long> ingestJobId = getIngestJobId();
 
  952                         getSleuthkitCase().getBlackboard().postArtifacts(assocObjectArtifacts, getModuleName(), ingestJobId.orElse(null));
 
  954                         throw new TskCoreException(
"Error posting TSK_ASSOCIATED_ARTIFACT artifacts for attachments", ex);
 
  971                 Collection<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  979         private String addressListToString(Collection<String> addressList) {
 
  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);
 
  989                         toAddresses = toAddressesSb.toString();
 
 1004         private boolean isEffectivelyEmpty(Collection<String> idList) {
 
 1006                 if (idList == null || idList.isEmpty()) {
 
 1010                 for (String 
id : idList) {
 
 1011                         if (!StringUtils.isEmpty(
id)) {
 
 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()));
 
 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));
 
 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));
 
 1051                 return selfAccountInstance;
 
READ
message has not been read 
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Long ingestJobId)
CommunicationArtifactsHelper(SleuthkitCase caseDb, String moduleName, Content srcContent, Account.Type accountsType, Account.Type selfAccountType, String selfAccountId, Long ingestJobId)
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