final fixes for PR1.3
[ussd-widget] / ussd4all / rtcom / rtcompatcher.py
1 #!/usr/bin/python
2
3 ## This program is free software; you can redistribute it and/or modify
4 ## it under the terms of the GNU General Public License as published
5 ## by the Free Software Foundation; version 2 and higer.
6 ##
7 ## Dani Church 2010
8
9 import hashlib
10
11 patch_config = {
12     'known_md5sums': [
13         '5a51e4fbb38dac338e4444e6b713e9b3',
14         '44d6b8258fb4fb9c849162704120ba53',
15 # PR 1.3
16         '2c2713a25e323670cad57d5f856f0acf'
17     ],
18     'check_ranges': [
19         (194380, 'f04f2de920b08de2'),
20         (195340, 'f04f2de920b08de2'),
21     ],
22     'patch_ranges': [
23         (194380, '0010a0e3001097e5'),
24         (195340, '0010a0e3001097e5'),
25     ],
26 }
27
28 class Patcher:
29     known_md5sums = []
30     check_ranges = []
31     patch_ranges = []
32
33     def __init__(self, config):
34         self.known_md5sums = config['known_md5sums']
35         self.check_ranges = config['check_ranges']
36         self.patch_ranges = config['patch_ranges']
37
38     def check_md5sum(self, filename):
39         md5 = hashlib.md5()
40         f = open(filename, 'rb')
41         while True:
42             d = f.read(8096)
43             if not d: break
44             md5.update(d)
45         f.close()
46
47         md5sum = md5.hexdigest()
48         for known_sum in self.known_md5sums:
49             if md5sum == known_sum: return True
50
51         return False
52
53     def check_data(self, filename):
54         f = open(filename, 'rb')
55
56         for seek, hexbytes in self.check_ranges:
57             bytes = hexbytes.decode('hex')
58             f.seek(seek)
59             actual = f.read(len(bytes))
60             if actual != bytes:
61                 f.close()
62                 return False
63
64         f.close()
65         return True
66         
67     def patch_file(self, filename):
68         f = open(filename, 'r+b')
69
70         for seek, hexbytes in self.patch_ranges:
71             bytes = hexbytes.decode('hex')
72             f.seek(seek)
73             f.write(bytes)
74
75         f.close()
76
77 if __name__ == '__main__':
78     import sys, os, shutil, subprocess
79
80     library = '/usr/lib/librtcom-call-ui.so.0.0.0'
81
82     if os.access(library+'-p1', os.F_OK):
83         print "It looks like %s has already been patched. Aborting." % (library,)
84         sys.exit(1)
85
86     patcher = Patcher(patch_config)
87
88     if not patcher.check_md5sum(library):
89         if not patcher.check_data(library):
90             message = "Your %s is not recognized. So I won't patch it." % (library)
91             subprocess.call(["dbus-send --system --type=method_call --dest=org.freedesktop.Notifications /org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteDialog string:\""+message+"\" uint32:0 string:\"OK\""],shell=True)
92             print message       
93             sys.exit(1)
94         if len(sys.argv) > 1 and sys.argv[1] == '--force':
95             message = "Patching an unrecognized %s. Please test your system before rebooting." % (library)
96             print message           
97         else:
98             message = "Your %s is not recognized, but it seems to match the patterns.\nRun '%s --force' to try patching anyway, but understand that\nTHIS MAY BREAK YOUR SYSTEM.  If you do, test your system thoroughly before rebooting." % (library,sys.argv[0])
99             subprocess.call(["dbus-send --system --type=method_call --dest=org.freedesktop.Notifications /org/freedesktop/Notifications org.freedesktop.Notifications.SystemNoteDialog string:\""+message+"\" uint32:0 string:\"OK\""],shell=True)
100             print message
101             sys.exit(1)
102
103     shutil.copy2(library, library+'-p1')
104     patcher.patch_file(library+'-p1')