2 # -*- coding: utf-8 -*-
3 """ Class for handling wap push messages and creating MMS messages
5 @author: Nick Leppänen Larsson <frals@frals.se>
19 from dbus.mainloop.glib import DBusGMainLoop
21 from mms import message
22 from mms.message import MMSMessage
23 from mms import mms_pdu
24 import fmms_config as fMMSconf
25 import controller as fMMSController
33 self.cont = fMMSController.fMMS_controller()
34 # TODO: get all this from controller instead of config
35 self.config = fMMSconf.fMMS_config()
36 self._mmsdir = self.config.get_mmsdir()
37 self._pushdir = self.config.get_pushdir()
38 self._apn = self.config.get_apn()
39 self._apn_nicename = self.config.get_apn_nicename()
40 self._incoming = '/home/user/.fmms/temp/LAST_INCOMING'
42 if not os.path.isdir(self._mmsdir):
43 print "creating dir", self._mmsdir
44 os.makedirs(self._mmsdir)
45 if not os.path.isdir(self._pushdir):
46 print "creating dir", self._pushdir
47 os.makedirs(self._pushdir)
49 """ handle incoming push over sms """
50 def _incoming_sms_push(self, source, src_port, dst_port, wsp_header, wsp_payload):
51 dbus_loop = DBusGMainLoop()
52 args = (source, src_port, dst_port, wsp_header, wsp_payload)
55 if not os.path.isdir('/home/user/.fmms/temp'):
56 print "creating dir /home/user/.fmms/temp"
57 os.makedirs("/home/user/.fmms/temp")
59 f = open(self._incoming, 'w')
66 print "SRC: ", source, ":", src_port
67 print "DST: ", dst_port
68 #print "WSPHEADER: ", wsp_header
69 #print "WSPPAYLOAD: ", wsp_payload
72 # throw away the wsp_header!
77 binarydata.append(int(d))
82 (data, sndr, url, trans_id) = self.cont.decode_mms_from_push(binarydata)
85 # Controller should save it
86 pushid = self.cont.save_push_message(data)
87 print "notifying push..."
88 # Send a notify we got the SMS Push and parsed it A_OKEY!
89 self.notify_mms(dbus_loop, sndr, "SMS Push for MMS received")
90 print "fetching mms..."
91 path = self._get_mms_message(url, trans_id)
92 print "decoding mms... path:", path
93 message = self.cont.decode_binary_mms(path)
94 print "storing mms..."
95 mmsid = self.cont.store_mms_message(pushid, message)
96 print "notifying mms..."
97 self.notify_mms(dbus_loop, sndr, "New MMS", trans_id);
101 """ handle incoming ip push """
102 # TODO: implement this
103 def _incoming_ip_push(self, src_ip, dst_ip, src_port, dst_port, wsp_header, wsp_payload):
105 print "SRC: " + src_ip + ":" + src_port + "\n"
106 print "DST: " + dst_ip + ":" + dst_port + "\n"
107 print "WSPHEADER: " + wsp_header + "\n"
108 print "WSPPAYLOAD: " + wsp_payload + "\n"
112 """ notifies the user with a org.freedesktop.Notifications.Notify, really fancy """
113 def notify_mms(self, dbus_loop, sender, message, path=None):
114 bus = dbus.SystemBus()
115 proxy = bus.get_object('org.freedesktop.Notifications', '/org/freedesktop/Notifications')
116 interface = dbus.Interface(proxy,dbus_interface='org.freedesktop.Notifications')
117 choices = ['default', 'cancel']
119 interface.Notify('MMS', 0, '', message, sender, choices, {"category": "sms-message", "dialog-type": 4, "led-pattern": "PatternCommunicationEmail", "dbus-callback-default": "se.frals.fmms /se/frals/fmms se.frals.fmms open_gui"}, -1)
121 # TODO: callback should open fMMS gui
122 interface.Notify("MMS", 0, '', message, sender, choices, {"category": "email-message", "dialog-type": 4, "led-pattern": "PatternCommunicationEmail", "dbus-callback-default": "se.frals.fmms /se/frals/fmms se.frals.fmms open_mms string:\"" + path + "\""}, -1)
125 """ get the mms message from content-location """
126 """ thanks benaranguren on talk.maemo.org for patch including x-wap-profile header """
127 def _get_mms_message(self, location, transaction):
128 print "getting file: ", location
130 # TODO: remove hardcoded sleep
131 con = ConnectToAPN(self._apn_nicename)
136 notifyresp = self._send_notify_resp(transaction)
137 print "notifyresp sent"
139 print "notify sending failed..."
141 # TODO: configurable time-out?
143 socket.setdefaulttimeout(timeout)
144 (proxyurl, proxyport) = self.config.get_proxy_from_apn()
146 if proxyurl == "" or proxyurl == None:
147 print "connecting without proxy"
149 proxyfull = str(proxyurl) + ":" + str(proxyport)
150 print "connecting with proxy", proxyfull
151 proxy = urllib2.ProxyHandler({"http": proxyfull})
152 opener = urllib2.build_opener(proxy)
153 urllib2.install_opener(opener)
155 #headers = {'x-wap-profile': 'http://mms.frals.se/n900.rdf'}
156 #User-Agent: NokiaN95/11.0.026; Series60/3.1 Profile/MIDP-2.0 Configuration/CLDC-1.1
157 headers = {'User-Agent' : 'NokiaN95/11.0.026; Series60/3.1 Profile/MIDP-2.0 Configuration/CLDC-1.1', 'x-wap-profile' : 'http://mms.frals.se/n900.rdf'}
158 req = urllib2.Request(location, headers=headers)
159 mmsdata = urllib2.urlopen(req)
165 mmsdataall = mmsdata.read()
166 dirname = self.cont.save_binary_mms(mmsdataall, transaction)
169 print "fetched ", location, " and wrote to file"
171 # send acknowledge we got it ok
173 ack = self._send_acknowledge(transaction)
176 print "sending ack failed"
182 bus = dbus.SystemBus()
183 proxy = bus.get_object('org.freedesktop.Notifications', '/org/freedesktop/Notifications')
184 interface = dbus.Interface(proxy,dbus_interface='org.freedesktop.Notifications')
185 interface.SystemNoteInfoprint ("fMMS: Failed to download MMS message.")
191 def _send_notify_resp(self, transid):
192 mms = MMSMessage(True)
193 mms.headers['Message-Type'] = "m-notifyresp-ind"
194 mms.headers['Transaction-Id'] = transid
195 mms.headers['MMS-Version'] = "1.3"
196 mms.headers['Status'] = "Deferred"
198 print "setting up notify sender"
199 sender = MMSSender(customMMS=True)
200 print "sending notify..."
201 out = sender.sendMMS(mms)
202 print "m-notifyresp-ind:", out
206 def _send_acknowledge(self, transid):
207 mms = MMSMessage(True)
208 mms.headers['Message-Type'] = "m-acknowledge-ind"
209 mms.headers['Transaction-Id'] = transid
210 mms.headers['MMS-Version'] = "1.3"
212 print "setting up ack sender"
213 ack = MMSSender(customMMS=True)
214 print "sending ack..."
215 out = ack.sendMMS(mms)
216 print "m-acknowledge-ind:", out
221 def __init__(self, apn):
223 self.connection = conic.Connection()
225 def connection_cb(self, connection, event, magic):
226 print "connection_cb(%s, %s, %x)" % (connection, event, magic)
229 def disconnect(self):
230 connection = self.connection
231 connection.disconnect_by_id(self._apn)
236 # Creates the connection object and attach the handler.
237 connection = self.connection
238 iaps = connection.get_all_iaps()
241 if i.get_name() == self._apn:
244 connection.disconnect()
245 connection.connect("connection-event", self.connection_cb, magic)
247 # The request_connection method should be called to initialize
248 # some fields of the instance
250 assert(connection.request_connection(conic.CONNECT_FLAG_NONE))
252 #print "Getting by iap", iap.get_id()
253 assert(connection.request_connection_by_id(iap.get_id(), conic.CONNECT_FLAG_NONE))
256 """ class for sending an mms """
258 def __init__(self, number=None, subject=None, message=None, attachment=None, sender=None, customMMS=None):
259 print "GOT SENDER:", sender
260 print "customMMS:", customMMS
261 self.customMMS = customMMS
262 self.config = fMMSconf.fMMS_config()
263 if customMMS == None:
265 self.subject = subject
266 self.message = message
267 self.attachment = attachment
269 self._sender = sender
273 slide = message.MMSMessagePage()
274 if self.attachment != None:
275 slide.addImage(self.attachment)
276 slide.addText(self.message)
278 self._mms = message.MMSMessage()
279 self._mms.headers['Subject'] = self.subject
280 self._mms.headers['To'] = str(self.number) + '/TYPE=PLMN'
281 self._mms.headers['From'] = str(self._sender) + '/TYPE=PLMN'
282 self._mms.addPage(slide)
284 def sendMMS(self, customData=None):
286 if customData != None:
287 print "using custom mms"
288 self._mms = customData
290 mmsc = self.config.get_mmsc()
292 (proxyurl, proxyport) = self.config.get_proxy_from_apn()
293 mms = self._mms.encode()
295 headers = {'Content-Type':'application/vnd.wap.mms-message', 'User-Agent' : 'NokiaN95/11.0.026; Series60/3.1 Profile/MIDP-2.0 Configuration/CLDC-1.1', 'x-wap-profile' : 'http://mms.frals.se/n900.rdf'}
296 #headers = {'Content-Type':'application/vnd.wap.mms-message'}
297 if proxyurl == "" or proxyurl == None:
298 print "connecting without proxy"
300 mmsc = mmsc.replace("http://", "")
301 mmsc = mmsc.rstrip('/')
302 mmsc = mmsc.partition('/')
304 path = "/" + str(mmsc[2])
305 print "mmschost:", mmschost, "path:", path, "pathlen:", len(path)
306 conn = httplib.HTTPConnection(mmschost)
307 conn.request('POST', path , mms, headers)
309 print "connecting via proxy " + proxyurl + ":" + str(proxyport)
310 print "mmschost:", mmsc
311 conn = httplib.HTTPConnection(proxyurl + ":" + str(proxyport))
312 conn.request('POST', mmsc, mms, headers)
314 if customData == None:
315 cont = fMMSController.fMMS_controller()
316 path = cont.save_binary_outgoing_mms(mms, self._mms.transactionID)
317 message = cont.decode_binary_mms(path)
318 mmsid = cont.store_outgoing_mms(message)
320 res = conn.getresponse()
321 print "MMSC STATUS:", res.status, res.reason
324 decoder = mms_pdu.MMSDecoder()
325 data = array.array('B')
328 outparsed = decoder.decodeResponseHeader(data)
331 pushid = cont.store_outgoing_push(outparsed)
332 cont.link_push_mms(pushid, mmsid)
338 print "MMSC RESPONDED:", outparsed
339 return res.status, res.reason, outparsed