Skip to content

Instantly share code, notes, and snippets.

@pingw33n
Created February 12, 2014 17:54
Show Gist options
  • Save pingw33n/8960898 to your computer and use it in GitHub Desktop.
Save pingw33n/8960898 to your computer and use it in GitHub Desktop.
iBackup SMS to XML converter
#!/usr/bin/env python
#######################################################################
# This is a script that converts iTunes SMS backup database (that is stored
# inf 3d0d7e5fb2ce288813306e4d4636395e047a3d28 file) into
# an XML file that can be restored on Android with SMS Backup & Restore
# app (https://play.google.com/store/apps/details?id=com.riteshsahu.SMSBackupRestore)
#
# Usage:
# python ibackup-sms-xml-converter.py /path/to/3d0d7e5fb2ce288813306e4d4636395e047a3d28 /path/to/smses.xml
#
# Use the generated smses.xml in the app on the target Android device.
#######################################################################
import xml.sax.saxutils
import xml.sax.xmlreader
import sqlite3
import sys
def idate_to_unix(idate):
# The iEpoch starts from 01.01.2001 00:00:00.
return 978307200 + idate
def xml_start_element(xml_gen, name, attrs):
values = {}
qnames = {}
for attr_name, attr_value in attrs.items():
values[(None, attr_name)] = unicode(attr_value)
qnames[(None, attr_name)] = attr_name
xml_gen.startElementNS((None, name), name,
xml.sax.xmlreader.AttributesNSImpl(values, qnames))
def xml_end_element(xml, name):
xml.endElementNS((None, name), name)
input_filename = sys.argv[1]
output_filename = sys.argv[2]
print "Reading %s..." % input_filename
conn = sqlite3.connect(input_filename)
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute(
"""
SELECT
h.uncanonicalized_id, id, m.text, m.date, m.is_from_me
FROM chat_message_join cmj
JOIN message m ON cmj.message_id = m.rowid
JOIN chat c ON cmj.chat_id = c.rowid
JOIN handle h ON m.handle_id = h.rowid
WHERE c.service_name = "SMS"
""");
rows = c.fetchall()
print "Read %s SMS message(s)" % len(rows)
print "Creating %s..." % output_filename
output_file = file(output_filename, "wb+")
xml_gen = xml.sax.saxutils.XMLGenerator(output_file, "UTF-8")
xml_gen.startDocument()
xml_start_element(xml_gen, "smses", {"count": len(rows)})
for row in rows:
id = row["id"]
uncanonicalized_id = row["uncanonicalized_id"]
address = uncanonicalized_id if not id.startswith("+") and uncanonicalized_id else id
type = 2 if row["is_from_me"] else 1
xml_start_element(xml_gen, "sms", {
"protocol": 0,
"address": address,
"date": str(idate_to_unix(row["date"])) + "000",
"subject": "null",
"body": row["text"],
"toa": "null",
"sc_toa": "null",
"service_center": "null",
"read": 1,
"status": -1,
"type": type})
xml_end_element(xml_gen, "smses")
xml_gen.endDocument()
print "Done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment