-
Notifications
You must be signed in to change notification settings - Fork 196
Fix database schema compatibility issues in multiple artifacts ( deviceHealthServices_Battery.py, FacebookMessenger.py, googleDuo.py, googleMessages.py, keepNotes.py , notificationHistory.py ) by 5025231128 #639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -233,28 +233,52 @@ def get_FacebookMessenger(files_found, report_folder, seeker, wrap_text): | |||||
| ''') | ||||||
| snippet = 1 | ||||||
| except: | ||||||
| cursor.execute(''' | ||||||
| select | ||||||
| case messages.timestamp_ms | ||||||
| when 0 then '' | ||||||
| else datetime(messages.timestamp_ms/1000,'unixepoch') | ||||||
| End as Datestamp, | ||||||
| (select json_extract (messages.sender, '$.name')) as "Sender", | ||||||
| substr((select json_extract (messages.sender, '$.user_key')),10) as "Sender ID", | ||||||
| messages.thread_key, | ||||||
| messages.text, | ||||||
| (select json_extract (messages.attachments, '$[0].filename')) as AttachmentName, | ||||||
| (select json_extract (messages.shares, '$[0].name')) as ShareName, | ||||||
| (select json_extract (messages.shares, '$[0].description')) as ShareDesc, | ||||||
| (select json_extract (messages.shares, '$[0].href')) as ShareLink, | ||||||
| message_reactions.reaction as "Message Reaction", | ||||||
| datetime(message_reactions.reaction_timestamp/1000,'unixepoch') as "Message Reaction Timestamp", | ||||||
| messages.msg_id | ||||||
| from messages, threads | ||||||
| left join message_reactions on message_reactions.msg_id = messages.msg_id | ||||||
| where messages.thread_key=threads.thread_key and generic_admin_message_extensible_data IS NULL and msg_type != -1 | ||||||
| order by messages.thread_key, datestamp; | ||||||
| ''') | ||||||
| try: | ||||||
| cursor.execute(''' | ||||||
| select | ||||||
| case messages.timestamp_ms | ||||||
| when 0 then '' | ||||||
| else datetime(messages.timestamp_ms/1000,'unixepoch') | ||||||
| End as Datestamp, | ||||||
| (select json_extract (messages.sender, '$.name')) as "Sender", | ||||||
| substr((select json_extract (messages.sender, '$.user_key')),10) as "Sender ID", | ||||||
| messages.thread_key, | ||||||
| messages.text, | ||||||
| (select json_extract (messages.attachments, '$[0].filename')) as AttachmentName, | ||||||
| (select json_extract (messages.shares, '$[0].name')) as ShareName, | ||||||
| (select json_extract (messages.shares, '$[0].description')) as ShareDesc, | ||||||
| (select json_extract (messages.shares, '$[0].href')) as ShareLink, | ||||||
| message_reactions.reaction as "Message Reaction", | ||||||
| datetime(message_reactions.reaction_timestamp/1000,'unixepoch') as "Message Reaction Timestamp", | ||||||
| messages.msg_id | ||||||
| from messages, threads | ||||||
| left join message_reactions on message_reactions.msg_id = messages.msg_id | ||||||
| where messages.thread_key=threads.thread_key and generic_admin_message_extensible_data IS NULL and msg_type != -1 | ||||||
| order by messages.thread_key, datestamp; | ||||||
| ''') | ||||||
| except: | ||||||
| # Fallback for databases without reaction_timestamp column | ||||||
|
||||||
| # Fallback for databases without reaction_timestamp column | |
| # Fallback for databases without message_reactions table |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bare except clause without specifying exception type. Consider catching specific exceptions like sqlite3.OperationalError or at minimum Exception to avoid catching SystemExit and KeyboardInterrupt.
| except: | |
| except sqlite3.OperationalError: |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -99,31 +99,57 @@ def get_googleDuo(files_found, report_folder, seeker, wrap_text): | |||||
| else: | ||||||
| logfunc('No Google Duo - Contacts data available') | ||||||
|
|
||||||
| cursor.execute(''' | ||||||
| select | ||||||
| case sent_timestamp_millis | ||||||
| when 0 then '' | ||||||
| else datetime(sent_timestamp_millis/1000,'unixepoch') | ||||||
| end as 'Sent Timestamp', | ||||||
| case received_timestamp_millis | ||||||
| when 0 then '' | ||||||
| else datetime(received_timestamp_millis/1000,'unixepoch') | ||||||
| end as 'Received Timestamp', | ||||||
| case seen_timestamp_millis | ||||||
| when 0 then '' | ||||||
| else datetime(seen_timestamp_millis/1000,'unixepoch') | ||||||
| end as 'Viewed Timestamp', | ||||||
| sender_id, | ||||||
| recipient_id, | ||||||
| content_uri, | ||||||
| replace(content_uri, rtrim(content_uri, replace(content_uri, '/', '')), '') as 'File Name', | ||||||
| content_size_bytes, | ||||||
| case saved_status | ||||||
| when 0 then '' | ||||||
| when 1 then 'Yes' | ||||||
| end as 'File Saved' | ||||||
| from messages | ||||||
| ''') | ||||||
| try: | ||||||
| cursor.execute(''' | ||||||
| select | ||||||
| case sent_timestamp_millis | ||||||
| when 0 then '' | ||||||
| else datetime(sent_timestamp_millis/1000,'unixepoch') | ||||||
| end as 'Sent Timestamp', | ||||||
| case received_timestamp_millis | ||||||
| when 0 then '' | ||||||
| else datetime(received_timestamp_millis/1000,'unixepoch') | ||||||
| end as 'Received Timestamp', | ||||||
| case seen_timestamp_millis | ||||||
| when 0 then '' | ||||||
| else datetime(seen_timestamp_millis/1000,'unixepoch') | ||||||
| end as 'Viewed Timestamp', | ||||||
| sender_id, | ||||||
| recipient_id, | ||||||
| content_uri, | ||||||
| replace(content_uri, rtrim(content_uri, replace(content_uri, '/', '')), '') as 'File Name', | ||||||
| content_size_bytes, | ||||||
| case saved_status | ||||||
| when 0 then '' | ||||||
| when 1 then 'Yes' | ||||||
| end as 'File Saved' | ||||||
| from messages | ||||||
| ''') | ||||||
| has_saved_status = True | ||||||
| except: | ||||||
|
||||||
| except: | |
| except sqlite3.OperationalError: |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -20,25 +20,63 @@ def get_googleMessages(files_found, report_folder, seeker, wrap_text): | |||||
|
|
||||||
| db = open_sqlite_db_readonly(file_found) | ||||||
| cursor = db.cursor() | ||||||
| cursor.execute(''' | ||||||
| SELECT | ||||||
| datetime(parts.timestamp/1000,'unixepoch') AS "Timestamp (UTC)", | ||||||
| parts.content_type AS "Message Type", | ||||||
| conversations.name AS "Other Participant/Conversation Name", | ||||||
| participants.display_destination AS "Message Sender", | ||||||
| parts.text AS "Message", | ||||||
| CASE | ||||||
| WHEN parts.file_size_bytes=-1 THEN "N/A" | ||||||
| ELSE parts.file_size_bytes | ||||||
| END AS "Attachment Byte Size", | ||||||
| parts.local_cache_path AS "Attachment Location" | ||||||
| FROM | ||||||
| parts | ||||||
| JOIN messages ON messages._id=parts.message_id | ||||||
| JOIN participants ON participants._id=messages.sender_id | ||||||
| JOIN conversations ON conversations._id=parts.conversation_id | ||||||
| ORDER BY "Timestamp (UTC)" ASC | ||||||
| ''') | ||||||
| try: | ||||||
| cursor.execute(''' | ||||||
| SELECT | ||||||
| datetime(parts.timestamp/1000,'unixepoch') AS "Timestamp (UTC)", | ||||||
| parts.content_type AS "Message Type", | ||||||
| conversations.name AS "Other Participant/Conversation Name", | ||||||
| participants.display_destination AS "Message Sender", | ||||||
| parts.text AS "Message", | ||||||
| CASE | ||||||
| WHEN parts.file_size_bytes=-1 THEN "N/A" | ||||||
| ELSE parts.file_size_bytes | ||||||
| END AS "Attachment Byte Size", | ||||||
| parts.local_cache_path AS "Attachment Location" | ||||||
| FROM | ||||||
| parts | ||||||
| JOIN messages ON messages._id=parts.message_id | ||||||
| JOIN participants ON participants._id=messages.sender_id | ||||||
| JOIN conversations ON conversations._id=parts.conversation_id | ||||||
| ORDER BY "Timestamp (UTC)" ASC | ||||||
| ''') | ||||||
| except: | ||||||
|
||||||
| # Fallback for databases without file_size_bytes column | ||||||
|
||||||
| # Fallback for databases without file_size_bytes column | |
| # Fallback for databases without file_size_bytes column (but with local_cache_path) |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bare except clause without specifying exception type. Consider catching specific exceptions like sqlite3.OperationalError or at minimum Exception to avoid catching SystemExit and KeyboardInterrupt.
| except: | |
| except sqlite3.OperationalError: |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,17 +28,44 @@ def get_keepNotes(files_found, report_folder, seeker, wrap_text): | |
| if filename.endswith('keep.db'): | ||
| db = open_sqlite_db_readonly(file_found) | ||
| cursor = db.cursor() | ||
| cursor.execute(''' | ||
| SELECT | ||
| datetime(tree_entity.time_created/1000, 'unixepoch') AS "Time Created", | ||
| datetime(tree_entity.time_last_updated/1000, 'unixepoch') AS "Time Last Updated", | ||
| datetime(tree_entity.user_edited_timestamp/1000, 'unixepoch') AS "User Edited Timestamp", | ||
| tree_entity.title AS Title, | ||
| text_search_note_content_content.c0text AS "Text", | ||
| tree_entity.last_modifier_email AS "Last Modifier Email" | ||
| FROM text_search_note_content_content | ||
| INNER JOIN tree_entity ON text_search_note_content_content.docid = tree_entity._id | ||
| ''') | ||
| try: | ||
| cursor.execute(''' | ||
| SELECT | ||
| datetime(tree_entity.time_created/1000, 'unixepoch') AS "Time Created", | ||
| datetime(tree_entity.time_last_updated/1000, 'unixepoch') AS "Time Last Updated", | ||
| datetime(tree_entity.user_edited_timestamp/1000, 'unixepoch') AS "User Edited Timestamp", | ||
| tree_entity.title AS Title, | ||
| text_search_note_content_content.c0text AS "Text", | ||
| tree_entity.last_modifier_email AS "Last Modifier Email" | ||
| FROM text_search_note_content_content | ||
| INNER JOIN tree_entity ON text_search_note_content_content.docid = tree_entity._id | ||
| ''') | ||
| except: | ||
|
||
| # Fallback for databases without text_search_note_content_content table | ||
| try: | ||
| cursor.execute(''' | ||
| SELECT | ||
| datetime(tree_entity.time_created/1000, 'unixepoch') AS "Time Created", | ||
| datetime(tree_entity.time_last_updated/1000, 'unixepoch') AS "Time Last Updated", | ||
| datetime(tree_entity.user_edited_timestamp/1000, 'unixepoch') AS "User Edited Timestamp", | ||
| tree_entity.title AS Title, | ||
| tree_entity.text_content AS "Text", | ||
| tree_entity.last_modifier_email AS "Last Modifier Email" | ||
| FROM tree_entity | ||
| WHERE tree_entity.type = 0 | ||
| ''') | ||
| except: | ||
|
||
| # Final fallback - just tree_entity with minimal columns | ||
| cursor.execute(''' | ||
| SELECT | ||
| datetime(tree_entity.time_created/1000, 'unixepoch') AS "Time Created", | ||
| datetime(tree_entity.time_last_updated/1000, 'unixepoch') AS "Time Last Updated", | ||
| datetime(tree_entity.user_edited_timestamp/1000, 'unixepoch') AS "User Edited Timestamp", | ||
| tree_entity.title AS Title, | ||
| NULL AS "Text", | ||
| tree_entity.last_modifier_email AS "Last Modifier Email" | ||
| FROM tree_entity | ||
| ''') | ||
|
|
||
| all_rows = cursor.fetchall() | ||
| usageentries = len(all_rows) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bare except clause without specifying exception type. Consider catching specific exceptions like
sqlite3.OperationalErroror at minimumExceptionto avoid catching SystemExit and KeyboardInterrupt.