StropheCappuccino API 1.0.0
/tmp/tempDoc.doc/strophejs/examples/attach/boshclient.py
Go to the documentation of this file.
00001 import sys, os
00002 import httplib, urllib
00003 import random, binascii
00004 from urlparse import urlparse
00005 
00006 from punjab.httpb import HttpbParse
00007 
00008 from twisted.words.xish import domish
00009 from twisted.words.protocols.jabber import jid
00010 
00011 TLS_XMLNS = 'urn:ietf:params:xml:ns:xmpp-tls'
00012 SASL_XMLNS = 'urn:ietf:params:xml:ns:xmpp-sasl'
00013 BIND_XMLNS = 'urn:ietf:params:xml:ns:xmpp-bind'
00014 SESSION_XMLNS = 'urn:ietf:params:xml:ns:xmpp-session'
00015 
00016 
00017 class BOSHClient:
00018     def __init__(self, jabberid, password, bosh_service):
00019         self.rid = random.randint(0, 10000000)
00020         self.jabberid = jid.internJID(jabberid)
00021         self.password = password
00022 
00023         self.authid = None
00024         self.sid = None
00025         self.logged_in = False
00026         self.headers = {"Content-type": "text/xml",
00027                         "Accept": "text/xml"}
00028 
00029         self.bosh_service = urlparse(bosh_service)
00030         
00031     def buildBody(self, child=None):
00032         """Build a BOSH body.
00033         """
00034         
00035         body = domish.Element(("http://jabber.org/protocol/httpbind", "body"))
00036         body['content'] = 'text/xml; charset=utf-8'
00037         self.rid = self.rid + 1
00038         body['rid'] = str(self.rid)
00039         body['sid'] = str(self.sid)
00040         body['xml:lang'] = 'en'
00041      
00042         if child is not None:
00043             body.addChild(child)
00044 
00045         return body
00046         
00047     def sendBody(self, body):
00048         """Send the body.
00049         """
00050 
00051         parser = HttpbParse(True)
00052 
00053         # start new session
00054         conn = httplib.HTTPConnection(self.bosh_service.netloc)
00055         conn.request("POST", self.bosh_service.path, 
00056                      body.toXml(), self.headers)
00057 
00058         response = conn.getresponse()
00059         data = ''
00060         if response.status == 200:
00061             data = response.read()
00062         conn.close()
00063 
00064         return parser.parse(data)
00065 
00066     def startSessionAndAuth(self, hold='1', wait='70'):
00067         # Create a session
00068         # create body
00069         body = domish.Element(("http://jabber.org/protocol/httpbind", "body"))
00070 
00071         body['content'] = 'text/xml; charset=utf-8'
00072         body['hold'] = hold
00073         body['rid'] = str(self.rid)
00074         body['to'] = self.jabberid.host
00075         body['wait'] = wait
00076         body['window'] = '5'
00077         body['xml:lang'] = 'en'
00078 
00079 
00080         retb, elems = self.sendBody(body)
00081         if type(retb) != str and retb.hasAttribute('authid') and \
00082                 retb.hasAttribute('sid'):
00083             self.authid = retb['authid']
00084             self.sid = retb['sid']
00085 
00086             # go ahead and auth
00087             auth = domish.Element((SASL_XMLNS, 'auth'))
00088             auth['mechanism'] = 'PLAIN'
00089             
00090             # TODO: add authzid
00091             if auth['mechanism'] == 'PLAIN':
00092                 auth_str = ""
00093                 auth_str += "\000"
00094                 auth_str += self.jabberid.user.encode('utf-8')
00095                 auth_str += "\000"
00096                 try:
00097                     auth_str += self.password.encode('utf-8').strip()
00098                 except UnicodeDecodeError:
00099                     auth_str += self.password.decode('latin1') \
00100                         .encode('utf-8').strip()
00101                         
00102                 auth.addContent(binascii.b2a_base64(auth_str))
00103                 
00104                 retb, elems = self.sendBody(self.buildBody(auth))
00105                 if len(elems) == 0:
00106                     # poll for data
00107                     retb, elems = self.sendBody(self.buildBody())
00108 
00109                 if len(elems) > 0:
00110                     if elems[0].name == 'success':
00111                         retb, elems = self.sendBody(self.buildBody())
00112                         
00113                         has_bind = False
00114                         for child in elems[0].children:
00115                             if child.name == 'bind':
00116                                 has_bind = True
00117                                 break
00118 
00119                         if has_bind:
00120                             iq = domish.Element(('jabber:client', 'iq'))
00121                             iq['type'] = 'set'
00122                             iq.addUniqueId()
00123                             iq.addElement('bind')
00124                             iq.bind['xmlns'] = BIND_XMLNS
00125                             if self.jabberid.resource:
00126                                 iq.bind.addElement('resource')
00127                                 iq.bind.resource.addContent(
00128                                     self.jabberid.resource)
00129 
00130                             retb, elems = self.sendBody(self.buildBody(iq))
00131                             if type(retb) != str and retb.name == 'body':
00132                                 # send session
00133                                 iq = domish.Element(('jabber:client', 'iq'))
00134                                 iq['type'] = 'set'
00135                                 iq.addUniqueId()
00136                                 iq.addElement('session')
00137                                 iq.session['xmlns'] = SESSION_XMLNS
00138 
00139                                 retb, elems = self.sendBody(self.buildBody(iq))
00140 
00141                                 # did not bind, TODO - add a retry?
00142                                 if type(retb) != str and retb.name == 'body':
00143                                     self.logged_in = True
00144                                     # bump up the rid, punjab already 
00145                                     # received self.rid
00146                                     self.rid += 1
00147 
00148 
00149 if __name__ == '__main__':
00150     USERNAME = sys.argv[1]
00151     PASSWORD = sys.argv[2]
00152     SERVICE = sys.argv[3]
00153 
00154     c = BOSHClient(USERNAME, PASSWORD, SERVICE)
00155     c.startSessionAndAuth()
00156 
00157     print c.logged_in
00158     
 All Classes Namespaces Files Functions Variables