root/hodgestar/PythonCode/NokiaArcExtractor/arc-extract.py

Revision 439, 3.1 kB (checked in by hodgestar, 4 years ago)

Note Mark's suggestion to try different string encoding.

  • Property svn:mime-type set to text/python-source
  • Property svn:eol-style set to native
Line 
1"""Nokia arc file extractor.
2
3   Copyright 2008 Simon Cross <hodgestar+arc@gmail.com>
4   Copyright 2008 Mark Ferry <gnomeza+arc@gmail.com>
5
6   With some help from:
7   http://www.opensource.or.ke/index.php?option=com_content&task=view&id=81&Itemid=1
8
9   Notes:
10     - <Gnome> Hodgestar: did you try running /usr/bin/strings with --encoding=l ?
11       <Gnome> produces good lists of file paths
12   """
13
14import zlib
15import os
16import sys
17
18def dump_header(data, recovery_folder, max_offset=256):
19    """Dump header."""
20    offset = 0
21    while offset <= max_offset:
22        try:
23            decoder = zlib.decompressobj()
24            msg = decoder.decompress(data[offset:])
25        except zlib.error:
26            offset += 1
27        else:
28            break
29    else:
30        raise RuntimeError("Unable to find end of header.")
31
32    hdr_len = offset
33    print "Found header of %d bytes." % (hdr_len,)
34
35    fname = os.path.join(recovery_folder, "header.dat")
36    f = file(fname, "wb")
37    try:
38        f.write(data[:hdr_len])
39    finally:
40        f.close()
41
42    return data[hdr_len:]
43
44def unpack_filelist(data, recovery_folder):
45    """Unpack list of files."""
46    n_files = ord(data[0])
47    data = data[21:]
48
49    print "Unpacking %d files ..." % (n_files,)
50
51    fname = os.path.join(recovery_folder, "filelist.txt")
52    f = file(fname, "wb")
53
54    for i in range(n_files):
55        for j, s in enumerate(data):
56            if s in ("\x00", "\x80"):
57                f.write(data[:j])
58                f.write("\n")
59                data = data[j+56+1:]
60                break
61
62    f.close()
63    return data
64
65def dump_contacts(data, recovery_folder):
66    """Dump contacts (assumed to be everything after the file list)."""
67    fname = os.path.join(recovery_folder, "contacts.db")
68    f = file(fname, "wb")
69    f.write(data)
70    f.close()
71
72def unpack(arc_file, recovery_folder):
73    data = file(arc_file, "rb").read()
74    len_file = len(data)
75
76    data = dump_header(data, recovery_folder)
77    print "Dumped header."
78
79    i = 0
80    while True:
81        pos = len_file - len(data)
82
83        try:
84            decoder = zlib.decompressobj()
85            msg = decoder.decompress(data)
86        except zlib.error:
87            # end of zlib blocks
88            break
89
90        data = decoder.unused_data
91        old_pos = pos
92        pos = len_file - len(data)
93
94        print "Decoded data from %d to %d as file%d.rec." % (old_pos, pos, i)
95
96        fname = os.path.join(recovery_folder, "file_%d.rec" % (i,))
97        f = file(fname, "wb")
98        try:
99            f.write(msg)
100        finally:
101            f.close()
102
103        i += 1
104
105    # process file list
106    data = unpack_filelist(data, recovery_folder)
107    old_pos = pos
108    pos = len_file - len(data)
109    print "Files unpacked from %d to %d" % (old_pos, pos)
110
111    # dump contacts
112    dump_contacts(data, recovery_folder)
113    print "Contacts db dumped from %d to %d" % (pos, len_file)
114
115
116if __name__ == "__main__":
117    if len(sys.argv) != 3:
118        print "Usage: %s <arc file> <recovery folder>" % (sys.argv[0],)
119        sys.exit(1)
120
121    arc_file = sys.argv[1]
122    recovery_folder = sys.argv[2]
123
124    unpack(arc_file, recovery_folder)
Note: See TracBrowser for help on using the browser.