예제 #1
0
파일: zapya.py 프로젝트: dannysmyda/autopsy
    def analyze(self, dataSource, fileManager, context):
        transferDbs = AppSQLiteDB.findAppDatabases(dataSource, "transfer20.db", True, self._PACKAGE_NAME)
        for transferDb in transferDbs:
            try:
                current_case = Case.getCurrentCaseThrows()
                # 
                transferDbHelper = CommunicationArtifactsHelper(current_case.getSleuthkitCase(),
                                    self._MODULE_NAME, transferDb.getDBFile(),
                                    Account.Type.ZAPYA)

                queryString = "SELECT device, name, direction, createtime, path, title FROM transfer"
                transfersResultSet = transferDb.runQuery(queryString)
                if transfersResultSet is not None:
                    while transfersResultSet.next():
                        direction = CommunicationDirection.UNKNOWN
                        fromId = None
                        toId = None
                        fileAttachments = ArrayList()
                    
                        if (transfersResultSet.getInt("direction") == 1):
                            direction = CommunicationDirection.OUTGOING
                            toId = transfersResultSet.getString("device")
                        else:
                            direction = CommunicationDirection.INCOMING
                            fromId = transfersResultSet.getString("device")
                        
                        timeStamp = transfersResultSet.getLong("createtime") / 1000
                        messageArtifact = transferDbHelper.addMessage( 
                                                            self._MESSAGE_TYPE,
                                                            direction,
                                                            fromId,
                                                            toId,
                                                            timeStamp,
                                                            MessageReadStatus.UNKNOWN,
                                                            None,   # subject
                                                            None,   # message Text
                                                            None )    # thread id
                                                                                                
                        # add the file as attachment 
                        fileAttachments.add(FileAttachment(current_case.getSleuthkitCase(), transferDb.getDBFile().getDataSource(), transfersResultSet.getString("path")))
                        messageAttachments = MessageAttachments(fileAttachments, [])
                        transferDbHelper.addAttachments(messageArtifact, messageAttachments)

            except SQLException as ex:
                self._logger.log(Level.WARNING, "Error processing query result for transfer.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(Level.SEVERE, "Failed to create Zapya message artifacts.", ex)
                self._logger.log(Level.SEVERE, traceback.format_exc())
            except BlackboardException as ex:
                self._logger.log(Level.WARNING, "Failed to post artifacts.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except NoCurrentCaseException as ex:
                self._logger.log(Level.WARNING, "No case currently open.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            finally:
                transferDb.close()
예제 #2
0
    def parse_messages(self, skype_db, helper, current_case):
        #Query for messages and iterate row by row adding
        #each message artifact
        try:
            messages_parser = SkypeMessagesParser(skype_db)
            while messages_parser.next():
                message_artifact = helper.addMessage(
                    messages_parser.get_message_type(),
                    messages_parser.get_message_direction(),
                    messages_parser.get_phone_number_from(),
                    messages_parser.get_phone_number_to(),
                    messages_parser.get_message_date_time(),
                    messages_parser.get_message_read_status(),
                    messages_parser.get_message_subject(),
                    messages_parser.get_message_text(),
                    messages_parser.get_thread_id())

                if (messages_parser.get_file_attachment() is not None):
                    file_attachments = ArrayList()
                    file_attachments.add(
                        FileAttachment(current_case.getSleuthkitCase(),
                                       skype_db.getDBFile().getDataSource(),
                                       messages_parser.get_file_attachment()))
                    message_attachments = MessageAttachments(
                        file_attachments, [])
                    helper.addAttachments(message_artifact,
                                          message_attachments)

            messages_parser.close()
        except SQLException as ex:
            #Error parsing Skype db
            self._logger.log(
                Level.WARNING,
                "Error parsing Skype database for message artifacts.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
            #Severe error trying to add to case database.. case is not complete.
            #These exceptions are thrown by the CommunicationArtifactsHelper.
            self._logger.log(
                Level.SEVERE,
                "Failed to add message artifacts to the case database.", ex)
            self._logger.log(Level.SEVERE, traceback.format_exc())
        except BlackboardException as ex:
            #Failed to post notification to blackboard
            self._logger.log(
                Level.WARNING,
                "Failed to post message artifact to the blackboard", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
예제 #3
0
    def parse_messages(self, dataSource, messages_db, helper, current_case):
        try:
            messages_db.attachDatabase(dataSource, "wa.db",
                                       messages_db.getDBFile().getParentPath(),
                                       "wadb")

            messages_parser = WhatsAppMessagesParser(messages_db)
            while messages_parser.next():
                message_artifact = helper.addMessage(
                    messages_parser.get_message_type(),
                    messages_parser.get_message_direction(),
                    messages_parser.get_phone_number_from(),
                    messages_parser.get_phone_number_to(),
                    messages_parser.get_message_date_time(),
                    messages_parser.get_message_read_status(),
                    messages_parser.get_message_subject(),
                    messages_parser.get_message_text(),
                    messages_parser.get_thread_id())

                # add attachments, if any
                if (messages_parser.get_url_attachment() is not None):
                    url_attachments = ArrayList()
                    url_attachments.add(
                        URLAttachment(messages_parser.get_url_attachment()))
                    message_attachments = MessageAttachments([],
                                                             url_attachments)
                    helper.addAttachments(message_artifact,
                                          message_attachments)

            messages_parser.close()
        except SQLException as ex:
            self._logger.log(
                Level.WARNING,
                "Error querying the whatsapp database for contacts.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
            self._logger.log(
                Level.SEVERE,
                "Error adding whatsapp contact artifacts to the case database.",
                ex)
            self._logger.log(Level.SEVERE, traceback.format_exc())
        except BlackboardException as ex:
            self._logger.log(
                Level.WARNING,
                "Error posting contact artifact to the blackboard.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
예제 #4
0
파일: line.py 프로젝트: dannysmyda/autopsy
    def parse_messages(self, messages_db, helper, current_case):
        try:

            messages_parser = LineMessagesParser(messages_db)
            while messages_parser.next():
                message_artifact = helper.addMessage(
                    messages_parser.get_message_type(),
                    messages_parser.get_message_direction(),
                    messages_parser.get_phone_number_from(),
                    messages_parser.get_phone_number_to(),
                    messages_parser.get_message_date_time(),
                    messages_parser.get_message_read_status(),
                    messages_parser.get_message_subject(),
                    messages_parser.get_message_text(),
                    messages_parser.get_thread_id())
                if (messages_parser.get_file_attachment() is not None):
                    file_attachments = ArrayList()
                    file_attachments.add(
                        FileAttachment(current_case.getSleuthkitCase(),
                                       messages_db.getDBFile().getDataSource(),
                                       messages_parser.get_file_attachment()))
                    message_attachments = MessageAttachments(
                        file_attachments, [])
                    helper.addAttachments(message_artifact,
                                          message_attachments)

            messages_parser.close()
        except SQLException as ex:
            self._logger.log(
                Level.WARNING,
                "Error parsing the Line App Database for messages.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
            #Error adding artifact to case database... case is not complete.
            self._logger.log(
                Level.SEVERE,
                "Error adding Line message artifacts to the case database.",
                ex)
            self._logger.log(Level.SEVERE, traceback.format_exc())
        except BlackboardException as ex:
            #Error posting notification to blackboard
            self._logger.log(
                Level.WARNING,
                "Error posting Line message artifacts to blackboard.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
    def _newArtifactTSKMessage(self, appDbHelper, message, participants,
                               selfAccountId):
        threadId = message[0]
        dateString = message[1]
        senderId = message[2]
        messageText = message[4]
        previewURL = message[5]
        playableURL = message[6]

        formatString = "%Y-%m-%d %H:%M:%S"
        # We assume 'dateString' is in UTC/GMT
        dateTime = datetime.datetime.strptime(dateString, formatString)
        timeStruct = dateTime.timetuple()
        timestamp = int(calendar.timegm(timeStruct))

        subject = ""
        messageType = "Messenger (Beta)"
        direction = self._deduceCommunicationDirection(senderId, selfAccountId)
        recipientIdsList = [
            participantId for participantId in participants
            if participantId != senderId
        ]
        readStatus = MessageReadStatus.UNKNOWN

        artifact = appDbHelper.addMessage(messageType, direction, senderId,
                                          recipientIdsList, timestamp,
                                          readStatus, subject, messageText,
                                          threadId)

        fileAttachments = ArrayList()
        urlAttachments = ArrayList()
        if previewURL:
            urlAttachments.add(URLAttachment(previewURL))
        if playableURL:
            urlAttachments.add(URLAttachment(playableURL))
        messageAttachments = MessageAttachments(fileAttachments,
                                                urlAttachments)
        appDbHelper.addAttachments(artifact, messageAttachments)

        return artifact
예제 #6
0
    def parse_messages(self, textnow_db, helper, current_case):
        #Query for messages and iterate row by row adding
        #each message artifact
        try:
            messages_parser = TextNowMessagesParser(textnow_db)
            while messages_parser.next():
                message_artifact = helper.addMessage(
                                       messages_parser.get_message_type(),
                                       messages_parser.get_message_direction(),
                                       messages_parser.get_phone_number_from(),
                                       messages_parser.get_phone_number_to(),
                                       messages_parser.get_message_date_time(),
                                       messages_parser.get_message_read_status(),
                                       messages_parser.get_message_subject(),
                                       messages_parser.get_message_text(),
                                       messages_parser.get_thread_id()
                                   )
                if (len(messages_parser.get_file_attachment()) > 0):
                    file_attachments = ArrayList()
                    self._logger.log(Level.INFO, "SHow Attachment ==> " + str(len(messages_parser.get_file_attachment())) + " <> " + str(messages_parser.get_file_attachment()))
                    file_attachments.add(FileAttachment(current_case.getSleuthkitCase(), textnow_db.getDBFile().getDataSource(), messages_parser.get_file_attachment()))
                    message_attachments = MessageAttachments(file_attachments, [])
                    helper.addAttachments(message_artifact, message_attachments)

            messages_parser.close()
        except SQLException as ex:
            #Error parsing TextNow db
            self._logger.log(Level.WARNING, "Error parsing TextNow databases for messages.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
            #Error adding artifacts to the case database.. case database is not complete.
            self._logger.log(Level.SEVERE, 
                    "Error adding TextNow messages artifacts to the case database", ex)
            self._logger.log(Level.SEVERE, traceback.format_exc())
        except BlackboardException as ex:
            #Error posting notification to blackboard...
            self._logger.log(Level.WARNING, 
                    "Error posting TextNow messages artifact to the blackboard", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
예제 #7
0
    def analyze(self, dataSource, fileManager, context):
        historyDbs = AppSQLiteDB.findAppDatabases(dataSource, "history.db",
                                                  True, self._PACKAGE_NAME)
        for historyDb in historyDbs:
            try:
                current_case = Case.getCurrentCaseThrows()
                historyDbHelper = CommunicationArtifactsHelper(
                    current_case.getSleuthkitCase(), self._MODULE_NAME,
                    historyDb.getDBFile(), Account.Type.SHAREIT)

                queryString = """
                                SELECT history_type, device_id, device_name, description, timestamp, file_path
                                FROM history
                                JOIN item where history.content_id = item.item_id
                              """
                historyResultSet = historyDb.runQuery(queryString)
                if historyResultSet is not None:
                    while historyResultSet.next():
                        direction = ""
                        fromId = None
                        toId = None
                        fileAttachments = ArrayList()

                        if (historyResultSet.getInt("history_type") == 1):
                            direction = CommunicationDirection.INCOMING
                            fromId = historyResultSet.getString("device_id")
                        else:
                            direction = CommunicationDirection.OUTGOING
                            toId = historyResultSet.getString("device_id")

                        timeStamp = historyResultSet.getLong(
                            "timestamp") / 1000
                        messageArtifact = historyDbHelper.addMessage(
                            self._MESSAGE_TYPE,
                            direction,
                            fromId,
                            toId,
                            timeStamp,
                            MessageReadStatus.UNKNOWN,
                            None,  # subject
                            None,  # message text
                            None)  # thread id

                        # add the file as attachment
                        fileAttachments.add(
                            FileAttachment(
                                current_case.getSleuthkitCase(),
                                historyDb.getDBFile().getDataSource(),
                                historyResultSet.getString("file_path")))
                        messageAttachments = MessageAttachments(
                            fileAttachments, [])
                        historyDbHelper.addAttachments(messageArtifact,
                                                       messageAttachments)

            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for ShareIt history.", ex)
                self._logger.log(Level.SEVERE, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(
                    Level.SEVERE,
                    "Failed to create ShareIt message artifacts.", ex)
                self._logger.log(Level.SEVERE, traceback.format_exc())
            except BlackboardException as ex:
                self._logger.log(Level.WARNING, "Failed to post artifacts.",
                                 ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except NoCurrentCaseException as ex:
                self._logger.log(Level.WARNING, "No case currently open.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            finally:
                historyDb.close()
예제 #8
0
    def analyzeMessages(self, threadsDb, threadsDBHelper):
        try:

            ## Messages are found in the messages table.
            ## This query filters messages by msg_type to only get actual user created conversation messages (msg_type 0).
            ## The participant ids can be found in the thread_participants table.
            ## Participant names are found in thread_users table.
            ## Joining these tables produces multiple rows per message, one row for each recipient.
            ## The result set is processed to collect the multiple recipients for a given message.
            sqlString = """
                        SELECT msg_id, text, sender, timestamp_ms, msg_type, messages.thread_key as thread_key, 
                             snippet, thread_participants.user_key as user_key, thread_users.name as name,
                             attachments, pending_send_media_attachment
                        FROM messages
                        JOIN thread_participants ON messages.thread_key = thread_participants.thread_key
                        JOIN thread_users ON thread_participants.user_key = thread_users.user_key
                        WHERE msg_type = 0
                        ORDER BY msg_id
                        """

            messagesResultSet = threadsDb.runQuery(sqlString)
            if messagesResultSet is not None:
                oldMsgId = None

                direction = CommunicationDirection.UNKNOWN
                fromId = None
                recipientIdsList = None
                timeStamp = -1
                msgText = ""
                threadId = ""
                messageAttachments = None
                currentCase = Case.getCurrentCaseThrows()

                while messagesResultSet.next():
                    msgId = messagesResultSet.getString("msg_id")

                    # new msg begins when msgId changes
                    if msgId != oldMsgId:
                        # Create message artifact with collected attributes
                        if oldMsgId is not None:
                            messageArtifact = threadsDBHelper.addMessage(
                                self._MESSAGE_TYPE,
                                direction,
                                fromId,
                                recipientIdsList,
                                timeStamp,
                                MessageReadStatus.UNKNOWN,
                                "",  # subject
                                msgText,
                                threadId)

                            if (messageAttachments is not None):
                                threadsDBHelper.addAttachments(
                                    messageArtifact, messageAttachments)
                                messageAttachments = None

                        oldMsgId = msgId

                        # New message - collect all attributes
                        recipientIdsList = []

                        ## get sender id by parsing JSON in sender column
                        fromId = self.getSenderIdFromJson(
                            messagesResultSet.getString("sender"))
                        direction = self.deduceDirectionFromSenderId(fromId)

                        # Get recipient and add to list
                        self.addRecipientToList(
                            messagesResultSet.getString("user_key"), fromId,
                            recipientIdsList)

                        timeStamp = messagesResultSet.getLong(
                            "timestamp_ms") / 1000

                        # Get msg text
                        # Sometimes there may not be an explict msg text,
                        # but an app generated snippet instead
                        msgText = messagesResultSet.getString("text")
                        if not msgText:
                            msgText = messagesResultSet.getString("snippet")

                        # Get attachments and pending attachments if they exist
                        attachment = messagesResultSet.getString("attachments")
                        pendingAttachment = messagesResultSet.getString(
                            "pending_send_media_attachment")

                        urlAttachments = ArrayList()
                        fileAttachments = ArrayList()

                        if ((attachment is not None)
                                or (pendingAttachment is not None)):
                            if (attachment is not None):
                                attachmentDict = json.loads(attachment)[0]
                                if (attachmentDict["mime_type"] == "image/jpeg"
                                    ):
                                    urls = attachmentDict.get("urls", None)
                                    if (urls is not None):
                                        urlAttachments = self.getJPGListFromJson(
                                            urls)

                                elif (attachmentDict["mime_type"] ==
                                      "video/mp4"):
                                    # filename does not have an associated path with it so it will be ignored

                                    urls = attachmentDict.get("urls", None)
                                    if (urls is not None):
                                        urlAttachments = self.getJPGListFromJson(
                                            urls)

                                    video_data_url = attachmentDict.get(
                                        "video_data_url", None)
                                    if (video_data_url is not None):
                                        urlAttachments.add(
                                            URLAttachment(video_data_url))
                                    video_data_thumbnail_url = attachmentDict.get(
                                        "video_data_thumbnail_url", None)

                                    if (video_data_thumbnail_url is not None):
                                        urlAttachments.add(
                                            URLAttachment(
                                                video_data_thumbnail_url))
                                elif (attachmentDict["mime_type"] ==
                                      "audio/mpeg"):
                                    audioUri = attachmentDict.get(
                                        "audio_uri", None)
                                    if (audioUri is None or audioUri == ""):
                                        continue
                                    else:
                                        fileAttachments.add(
                                            FileAttachment(
                                                currentCase.getSleuthkitCase(),
                                                threadsDb.getDBFile().
                                                getDataSource(),
                                                audioUri.replace(
                                                    "file://", "")))

                                else:
                                    self._logger.log(
                                        Level.INFO,
                                        "Attachment type not handled: " +
                                        attachmentDict["mime_type"])

                            if (pendingAttachment is not None):
                                pendingAttachmentDict = json.loads(
                                    pendingAttachment)[0]
                                pendingAttachmentUri = pendingAttachmentDict.get(
                                    "uri", None)
                                if (pendingAttachmentUri is not None):
                                    fileAttachments.add(
                                        FileAttachment(
                                            currentCase.getSleuthkitCase(),
                                            threadsDb.getDBFile().
                                            getDataSource(),
                                            pendingAttachmentUri.replace(
                                                "file://", "")))

                            messageAttachments = MessageAttachments(
                                fileAttachments, urlAttachments)

                        threadId = messagesResultSet.getString("thread_key")

                    else:  # same msgId as last, just collect recipient from current row
                        self.addRecipientToList(
                            messagesResultSet.getString("user_key"), fromId,
                            recipientIdsList)

                # at the end of the loop, add last message
                messageArtifact = threadsDBHelper.addMessage(
                    self._MESSAGE_TYPE,
                    direction,
                    fromId,
                    recipientIdsList,
                    timeStamp,
                    MessageReadStatus.UNKNOWN,
                    "",  # subject
                    msgText,
                    threadId)

        except SQLException as ex:
            self._logger.log(
                Level.WARNING,
                "Error processing query result for FB Messenger messages.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
            self._logger.log(Level.SEVERE,
                             "Failed to add FB Messenger message artifacts.",
                             ex)
            self._logger.log(Level.SEVERE, traceback.format_exc())
        except BlackboardException as ex:
            self._logger.log(Level.WARNING, "Failed to post artifacts.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
예제 #9
0
    def analyze(self, dataSource, fileManager, context):
        selfAccountId = None
        transactionDbs = AppSQLiteDB.findAppDatabases(dataSource,
                                                      "trans-history-db", True,
                                                      self._PACKAGE_NAME)
        for transactionDb in transactionDbs:
            try:
                current_case = Case.getCurrentCaseThrows()
                # get the profile with connection_times 0, that's the self account.
                profilesResultSet = transactionDb.runQuery(
                    "SELECT device_id, nick_name FROM profile WHERE connect_times = 0"
                )
                if profilesResultSet:
                    while profilesResultSet.next():
                        if not selfAccountId:
                            selfAccountId = profilesResultSet.getString(
                                "device_id")
                # create artifacts helper
                if selfAccountId is not None:
                    transactionDbHelper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._MODULE_NAME,
                        transactionDb.getDBFile(), Account.Type.XENDER,
                        Account.Type.XENDER, selfAccountId)
                else:
                    transactionDbHelper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._MODULE_NAME,
                        transactionDb.getDBFile(), Account.Type.XENDER)

                queryString = """
                                SELECT f_path, f_display_name, f_size_str, c_start_time, c_direction, c_session_id,
                                    s_name, s_device_id, r_name, r_device_id
                                FROM new_history
                              """
                messagesResultSet = transactionDb.runQuery(queryString)
                if messagesResultSet is not None:
                    while messagesResultSet.next():
                        direction = CommunicationDirection.UNKNOWN
                        fromId = None
                        toId = None

                        fileAttachments = ArrayList()

                        if (messagesResultSet.getInt("c_direction") == 1):
                            direction = CommunicationDirection.OUTGOING
                            toId = messagesResultSet.getString("r_device_id")
                        else:
                            direction = CommunicationDirection.INCOMING
                            fromId = messagesResultSet.getString("s_device_id")

                        timeStamp = messagesResultSet.getLong(
                            "c_start_time") / 1000
                        messageArtifact = transactionDbHelper.addMessage(
                            self._MESSAGE_TYPE,
                            direction,
                            fromId,
                            toId,
                            timeStamp,
                            MessageReadStatus.UNKNOWN,
                            None,  # subject
                            None,  # message text
                            messagesResultSet.getString("c_session_id"))

                        # add the file as attachment
                        fileAttachments.add(
                            FileAttachment(
                                current_case.getSleuthkitCase(),
                                transactionDb.getDBFile().getDataSource(),
                                messagesResultSet.getString("f_path")))
                        messageAttachments = MessageAttachments(
                            fileAttachments, [])
                        transactionDbHelper.addAttachments(
                            messageArtifact, messageAttachments)

            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for profiles.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(Level.SEVERE,
                                 "Failed to create Xender message artifacts.",
                                 ex)
                self._logger.log(Level.SEVERE, traceback.format_exc())
            except BlackboardException as ex:
                self._logger.log(Level.WARNING, "Failed to post artifacts.",
                                 ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except NoCurrentCaseException as ex:
                self._logger.log(Level.WARNING, "No case currently open.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            finally:
                transactionDb.close()
예제 #10
0
파일: imo.py 프로젝트: dannysmyda/autopsy
    def analyze(self, dataSource, fileManager, context):
        selfAccountId = None
        accountDbs = AppSQLiteDB.findAppDatabases(dataSource, "accountdb.db",
                                                  True, self._PACKAGE_NAME)
        for accountDb in accountDbs:
            try:
                accountResultSet = accountDb.runQuery(
                    "SELECT uid, name FROM account")
                if accountResultSet:
                    # We can determine the IMO user ID of the device owner.
                    # Therefore we can create and use a app account and use that
                    # as a 'self' account instead of a Device account
                    if not selfAccountId:
                        selfAccountId = accountResultSet.getString("uid")

            except SQLException as ex:
                self._logger.log(Level.WARNING,
                                 "Error processing query result for account",
                                 ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            finally:
                accountDb.close()

        friendsDbs = AppSQLiteDB.findAppDatabases(dataSource, "imofriends.db",
                                                  True, self._PACKAGE_NAME)
        for friendsDb in friendsDbs:
            try:
                current_case = Case.getCurrentCaseThrows()
                if selfAccountId is not None:
                    friendsDBHelper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._PARSER_NAME,
                        friendsDb.getDBFile(), Account.Type.IMO,
                        Account.Type.IMO, selfAccountId)
                else:
                    friendsDBHelper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._PARSER_NAME,
                        friendsDb.getDBFile(), Account.Type.IMO)
                contactsResultSet = friendsDb.runQuery(
                    "SELECT buid, name FROM friends")
                if contactsResultSet is not None:
                    while contactsResultSet.next():
                        contactId = contactsResultSet.getString("buid")

                        ## add a  TSK_ID attribute with contact's IMO Id
                        additionalAttributes = ArrayList()
                        additionalAttributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID,
                                self._PARSER_NAME, contactId))

                        friendsDBHelper.addContact(
                            contactsResultSet.getString(
                                "name"),  ##  contact name
                            "",  ## phone
                            "",  ## home phone
                            "",  ## mobile
                            "",  ## email
                            additionalAttributes)

                queryString = """
                                SELECT messages.buid AS buid, imdata, last_message, timestamp, message_type, message_read, name
                                FROM messages
                                INNER JOIN friends ON friends.buid = messages.buid
                              """
                messagesResultSet = friendsDb.runQuery(queryString)
                if messagesResultSet is not None:
                    while messagesResultSet.next():
                        direction = ""
                        fromId = None
                        toId = None
                        name = messagesResultSet.getString("name")
                        uniqueId = messagesResultSet.getString("buid")

                        if (messagesResultSet.getInt("message_type") == 1):
                            direction = CommunicationDirection.INCOMING
                            fromId = uniqueId
                        else:
                            direction = CommunicationDirection.OUTGOING
                            toId = uniqueId

                        message_read = messagesResultSet.getInt("message_read")
                        if (message_read == 1):
                            msgReadStatus = MessageReadStatus.READ
                        elif (message_read == 0):
                            msgReadStatus = MessageReadStatus.UNREAD
                        else:
                            msgReadStatus = MessageReadStatus.UNKNOWN

                        timeStamp = messagesResultSet.getLong(
                            "timestamp") / 1000000000
                        msgBody = messagesResultSet.getString("last_message")

                        messageArtifact = friendsDBHelper.addMessage(
                            self._MESSAGE_TYPE,
                            direction,
                            fromId,
                            toId,
                            timeStamp,
                            msgReadStatus,
                            "",  # subject
                            msgBody,
                            "")  # thread id

                        # Parse the imdata JSON structure to check if there is an attachment.
                        # If one exists, create an attachment and add to the message.
                        fileAttachments = ArrayList()
                        urlAttachments = ArrayList()

                        imdataJsonStr = messagesResultSet.getString("imdata")
                        if imdataJsonStr is not None:
                            imdata_dict = json.loads(imdataJsonStr)

                            # set to none if the key doesn't exist in the dict
                            attachmentOriginalPath = imdata_dict.get(
                                'original_path', None)
                            attachmentLocalPath = imdata_dict.get(
                                'local_path', None)
                            if attachmentOriginalPath:
                                attachmentPath = attachmentOriginalPath
                            else:
                                attachmentPath = attachmentLocalPath

                            if attachmentPath:
                                # Create a file attachment with given path
                                fileAttachment = FileAttachment(
                                    current_case.getSleuthkitCase(),
                                    friendsDb.getDBFile().getDataSource(),
                                    attachmentPath)
                                fileAttachments.add(fileAttachment)

                                msgAttachments = MessageAttachments(
                                    fileAttachments, [])
                                attachmentArtifact = friendsDBHelper.addAttachments(
                                    messageArtifact, msgAttachments)

            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for IMO friends", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(Level.SEVERE,
                                 "Failed to add IMO message artifacts.", ex)
                self._logger.log(Level.SEVERE, traceback.format_exc())
            except BlackboardException as ex:
                self._logger.log(Level.WARNING, "Failed to post artifacts.",
                                 ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except NoCurrentCaseException as ex:
                self._logger.log(Level.WARNING, "No case currently open.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            finally:
                friendsDb.close()