diff --git a/scripts/artifacts/deviceHealthServices_Battery.py b/scripts/artifacts/deviceHealthServices_Battery.py index 38f2c8df..7612ddf8 100644 --- a/scripts/artifacts/deviceHealthServices_Battery.py +++ b/scripts/artifacts/deviceHealthServices_Battery.py @@ -35,7 +35,7 @@ from packaging import version from scripts.artifact_report import ArtifactHtmlReport -from scripts.ilapfuncs import artifact_processor, open_sqlite_db_readonly, convert_ts_human_to_utc, convert_utc_human_to_timezone +from scripts.ilapfuncs import artifact_processor, open_sqlite_db_readonly, convert_ts_human_to_utc, convert_utc_human_to_timezone, logfunc @artifact_processor def Turbo_Battery(files_found, report_folder, seeker, wrap_text): @@ -80,7 +80,17 @@ def Turbo_Battery(files_found, report_folder, seeker, wrap_text): if timestamp is None: pass else: - timestamp = convert_utc_human_to_timezone(convert_ts_human_to_utc(timestamp),time_offset) + try: + time_offset = row[4] if len(row) > 4 and row[4] else 'UTC' + except Exception as ex: + logfunc(f'Turbo_Battery: failed to read timezone ({ex}); defaulting to UTC.') + time_offset = 'UTC' + + try: + timestamp = convert_utc_human_to_timezone(convert_ts_human_to_utc(timestamp), time_offset) + except Exception as ex: + logfunc(f'Turbo_Battery: timezone conversion failed ({ex}); falling back to UTC.') + timestamp = convert_ts_human_to_utc(timestamp) data_list.append((timestamp,row[1],row[2],row[3],row[4],file_found)) db.close() diff --git a/scripts/artifacts/googleMessages.py b/scripts/artifacts/googleMessages.py index 38c9eb04..6c545b9a 100755 --- a/scripts/artifacts/googleMessages.py +++ b/scripts/artifacts/googleMessages.py @@ -20,17 +20,33 @@ def get_googleMessages(files_found, report_folder, seeker, wrap_text): db = open_sqlite_db_readonly(file_found) cursor = db.cursor() - cursor.execute(''' + + parts_columns = {row[1] for row in cursor.execute('PRAGMA table_info(parts)').fetchall()} + if 'file_size_bytes' in parts_columns: + attachment_case = ''' + CASE + WHEN parts.file_size_bytes=-1 THEN "N/A" + ELSE parts.file_size_bytes + END AS "Attachment Byte Size"''' + elif 'file_size' in parts_columns: + attachment_case = ''' + CASE + WHEN parts.file_size=-1 THEN "N/A" + ELSE parts.file_size + END AS "Attachment Byte Size"''' + else: + attachment_case = '"N/A" AS "Attachment Byte Size"' + logfunc('Google Messages: attachment size column missing; defaulting to N/A.') + + try: + cursor.execute(f''' 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", + {attachment_case}, parts.local_cache_path AS "Attachment Location" FROM parts @@ -39,8 +55,11 @@ def get_googleMessages(files_found, report_folder, seeker, wrap_text): JOIN conversations ON conversations._id=parts.conversation_id ORDER BY "Timestamp (UTC)" ASC ''') + all_rows = cursor.fetchall() + except sqlite3.OperationalError as ex: + logfunc(f'Google Messages: SQLite error - {ex}') + all_rows = [] - all_rows = cursor.fetchall() usageentries = len(all_rows) if usageentries > 0: report = ArtifactHtmlReport('Google Messages') diff --git a/scripts/artifacts/keepNotes.py b/scripts/artifacts/keepNotes.py index a50ec7b3..b2942809 100644 --- a/scripts/artifacts/keepNotes.py +++ b/scripts/artifacts/keepNotes.py @@ -28,20 +28,29 @@ 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 - ''') - all_rows = cursor.fetchall() - usageentries = len(all_rows) + 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 + ''') + + all_rows = cursor.fetchall() + usageentries = len(all_rows) + except sqlite3.OperationalError as ex: + logfunc(f'Google Keep Notes: SQLite error - {ex}') + usageentries = 0 + all_rows = [] + finally: + cursor.close() + db.close() if usageentries > 0: data_list = [] @@ -62,5 +71,4 @@ def get_keepNotes(files_found, report_folder, seeker, wrap_text): timeline(report_folder, tlactivity, data_list, data_headers) else: - logfunc('No Google Keep Notes data available') - + logfunc('No Google Keep Notes data available') \ No newline at end of file