mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge pull request #5362 from dannysmyda/5682-simplify-app-db-queries
5682 simplify app db queries
This commit is contained in:
commit
bc21a24caf
@ -236,28 +236,23 @@ class LineCallLogsParser(TskCallLogsParser):
|
||||
def __init__(self, calllog_db):
|
||||
super(LineCallLogsParser, self).__init__(calllog_db.runQuery(
|
||||
"""
|
||||
SELECT Substr(CH.call_type, -1) AS direction,
|
||||
CH.start_time AS start_time,
|
||||
CH.end_time AS end_time,
|
||||
contacts_list_with_groups.members AS group_members,
|
||||
contacts_list_with_groups.member_names AS names,
|
||||
CH.caller_mid,
|
||||
CH.voip_type AS call_type,
|
||||
CH.voip_gc_media_type AS group_call_type
|
||||
SELECT Substr(calls.call_type, -1) AS direction,
|
||||
calls.start_time AS start_time,
|
||||
calls.end_time AS end_time,
|
||||
contact_book_w_groups.members AS group_members,
|
||||
calls.caller_mid,
|
||||
calls.voip_type AS call_type,
|
||||
calls.voip_gc_media_type AS group_call_type
|
||||
FROM (SELECT id,
|
||||
Group_concat(M.m_id) AS members,
|
||||
Group_concat(Replace(C.server_name, ",", "")) AS member_names
|
||||
Group_concat(M.m_id) AS members
|
||||
FROM membership AS M
|
||||
JOIN naver.contacts AS C
|
||||
ON M.m_id = C.m_id
|
||||
GROUP BY id
|
||||
UNION
|
||||
SELECT m_id,
|
||||
NULL,
|
||||
server_name
|
||||
FROM naver.contacts) AS contacts_list_with_groups
|
||||
JOIN call_history AS CH
|
||||
ON CH.caller_mid = contacts_list_with_groups.id
|
||||
NULL
|
||||
FROM naver.contacts) AS contact_book_w_groups
|
||||
JOIN call_history AS calls
|
||||
ON calls.caller_mid = contact_book_w_groups.id
|
||||
"""
|
||||
)
|
||||
)
|
||||
@ -355,42 +350,24 @@ class LineMessagesParser(TskMessagesParser):
|
||||
def __init__(self, message_db):
|
||||
super(LineMessagesParser, self).__init__(message_db.runQuery(
|
||||
"""
|
||||
SELECT contact_list_with_groups.name,
|
||||
contact_list_with_groups.id,
|
||||
contact_list_with_groups.members,
|
||||
contact_list_with_groups.member_names,
|
||||
CH.from_mid,
|
||||
C.server_name AS from_name,
|
||||
CH.content,
|
||||
CH.created_time,
|
||||
CH.attachement_type,
|
||||
CH.attachement_local_uri,
|
||||
CH.status
|
||||
FROM (SELECT G.name,
|
||||
group_members.id,
|
||||
group_members.members,
|
||||
group_members.member_names
|
||||
SELECT contact_book_w_groups.id,
|
||||
contact_book_w_groups.members,
|
||||
messages.from_mid,
|
||||
messages.content,
|
||||
messages.created_time,
|
||||
messages.attachement_type,
|
||||
messages.attachement_local_uri,
|
||||
messages.status
|
||||
FROM (SELECT id,
|
||||
group_concat(M.m_id) AS members,
|
||||
group_concat(replace(C.server_name,
|
||||
",",
|
||||
"")) as member_names
|
||||
Group_concat(M.m_id) AS members
|
||||
FROM membership AS M
|
||||
JOIN contacts as C
|
||||
ON M.m_id = C.m_id
|
||||
GROUP BY id) AS group_members
|
||||
JOIN groups AS G
|
||||
ON G.id = group_members.id
|
||||
GROUP BY id
|
||||
UNION
|
||||
SELECT server_name,
|
||||
m_id,
|
||||
NULL,
|
||||
SELECT m_id,
|
||||
NULL
|
||||
FROM contacts) AS contact_list_with_groups
|
||||
JOIN chat_history AS CH
|
||||
ON CH.chat_id = contact_list_with_groups.id
|
||||
LEFT JOIN contacts as C
|
||||
ON C.m_id = CH.from_mid
|
||||
FROM contacts) AS contact_book_w_groups
|
||||
JOIN chat_history AS messages
|
||||
ON messages.chat_id = contact_book_w_groups.id
|
||||
WHERE attachement_type != 6
|
||||
"""
|
||||
)
|
||||
|
@ -76,11 +76,8 @@ class SkypeAnalyzer(general.AndroidComponentAnalyzer):
|
||||
as they would be excluded in the join. Since the chatItem table stores both the
|
||||
group id or skype_id in one column, an implementation decision was made to union
|
||||
the person and particiapnt table together so that all rows are matched in one join
|
||||
with chatItem. This result is consistently labeled contact_list_with_groups in the
|
||||
with chatItem. This result is consistently labeled contact_book_w_groups in the
|
||||
following queries.
|
||||
- In order to keep the formatting of the name consistent throughout each query,
|
||||
a _format_user_name() function was created to encapsulate the CASE statement
|
||||
that was being shared across them. Refer to the method for more details.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
@ -93,7 +90,12 @@ class SkypeAnalyzer(general.AndroidComponentAnalyzer):
|
||||
account_query_result = skype_db.runQuery(
|
||||
"""
|
||||
SELECT entry_id,
|
||||
"""+_format_user_name()+""" AS name
|
||||
CASE
|
||||
WHEN Ifnull(first_name, "") == "" AND Ifnull(last_name, "") == "" THEN entry_id
|
||||
WHEN first_name is NULL THEN replace(last_name, ",", "")
|
||||
WHEN last_name is NULL THEN replace(first_name, ",", "")
|
||||
ELSE replace(first_name, ",", "") || " " || replace(last_name, ",", "")
|
||||
END AS name
|
||||
FROM user
|
||||
"""
|
||||
)
|
||||
@ -251,14 +253,6 @@ class SkypeCallLogsParser(TskCallLogsParser):
|
||||
|
||||
def __init__(self, calllog_db):
|
||||
"""
|
||||
Big picture:
|
||||
The query below creates a contacts_list_with_groups table, which
|
||||
represents the recipient info. A chatItem record holds ids for
|
||||
both the recipient and sender. The first join onto chatItem fills
|
||||
in the blanks for the recipients. The second join back onto person
|
||||
handles the sender info. The result is a table with all of the
|
||||
communication details.
|
||||
|
||||
Implementation details:
|
||||
- message_type w/ value 3 appeared to be the call type, regardless
|
||||
of if it was audio or video.
|
||||
@ -266,36 +260,22 @@ class SkypeCallLogsParser(TskCallLogsParser):
|
||||
"""
|
||||
super(SkypeCallLogsParser, self).__init__(calllog_db.runQuery(
|
||||
"""
|
||||
SELECT contacts_list_with_groups.conversation_id,
|
||||
contacts_list_with_groups.participant_ids,
|
||||
contacts_list_with_groups.participants,
|
||||
time,
|
||||
duration,
|
||||
is_sender_me,
|
||||
person_id as sender_id,
|
||||
sender_name.name as sender_name
|
||||
SELECT contact_book_w_groups.conversation_id,
|
||||
contact_book_w_groups.participant_ids,
|
||||
messages.time,
|
||||
messages.duration,
|
||||
messages.is_sender_me,
|
||||
messages.person_id AS sender_id
|
||||
FROM (SELECT conversation_id,
|
||||
Group_concat(person_id) AS participant_ids,
|
||||
Group_concat("""+_format_user_name()+""") AS participants
|
||||
FROM particiapnt AS PART
|
||||
JOIN person AS P
|
||||
ON PART.person_id = P.entry_id
|
||||
Group_concat(person_id) AS participant_ids
|
||||
FROM particiapnt
|
||||
GROUP BY conversation_id
|
||||
UNION
|
||||
SELECT entry_id,
|
||||
NULL,
|
||||
"""+_format_user_name()+""" AS participant
|
||||
FROM person) AS contacts_list_with_groups
|
||||
JOIN chatitem AS C
|
||||
ON C.conversation_link = contacts_list_with_groups.conversation_id
|
||||
JOIN (SELECT entry_id as id,
|
||||
"""+_format_user_name()+""" AS name
|
||||
FROM person
|
||||
UNION
|
||||
SELECT entry_id as id,
|
||||
"""+_format_user_name()+""" AS name
|
||||
FROM user) AS sender_name
|
||||
ON sender_name.id = C.person_id
|
||||
SELECT entry_id AS conversation_id,
|
||||
NULL
|
||||
FROM person) AS contact_book_w_groups
|
||||
join chatitem AS messages
|
||||
ON messages.conversation_link = contact_book_w_groups.conversation_id
|
||||
WHERE message_type == 3
|
||||
"""
|
||||
)
|
||||
@ -347,7 +327,12 @@ class SkypeContactsParser(TskContactsParser):
|
||||
super(SkypeContactsParser, self).__init__(contact_db.runQuery(
|
||||
"""
|
||||
SELECT entry_id,
|
||||
"""+_format_user_name()+""" AS name
|
||||
CASE
|
||||
WHEN Ifnull(first_name, "") == "" AND Ifnull(last_name, "") == "" THEN entry_id
|
||||
WHEN first_name is NULL THEN replace(last_name, ",", "")
|
||||
WHEN last_name is NULL THEN replace(first_name, ",", "")
|
||||
ELSE replace(first_name, ",", "") || " " || replace(last_name, ",", "")
|
||||
END AS name
|
||||
FROM person
|
||||
"""
|
||||
)
|
||||
@ -379,37 +364,23 @@ class SkypeMessagesParser(TskMessagesParser):
|
||||
"""
|
||||
super(SkypeMessagesParser, self).__init__(message_db.runQuery(
|
||||
"""
|
||||
SELECT contacts_list_with_groups.conversation_id,
|
||||
contacts_list_with_groups.participant_ids,
|
||||
contacts_list_with_groups.participants,
|
||||
time,
|
||||
content,
|
||||
device_gallery_path,
|
||||
is_sender_me,
|
||||
person_id as sender_id,
|
||||
sender_name.name AS sender_name
|
||||
SELECT contact_book_w_groups.conversation_id,
|
||||
contact_book_w_groups.participant_ids,
|
||||
messages.time,
|
||||
messages.content,
|
||||
messages.device_gallery_path,
|
||||
messages.is_sender_me,
|
||||
messages.person_id as sender_id
|
||||
FROM (SELECT conversation_id,
|
||||
Group_concat(person_id) AS participant_ids,
|
||||
Group_concat("""+_format_user_name()+""") AS participants
|
||||
FROM particiapnt AS PART
|
||||
JOIN person AS P
|
||||
ON PART.person_id = P.entry_id
|
||||
Group_concat(person_id) AS participant_ids
|
||||
FROM particiapnt
|
||||
GROUP BY conversation_id
|
||||
UNION
|
||||
SELECT entry_id as conversation_id,
|
||||
NULL,
|
||||
"""+_format_user_name()+""" AS participant
|
||||
FROM person) AS contacts_list_with_groups
|
||||
JOIN chatitem AS C
|
||||
ON C.conversation_link = contacts_list_with_groups.conversation_id
|
||||
JOIN (SELECT entry_id as id,
|
||||
"""+_format_user_name()+""" AS name
|
||||
FROM person
|
||||
UNION
|
||||
SELECT entry_id as id,
|
||||
"""+_format_user_name()+""" AS name
|
||||
FROM user) AS sender_name
|
||||
ON sender_name.id = C.person_id
|
||||
NULL
|
||||
FROM person) AS contact_book_w_groups
|
||||
JOIN chatitem AS messages
|
||||
ON messages.conversation_link = contact_book_w_groups.conversation_id
|
||||
WHERE message_type != 3
|
||||
"""
|
||||
)
|
||||
@ -469,25 +440,3 @@ class SkypeMessagesParser(TskMessagesParser):
|
||||
if group_ids is not None:
|
||||
return self.result_set.getString("conversation_id")
|
||||
return super(SkypeMessagesParser, self).get_thread_id()
|
||||
|
||||
def _format_user_name():
|
||||
"""
|
||||
This CASE SQL statement is used in many queries to
|
||||
format the names of users. For a user, there is a first_name
|
||||
column and a last_name column. Some of these columns can be null
|
||||
and our goal is to produce the cleanest data possible. In the event
|
||||
that both the first and last name columns are null, we return the skype_id
|
||||
which is stored in the database as 'entry_id'. Commas are removed from the name
|
||||
so that we can concatenate names into a comma seperate list for group chats.
|
||||
"""
|
||||
|
||||
return """
|
||||
CASE
|
||||
WHEN Ifnull(first_name, "") == "" AND Ifnull(last_name, "") == "" THEN entry_id
|
||||
WHEN first_name is NULL THEN replace(last_name, ",", "")
|
||||
WHEN last_name is NULL THEN replace(first_name, ",", "")
|
||||
ELSE replace(first_name, ",", "") || " " || replace(last_name, ",", "")
|
||||
END
|
||||
"""
|
||||
|
||||
|
||||
|
@ -290,39 +290,37 @@ class TextNowMessagesParser(TskMessagesParser):
|
||||
"""
|
||||
super(TextNowMessagesParser, self).__init__(message_db.runQuery(
|
||||
"""
|
||||
|
||||
SELECT CASE
|
||||
WHEN message_direction == 2 THEN ""
|
||||
WHEN to_addresses IS NULL THEN M.contact_value
|
||||
ELSE contact_name
|
||||
end from_address,
|
||||
WHEN messages.message_direction == 2 THEN NULL
|
||||
WHEN contact_book_w_groups.to_addresses IS NULL THEN
|
||||
messages.contact_value
|
||||
END from_address,
|
||||
CASE
|
||||
WHEN message_direction == 1 THEN ""
|
||||
WHEN to_addresses IS NULL THEN M.contact_value
|
||||
ELSE to_addresses
|
||||
end to_address,
|
||||
message_direction,
|
||||
message_text,
|
||||
M.READ,
|
||||
M.date,
|
||||
M.attach,
|
||||
WHEN messages.message_direction == 1 THEN NULL
|
||||
WHEN contact_book_w_groups.to_addresses IS NULL THEN
|
||||
messages.contact_value
|
||||
ELSE contact_book_w_groups.to_addresses
|
||||
END to_address,
|
||||
messages.message_direction,
|
||||
messages.message_text,
|
||||
messages.READ,
|
||||
messages.DATE,
|
||||
messages.attach,
|
||||
thread_id
|
||||
FROM (SELECT group_info.contact_value,
|
||||
group_info.to_addresses,
|
||||
G.contact_value AS thread_id
|
||||
FROM (SELECT GM.contact_value,
|
||||
Group_concat(GM.member_contact_value) AS to_addresses
|
||||
Group_concat(GM.member_contact_value) AS to_addresses,
|
||||
G.contact_value AS thread_id
|
||||
FROM group_members AS GM
|
||||
GROUP BY GM.contact_value) AS group_info
|
||||
JOIN groups AS G
|
||||
ON G.contact_value = group_info.contact_value
|
||||
join GROUPS AS G
|
||||
ON G.contact_value = GM.contact_value
|
||||
GROUP BY GM.contact_value
|
||||
UNION
|
||||
SELECT c.contact_value,
|
||||
SELECT contact_value,
|
||||
NULL,
|
||||
"-1"
|
||||
FROM contacts AS c) AS to_from_map
|
||||
JOIN messages AS M
|
||||
ON M.contact_value = to_from_map.contact_value
|
||||
NULL
|
||||
FROM contacts) AS contact_book_w_groups
|
||||
join messages
|
||||
ON messages.contact_value = contact_book_w_groups.contact_value
|
||||
WHERE message_type NOT IN ( 102, 100 )
|
||||
"""
|
||||
)
|
||||
@ -330,13 +328,12 @@ class TextNowMessagesParser(TskMessagesParser):
|
||||
self._TEXTNOW_MESSAGE_TYPE = "TextNow Message"
|
||||
self._INCOMING_MESSAGE_TYPE = 1
|
||||
self._OUTGOING_MESSAGE_TYPE = 2
|
||||
self._UNKNOWN_THREAD_ID = "-1"
|
||||
|
||||
def get_message_type(self):
|
||||
return self._TEXTNOW_MESSAGE_TYPE
|
||||
|
||||
def get_phone_number_from(self):
|
||||
if self.result_set.getString("from_address") == "":
|
||||
if self.result_set.getString("from_address") is None:
|
||||
return super(TextNowMessagesParser, self).get_phone_number_from()
|
||||
return self.result_set.getString("from_address")
|
||||
|
||||
@ -347,10 +344,9 @@ class TextNowMessagesParser(TskMessagesParser):
|
||||
return self.OUTGOING
|
||||
|
||||
def get_phone_number_to(self):
|
||||
if self.result_set.getString("to_address") == "":
|
||||
if self.result_set.getString("to_address") is None:
|
||||
return super(TextNowMessagesParser, self).get_phone_number_to()
|
||||
recipients = self.result_set.getString("to_address").split(",")
|
||||
return recipients
|
||||
return self.result_set.getString("to_address").split(",")
|
||||
|
||||
def get_message_date_time(self):
|
||||
#convert ms to s
|
||||
@ -359,7 +355,7 @@ class TextNowMessagesParser(TskMessagesParser):
|
||||
def get_message_read_status(self):
|
||||
read = self.result_set.getBoolean("read")
|
||||
if self.get_message_direction() == self.INCOMING:
|
||||
if read == True:
|
||||
if read:
|
||||
return self.READ
|
||||
return self.UNREAD
|
||||
|
||||
@ -375,6 +371,6 @@ class TextNowMessagesParser(TskMessagesParser):
|
||||
|
||||
def get_thread_id(self):
|
||||
thread_id = self.result_set.getString("thread_id")
|
||||
if thread_id == self._UNKNOWN_THREAD_ID:
|
||||
if thread_id is None:
|
||||
return super(TextNowMessagesParser, self).get_thread_id()
|
||||
return thread_id
|
||||
|
@ -433,31 +433,28 @@ class WhatsAppMessagesParser(TskMessagesParser):
|
||||
def __init__(self, message_db):
|
||||
super(WhatsAppMessagesParser, self).__init__(message_db.runQuery(
|
||||
"""
|
||||
SELECT M.key_remote_jid AS id,
|
||||
contact_info.recipients,
|
||||
SELECT messages.key_remote_jid AS id,
|
||||
contact_book_w_groups.recipients,
|
||||
key_from_me AS direction,
|
||||
CASE
|
||||
WHEN M.data IS NULL THEN ""
|
||||
ELSE M.data
|
||||
END AS content,
|
||||
M.timestamp AS send_timestamp,
|
||||
M.received_timestamp,
|
||||
M.remote_resource AS group_sender,
|
||||
M.media_url As attachment
|
||||
messages.data AS content,
|
||||
messages.timestamp AS send_timestamp,
|
||||
messages.received_timestamp,
|
||||
messages.remote_resource AS group_sender,
|
||||
messages.media_url AS attachment
|
||||
FROM (SELECT jid,
|
||||
recipients
|
||||
FROM wadb.wa_contacts AS WC
|
||||
LEFT JOIN (SELECT gjid,
|
||||
group_concat(CASE
|
||||
FROM wadb.wa_contacts AS contacts
|
||||
left join (SELECT gjid,
|
||||
Group_concat(CASE
|
||||
WHEN jid == "" THEN NULL
|
||||
ELSE jid
|
||||
END) AS recipients
|
||||
FROM group_participants
|
||||
GROUP BY gjid) AS group_map
|
||||
ON WC.jid = group_map.gjid
|
||||
GROUP BY jid) AS contact_info
|
||||
JOIN messages AS M
|
||||
ON M.key_remote_jid = contact_info.jid
|
||||
GROUP BY gjid) AS groups
|
||||
ON contacts.jid = groups.gjid
|
||||
GROUP BY jid) AS contact_book_w_groups
|
||||
join messages
|
||||
ON messages.key_remote_jid = contact_book_w_groups.jid
|
||||
"""
|
||||
)
|
||||
)
|
||||
@ -503,6 +500,8 @@ class WhatsAppMessagesParser(TskMessagesParser):
|
||||
|
||||
def get_message_text(self):
|
||||
message = self.result_set.getString("content")
|
||||
if message is None:
|
||||
message = super(WhatsAppMessagesParser, self).get_message_text()
|
||||
attachment = self.result_set.getString("attachment")
|
||||
if attachment is not None:
|
||||
return general.appendAttachmentList(message, [attachment])
|
||||
|
Loading…
x
Reference in New Issue
Block a user