initial commit
[fmms] / src / controller.py
1 #!/usr/bin/env python2.5
2 # -*- coding: utf-8 -*-
3 """ Useful functions that shouldn't be in the UI code
4
5
6 And, yes, I know this is not really a controller.
7
8 @author: Nick Leppänen Larsson <frals@frals.se>
9 @license: GNU GPL
10 """
11 import os
12 import array
13
14 import dbus
15 from dbus.mainloop.glib import DBusGMainLoop
16
17 import fmms_config as fMMSconf
18 import dbhandler as DBHandler
19 from mms.message import MMSMessage
20 from mms import mms_pdu
21
22 #TODO: constants.py?
23 MSG_DIRECTION_IN = 0
24 MSG_DIRECTION_OUT = 1
25 MSG_UNREAD = 0
26 MSG_READ = 1
27
28 class fMMS_controller():
29         
30         def __init__(self):
31                 self.config = fMMSconf.fMMS_config()
32                 self._mmsdir = self.config.get_mmsdir()
33                 self._pushdir = self.config.get_pushdir()
34                 self._outdir = self.config.get_outdir()
35                 self.store = DBHandler.DatabaseHandler()
36         
37         
38         def decode_mms_from_push(self, binarydata):
39                 decoder = mms_pdu.MMSDecoder()
40                 wsplist = decoder.decodeCustom(binarydata)
41
42                 sndr, url, trans_id = None, None, None
43                 bus = dbus.SystemBus()
44                 proxy = bus.get_object('org.freedesktop.Notifications', '/org/freedesktop/Notifications')
45                 interface = dbus.Interface(proxy,dbus_interface='org.freedesktop.Notifications')
46
47                 try:
48                         url = wsplist["Content-Location"]
49                         print "content-location:", url
50                         trans_id = wsplist["Transaction-Id"]
51                         trans_id = str(trans_id)
52                         print "transid:", trans_id
53                 except Exception, e:
54                         print "no content-location/transid in push; aborting...", type(e), e
55                         interface.SystemNoteInfoprint ("fMMS: Failed to parse SMS PUSH.")
56                         raise
57                 try:
58                         sndr = wsplist["From"]
59                         print "Sender:", sndr
60                 except Exception, e:
61                         print "No sender value defined", type(e), e
62                         sndr = "Unknown sender"
63
64                 self.save_binary_push(binarydata, trans_id)
65                 return (wsplist, sndr, url, trans_id)
66         
67         
68         def save_binary_push(self, binarydata, transaction):
69                 data = array.array('B')
70                 for b in binarydata:
71                         data.append(b)
72                 # TODO: move to config?
73                 if not os.path.isdir(self._pushdir):
74                         os.makedirs(self._pushdir)
75                 try:
76                         fp = open(self._pushdir + transaction, 'wb')
77                         fp.write(data)
78                         print "saved binary push", fp
79                         fp.close()
80                 except Exception, e:
81                         print "failed to save binary push:", type(e), e
82                         raise
83         
84         def save_push_message(self, data):
85                 """ Gets the decoded data as a list (preferably from decode_mms_from_push)
86                 """
87                 pushid = self.store.insert_push_message(data)
88                 return pushid
89         
90         
91         def get_push_list(self, types=None):
92                 return self.store.get_push_list()
93                 
94         
95         def is_fetched_push_by_transid(self, transactionid):
96                 return self.store.is_mms_downloaded(transactionid)
97         
98         
99         def read_push_as_list(self, transactionid):
100                 return self.store.get_push_message(transactionid)
101         
102         
103         def save_binary_mms(self, data, transaction):
104                 dirname = self._mmsdir + transaction
105                 if not os.path.isdir(dirname):
106                         os.makedirs(dirname)
107                 
108                 fp = open(dirname + "/message", 'wb')
109                 fp.write(data)
110                 print "saved binary mms", fp
111                 fp.close()
112                 return dirname
113                 
114         def save_binary_outgoing_mms(self, data, transaction):
115                 transaction = str(transaction)
116                 dirname = self._outdir + transaction
117                 if not os.path.isdir(dirname):
118                         os.makedirs(dirname)
119
120                 fp = open(dirname + "/message", 'wb')
121                 fp.write(data)
122                 print "saved binary mms", fp
123                 fp.close()
124                 return dirname
125         
126         def decode_binary_mms(self, path):
127                 """ decodes and saves the binary mms"""
128                 # Decode the specified file
129                 # This also creates all the parts as files in path
130                 print "decode_binary_mms running"
131                 try:
132                         message = MMSMessage.fromFile(path + "/message")
133                 except Exception, e:
134                         print type(e), e
135                         raise
136                 print "returning message!"
137                 return message
138         
139         
140         def store_mms_message(self, pushid, message):
141                 mmsid = self.store.insert_mms_message(pushid, message)
142                 return mmsid
143         
144         def store_outgoing_mms(self, message):
145                 mmsid = self.store.insert_mms_message(0, message, DBHandler.MSG_DIRECTION_OUT)
146                 return mmsid
147                 
148         def store_outgoing_push(self, wsplist):
149                 pushid = self.store.insert_push_send(wsplist)
150                 return pushid
151                 
152         def link_push_mms(self, pushid, mmsid):
153                 self.store.link_push_mms(pushid, mmsid)
154         
155         def get_direction_mms(self, transid):
156                 return self.store.get_direction_mms(transid)
157         
158         def get_mms_from_push(self, transactionid):
159                 plist = self.store.get_push_message(transactionid)
160                 trans_id = plist['Transaction-Id']
161                 pushid = plist['PUSHID']
162                 url = plist['Content-Location']
163                 
164                 from wappushhandler import PushHandler
165                 p = PushHandler()
166                 path = p._get_mms_message(url, trans_id)
167                 print "decoding mms..."
168                 message = self.cont.decode_binary_mms(path)
169                 print "storing mms..."
170                 mmsid = self.cont.store_mms_message(pushid, message)
171                 
172                 
173         def get_mms_attachments(self, transactionid, allFiles=False):
174                 return self.store.get_mms_attachments(transactionid, allFiles)
175         
176         def get_mms_headers(self, transactionid):
177                 return self.store.get_mms_headers(transactionid)
178         
179         def delete_mms_message(self, fname):
180                 fullpath = self._mmsdir + fname
181                 print fullpath
182                 if os.path.isdir(fullpath):
183                         print "starting deletion of", fullpath
184                         filelist = self.get_mms_attachments(fname, allFiles=True)
185                         if filelist == None:
186                                 filelist = []
187                         filelist.append("message")
188                         for fn in filelist:
189                                 try:
190                                         fullfn = fullpath + "/" + fn
191                                         os.remove(fullfn)
192                                 except:
193                                         print "failed to remove", fullfn
194                         try:
195                                 print "trying to remove", fullpath
196                                 os.rmdir(fullpath)
197                         except OSError, e:
198                                 print "failed to remove dir:", type(e), e
199                                 raise
200                 self.store.delete_mms_message(fname)
201                 
202         def delete_push_message(self, fname):
203                 fullpath = self._pushdir + fname
204                 print fullpath
205                 if os.path.isfile(fullpath):
206                         print "removing", fullpath
207                         try:
208                                 os.remove(fullpath)
209                         except Exception, e:
210                                 raise
211                 self.store.delete_push_message(fname)
212                 
213         def wipe_message(self, transactionid):
214                 self.delete_mms_message(transactionid)
215                 self.delete_push_message(transactionid)
216         
217         """ DEPRECATED AS OF 0.2.10
218         gets a mms from a previously received push """
219         """ this function requires the fname to be the fullpath """
220         # TODO: dont require fullpath
221         """def get_mms_from_push(self, fname):
222                 
223                 plist = self.read_push_as_list(fname)
224                 try:
225                         sndr = plist['From']
226                 except:
227                         sndr = "Unknown"
228                 url = plist['Content-Location']
229                 print url
230                 trans_id = plist['Transaction-Id']
231                 print trans_id
232                 
233                 from wappushhandler import PushHandler
234                 push = PushHandler()
235                 path = push._get_mms_message(url, trans_id)
236                 Push.decodeMMS(path)
237                 
238                 return 0"""
239         
240         """ Old function relying on files... Deprecated as of 0.2.10
241         def is_fetched_push(self, filename):
242                 this function takes the FILENAME, not the full path
243                 path = self._mmsdir + filename
244                 if os.path.isdir(path):
245                         if os.path.isfile(self._mmsdir + filename + "/message"):
246                                 return True
247                 else:
248                 return False"""
249         
250         
251         """def read_push_as_list(self, fname):
252                         # reads a saved push message into a dict
253                         fp = open(fname, 'r')
254                         pdict = {}
255                         for line in fp:
256                                 line = line.replace("\n", "")
257                                 lsplit = line.partition(" ")
258                                 pdict[lsplit[0]] = lsplit[2]
259                         fp.close()
260                 return pdict"""
261         
262 if __name__ == '__main__':
263         c = fMMS_controller()
264         pass