Created
September 15, 2012 06:31
-
-
Save davidfraser/3726604 to your computer and use it in GitHub Desktop.
Code to explore android sms corruption by comparing raw and sms tables in mmssms.db
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sqlite3 | |
import pprint | |
import datetime | |
import time | |
# install from https://github.com/pmarti/python-messaging/tarball/master - built against 0.5.12 | |
from messaging import sms | |
import pprint | |
# TODO: check timezones... | |
def adapt_datetime(ts): | |
return int(time.mktime(ts.timetuple())*1000) | |
sqlite3.register_adapter(datetime.datetime, adapt_datetime) | |
class SMSExplorer(object): | |
DEFAULT_DATE_RANGE = datetime.timedelta(minutes=15) | |
TIMEZONE_OFFSET = datetime.timedelta(seconds=time.timezone) | |
def __init__(self): | |
self.db = sqlite3.connect("mmssms.db") | |
@property | |
def raw_addresses(self): | |
"""shows all the addresses in the raw table""" | |
cursor = self.db.cursor() | |
try: | |
cursor.execute("select distinct address from raw") | |
return set([values[0] for values in cursor.fetchall()]) | |
finally: | |
cursor.close() | |
def raw_entries(self, address=None): | |
"""returns entries from the raw table as dicts, with parsed pdu under parsed_pdu, filtering by address if given""" | |
cursor = self.db.cursor() | |
try: | |
if address is None: | |
cursor.execute("select * from raw") | |
else: | |
cursor.execute("select * from raw where address = ?", (address,)) | |
columns = [c[0] for c in cursor.description] | |
entries = [dict(zip(columns, values)) for values in cursor.fetchall()] | |
finally: | |
cursor.close() | |
for entry in entries: | |
# entry["datetime"] = datetime. | |
entry["parsed"] = sms.SmsDeliver(entry["pdu"]) | |
return entries | |
def search_sms(self, address, date, date_range=DEFAULT_DATE_RANGE): | |
"""finds possible retrieved smses from the given address, close to the given date""" | |
cursor = self.db.cursor() | |
try: | |
date_min, date_max = date - date_range, date + date_range | |
# limit to retrieved sms from the given address in a date window | |
cursor.execute("select * from sms where address = ? and date >= ? and date <= ? and type = 1", (address, date_min, date_max)) | |
columns = [c[0] for c in cursor.description] | |
messages = [dict(zip(columns, values)) for values in cursor.fetchall()] | |
for message in messages: | |
message["date_parsed"] = datetime.datetime.utcfromtimestamp(message["date"]/1000.) | |
return messages | |
finally: | |
cursor.close() | |
if __name__ == "__main__": | |
explorer = SMSExplorer() | |
for address in explorer.raw_addresses: | |
entries = explorer.raw_entries(address) | |
for entry in entries: | |
entry_parsed = entry["parsed"] | |
entry_date = entry_parsed.date | |
sms_possibilities = explorer.search_sms(address, entry_date - explorer.TIMEZONE_OFFSET) | |
if sms_possibilities and True not in [entry_parsed.text in s["body"] for s in sms_possibilities]: | |
pprint.pprint((entry_parsed.number, entry_parsed.date, entry_parsed.text, entry_parsed.udh)) | |
for s in sms_possibilities: | |
pprint.pprint((s["address"], s["date_parsed"], s["body"])) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment