class IQAuthFeature(object): """ XEP-0078 : http://www.xmpp.org/extensions/xep-0078.html""" implements(IXMPPAuthenticationFeature) IQ_GET_AUTH = xpath.internQuery(ns.IQ_GET_AUTH) IQ_SET_AUTH = xpath.internQuery(ns.IQ_SET_AUTH) def associateWithStream(self, xs): """Add a streamm start event observer. And do other things to associate with the xmlstream if necessary. """ self.xmlstream = xs self.xmlstream.addOnetimeObserver(xmlstream.STREAM_START_EVENT, self.streamStarted) def disassociateWithStream(self, xs): self.xmlstream.removeObserver(self.IQ_GET_AUTH, self.authRequested) self.xmlstream.removeObserver(self.IQ_SET_AUTH, self.auth) self.xmlstream = None def streamStarted(self, elm): """ Called when client sends stream:stream """ self.xmlstream.addObserver(self.IQ_GET_AUTH, self.authRequested) self.xmlstream.addObserver(self.IQ_SET_AUTH, self.auth) def authRequested(self, elem): """Return the supported auth type. """ resp = domish.Element(('iq', ns.NS_CLIENT)) resp['type'] = 'result' resp['id'] = elem['id'] q = resp.addElement("query", ns.NS_AUTH) q.addElement("username", content=str(elem.query.username)) q.addElement("digest") q.addElement("password") q.addElement("resource") self.xmlstream.send(resp) def auth(self, elem): """Do not auth the user, anyone can log in""" username = elem.query.username.__str__() resource = elem.query.resource.__str__() user = jid.internJID(username + '@' + self.xmlstream.host + '/' + resource) resp = domish.Element(('iq', ns.NS_CLIENT)) resp['type'] = 'result' resp['id'] = elem['id'] self.xmlstream.send(resp) self.xmlstream.authenticated(user)
class JabberRouter(JabberComponent): routes = None # this is probably just a helper for the router # to speed things up if we already know where to go NAMED_ROUTE = xpath.internQuery("""/route""") def __init__(self, *args, **kw): JabberComponent.__init__(self, *args, **kw) self.bootstraps = [(self.NAMED_ROUTE, self.onNamedRoute)] #self.routes = [] def startService(self): JabberComponent.startService(self) for event, fn in self.bootstraps: self.addObserver(event, fn) def onNamedRoute(self, elm): print "i know where to go" pass def onElement(self, elm): print "routing element", elm.toXml() JabberComponent.onElement(self, elm)
def _getEventAndObservers(self, event): if isinstance(event, xpath.XPathQuery): # Treat as xpath observers = self._xpathObservers else: if self.prefix == event[:len(self.prefix)]: # Treat as event observers = self._eventObservers else: # Treat as xpath event = xpath.internQuery(event) observers = self._xpathObservers return event, observers
def handleRequest(self, xml): """ Find a handler and call it directly """ handler = None iq = parseXml(xml) for queryString, method in self.service.iqHandlers.iteritems(): if xpath.internQuery(queryString).matches(iq): handler = getattr(self.service, method) if handler: d = defer.maybeDeferred(handler, iq) else: d = defer.fail(NotImplementedError()) return d
def handleRequest(self, iq): """ Find a handler and wrap the call for sending a response stanza. """ def toResult(result, iq): response = toResponse(iq, 'result') if result: if IElement.providedBy(result): response.addChild(result) else: for element in result: response.addChild(element) return response def checkNotImplemented(failure): failure.trap(NotImplementedError) raise error.StanzaError('feature-not-implemented') def fromStanzaError(failure, iq): failure.trap(error.StanzaError) return failure.value.toResponse(iq) def fromOtherError(failure, iq): log.msg("Unhandled error in iq handler:", isError=True) log.err(failure) return error.StanzaError('internal-server-error').toResponse(iq) handler = None for queryString, method in self.iqHandlers.iteritems(): if xpath.internQuery(queryString).matches(iq): handler = getattr(self, method) if handler: d = defer.maybeDeferred(handler, iq) else: d = defer.fail(NotImplementedError()) d.addCallback(toResult, iq) d.addErrback(checkNotImplemented) d.addErrback(fromStanzaError, iq) d.addErrback(fromOtherError, iq) d.addCallback(self.send) iq.handled = True
def handleRequest(self, iq): """ Find a handler and wrap the call for sending a response stanza. """ def toResult(result, iq): response = toResponse(iq, 'result') if result: if IElement.providedBy(result): response.addChild(result) else: for element in result: response.addChild(element) return response def checkNotImplemented(failure): failure.trap(NotImplementedError) raise error.StanzaError('feature-not-implemented') def fromStanzaError(failure, iq): e = failure.trap(error.StanzaError) return failure.value.toResponse(iq) def fromOtherError(failure, iq): log.msg("Unhandled error in iq handler:", isError=True) log.err(failure) return error.StanzaError('internal-server-error').toResponse(iq) handler = None for queryString, method in self.iqHandlers.iteritems(): if xpath.internQuery(queryString).matches(iq): handler = getattr(self, method) if handler: d = defer.maybeDeferred(handler, iq) else: d = defer.fail(NotImplementedError()) d.addCallback(toResult, iq) d.addErrback(checkNotImplemented) d.addErrback(fromStanzaError, iq) d.addErrback(fromOtherError, iq) d.addCallback(self.send) iq.handled = True
def removeObserver(self, event, observerfn): """ Remove function as observer for an event. The observer function is removed for all priority levels for the specified event. @param event: Event for which the observer function was registered. @type event: L{str} or L{xpath.XPathQuery} @param observerfn: Observer function to be unregistered. """ # If this is happening in the middle of the dispatch, queue # it up for processing after the dispatch completes if self._dispatchDepth > 0: self._updateQueue.append( lambda: self.removeObserver(event, observerfn)) return observers = None if _isStr(event): if self.prefix == event[0:len(self.prefix)]: observers = self._eventObservers else: event = xpath.internQuery(event) observers = self._xpathObservers else: observers = self._xpathObservers for priority, query in observers: if event == query: observers[(priority, query)].removeCallback(observerfn) # Update the priority ordered list of xpath keys -- # This really oughta be rethought for efficiency self._orderedEventObserverKeys = self._eventObservers.keys() self._orderedEventObserverKeys.sort() self._orderedEventObserverKeys.reverse() self._orderedXpathObserverKeys = self._xpathObservers.keys() self._orderedXpathObserverKeys.sort() self._orderedXpathObserverKeys.reverse()
def handleRequest(self, xml): """ Find a handler and call it directly. @param xml: XML stanza that may yield a handler being called. @type xml: C{str}. @return: Deferred that fires with the result of a handler for this stanza. If no handler was found, the deferred has its errback called with a C{NotImplementedError} exception. """ handler = None iq = parseXml(xml) for queryString, method in iteritems(self.service.iqHandlers): if xpath.internQuery(queryString).matches(iq): handler = getattr(self.service, method) if handler: d = defer.maybeDeferred(handler, iq) else: d = defer.fail(NotImplementedError()) return d
def _addObserver(self, onetime, event, observerfn, priority, *args, **kwargs): # If this is happening in the middle of the dispatch, queue # it up for processing after the dispatch completes if self._dispatchDepth > 0: self._updateQueue.append(lambda: self.addObserver( event, observerfn, priority, *args, **kwargs)) return observers = None if _isStr(event): if self.prefix == event[0:len(self.prefix)]: # Treat as event observers = self._eventObservers else: # Treat as xpath event = xpath.internQuery(event) observers = self._xpathObservers else: # Treat as xpath observers = self._xpathObservers key = (priority, event) if not key in observers: cbl = CallbackList() cbl.addCallback(onetime, observerfn, *args, **kwargs) observers[key] = cbl else: observers[key].addCallback(onetime, observerfn, *args, **kwargs) # Update the priority ordered list of xpath keys -- # This really oughta be rethought for efficiency self._orderedEventObserverKeys = self._eventObservers.keys() self._orderedEventObserverKeys.sort() self._orderedEventObserverKeys.reverse() self._orderedXpathObserverKeys = self._xpathObservers.keys() self._orderedXpathObserverKeys.sort() self._orderedXpathObserverKeys.reverse()
import re import htmlentitydefs from twisted.web.client import getPage from twisted.internet import reactor from twisted.names.srvconnect import SRVConnector from twisted.words.xish import domish, xpath from twisted.words.protocols.jabber import xmlstream, client, jid from twisted.python import log import messenger from rcore import config, scheduler from hermes.contacts import Contact, AT_XMPP from rcore.core import Core MessageWithBody = xpath.internQuery("/message/body") MessageWithError = xpath.internQuery("/message/error") ## # Removes HTML or XML character references and entities from a text string. # # @param text The HTML (or XML) source text. # @return The plain text, as a Unicode string, if necessary. def unescape(text): def fixup(m): text = m.group(0) if text[:2] == "&#": # character reference try:
class JabberComponentProxy(JabberProtocol): namespace = NS_COMPONENT ROUTE_ADDED = xpath.internQuery("/iq/route/add") ROUTE_REMOVED = xpath.internQuery("/iq/route/remove") # this is the routing bits def _handle(self, elm): self.send(elm) def _onElement(self, elm): #print "routing to", self.parent self.factory.handle(elm) #def addObserver(self, event, observerfn, *args, **kw): # print "add observer!", event, observerfn # JabberProtocol.addObserver(self, event, observerfn, *args, **kw) def _addForwardingObserver(self, event, observerfn, priority=0, *args, **kw): JabberProtocol.addObserver(self, event, observerfn, priority, *args, **kw) self.addRoute(event, priority) def _removeForwardingObserver(self, event, observerfn): raise NotImplementedError def addRoute(self, event, priority=0): iq = IQRequest("set") r = iq.addElement("route", NS_ROUTE) a = r.addElement("add") a.addElement("xpath", content=event.queryStr) a.addElement("priority", content=priority) d = iq.send(self) def success(elm): self.routes[event] = str(elm.route.id) d.addCallback(success) #inherited callbacks def streamAuthenticated(self, elm): JabberProtocol.streamAuthenticated(self, elm) self.addObserver(self.ROUTE_ADDED, self.routeAdded) self.addObserver(self.ROUTE_REMOVED, self.routeRemoved) # we are going to switch to the forwarding observer style now self.addObserver = self._addForwardingObserver self.removeObverser = self._removeForwardingObserver self.handle = self._handle self.onElement = self._onElement # callbacks def routeAdded(self, elm): # just xpath for now q = elm.route.add.xpath p = elm.route.add.priority id = elm.id # the callback will basically just be to send # the data to the remote host self.parent.addObserver(q, self.send, p) # add this route to our store of routes self.routes[id] = q # respond to the reques # TODO def routeRemoved(self, elm): # just xpath for now id = elm.route.remove.id self.parent.removeObserver(self.routes[id], self.send)
# -*- test-case-name: twisted.words.test.test_jabberclient -*- # # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.words.xish import domish, xpath, utility from twisted.words.protocols.jabber import xmlstream, sasl, error from twisted.words.protocols.jabber.jid import JID NS_XMPP_STREAMS = 'urn:ietf:params:xml:ns:xmpp-streams' NS_XMPP_BIND = 'urn:ietf:params:xml:ns:xmpp-bind' NS_XMPP_SESSION = 'urn:ietf:params:xml:ns:xmpp-session' NS_IQ_AUTH_FEATURE = 'http://jabber.org/features/iq-auth' DigestAuthQry = xpath.internQuery("/iq/query/digest") PlaintextAuthQry = xpath.internQuery("/iq/query/password") def basicClientFactory(jid, secret): a = BasicAuthenticator(jid, secret) return xmlstream.XmlStreamFactory(a) class IQ(domish.Element): """ Wrapper for a Info/Query packet. This provides the necessary functionality to send IQs and get notified when a result comes back. It's a subclass from L{domish.Element}, so you can use the standard DOM manipulation calls to add data to the outbound request.
# -*- test-case-name: twisted.words.test.test_jabberclient -*- # # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.words.xish import domish, xpath, utility from twisted.words.protocols.jabber import xmlstream, sasl, error from twisted.words.protocols.jabber.jid import JID NS_XMPP_STREAMS = 'urn:ietf:params:xml:ns:xmpp-streams' NS_XMPP_BIND = 'urn:ietf:params:xml:ns:xmpp-bind' NS_XMPP_SESSION = 'urn:ietf:params:xml:ns:xmpp-session' NS_IQ_AUTH_FEATURE = 'http://jabber.org/features/iq-auth' DigestAuthQry = xpath.internQuery("/iq/query/digest") PlaintextAuthQry = xpath.internQuery("/iq/query/password") def basicClientFactory(jid, secret): a = BasicAuthenticator(jid, secret) return xmlstream.XmlStreamFactory(a) class IQ(domish.Element): """ Wrapper for a Info/Query packet. This provides the necessary functionality to send IQs and get notified when a result comes back. It's a subclass from L{domish.Element}, so you can use the standard DOM manipulation calls to add data to the outbound request. @type callbacks: L{utility.CallbackList} @cvar callbacks: Callback list to be notified when response comes back
class NonSASLAuthenticationFeature(object): """JEP-0078""" implements(IJabberAuthenticationFeature) feature = "some_feature_id" # event triggers AUTH_FIELDS_REQUESTED_EVENT = \ xpath.internQuery("""/iq[@type="get"]/query[@xmlns="jabber:iq:auth"]""") AUTH_FIELDS_PROVIDED_EVENT = \ xpath.internQuery("""/iq[@type="set"]/query[@xmlns="jabber:iq:auth"]""") def associateWithStream(self, xs): """do all the things necessary to register ourselves with the xmlstream """ self.xmlstream = xs self.xmlstream.addOnetimeObserver(xmlstream.STREAM_START_EVENT, self.streamStarted) def disassociateWithStream(self, xs): if not self.xmlstream.initiating: self.xmlstream.removeObserver(self.AUTH_FIELDS_REQUESTED_EVENT, self.authFieldsRequested) self.xmlstream.removeObserver(self.AUTH_FIELDS_PROVIDED_EVENT, self.authFieldsProvided) self.xmlstream = None #actions def authenticate(self): self.requestAuthFields() def checkSupported(self, *args): """return a deferred, callback with self on success, errback""" def requestAuthFields(self): #iq = IQRequest("get", to=self.xmlstream.otherHost pass def provideAuthFields(self): pass #callbacks def streamStarted(self, elm): if not self.xmlstream.initiating: self.xmlstream.addObserver(self.AUTH_FIELDS_REQUESTED_EVENT, self.authFieldsRequested) self.xmlstream.addObserver(self.AUTH_FIELDS_PROVIDED_EVENT, self.authFieldsProvided) def authFieldsRequested(self, elm): """return the types of auth fields that are supported""" print "auth fields requested!" resp = IQStanza(type="result", id=elm['id']) q = resp.addElement("query", "jabber:iq:auth") q.addElement("username", content=str(elm.query.username)) q.addElement("digest") q.addElement("password") q.addElement("resource") self.xmlstream.send(resp) def authFieldsProvided(self, elm): """authenticate the user or return an error""" # XXX andy: theoretically this defers the actual authentication to # the factory/service print "auth fields provided!" user = JabberUser(self.xmlstream.host, str(elm.query.username), str(elm.query.resource)) resp = IQStanza(type="result", id=elm['id']) self.xmlstream.send(resp) # XXX andy: for now I am just makign a user class, # there is surely a better way to do this self.xmlstream.authenticated(user)
class IMFeature(object): implements(IJabberFeature) feature = "blah" ROSTER_REQUESTED_EVENT = \ xpath.internQuery("""/iq[@type="get"]/query[@xmlns="jabber:iq:roster"]""") def associateWithStream(self, xs): self.xmlstream = xs self.xmlstream.addObserver(self.ROSTER_REQUESTED_EVENT, self.rosterRequested) def rosterRequested(self, elm): #raise NotImplementedError print "roster requested!" #return id = elm['id'] msg = """<iq from="%s" type="result" id="%s" > <query xmlns="jabber:iq:roster"> <item subscription="from" jid="*****@*****.**" /> <item subscription="to" jid="*****@*****.**" > <group>.be</group> </item> <item subscription="both" jid="*****@*****.**" > <group>sf</group> </item> <item subscription="both" jid="*****@*****.**" > <group>sf</group> </item> <item subscription="both" jid="*****@*****.**" > <group>.be</group> </item> <item ask="subscribe" subscription="none" jid="*****@*****.**" > <group>.de</group> </item> <item subscription="both" jid="*****@*****.**" > <group>.de</group> </item> <item subscription="both" jid="*****@*****.**" > <group>...</group> </item> <item subscription="both" jid="*****@*****.**" > <group>...</group> </item> <item subscription="both" jid="*****@*****.**" > <group>.nl</group> </item> <item subscription="both" jid="*****@*****.**" > <group>.nl</group> </item> <item subscription="both" jid="*****@*****.**" > <group>.nl</group> </item> <item subscription="both" jid="*****@*****.**" > <group>.nl</group> </item> <item subscription="both" jid="*****@*****.**" > <group>.nl</group> </item> </query> </iq> """%(str(self.xmlstream.user), id) self.xmlstream.send(msg)
class NonSASLAuthenticationFeature(object): """JEP-0078""" implements(IJabberAuthenticationFeature) feature = "some_feature_id" # event triggers AUTH_FIELDS_REQUESTED_EVENT = \ xpath.internQuery("""/iq[@type="get"]/query[@xmlns="jabber:iq:auth"]""") AUTH_FIELDS_PROVIDED_EVENT = \ xpath.internQuery("""/iq[@type="set"]/query[@xmlns="jabber:iq:auth"]""") def associateWithStream(self, xs): """do all the things necessary to register ourselves with the xmlstream """ self.xmlstream = xs if not self.xmlstream.initiating: self.xmlstream.addOnetimeObserver(xmlstream.STREAM_START_EVENT, self.streamStarted) def disassociateWithStream(self, xs): if not self.xmlstream.initiating: self.xmlstream.removeObserver(self.AUTH_FIELDS_REQUESTED_EVENT, self.authFieldsRequested) self.xmlstream.removeObserver(self.AUTH_FIELDS_PROVIDED_EVENT, self.authFieldsProvided) self.xmlstream = None #actions def authenticate(self): return self.provideAuthFields() def checkSupported(self, *args): """return a deferred, callback with self on success, errback""" return self.requestAuthFields() def requestAuthFields(self): iq = IQRequest("get") q = iq.addElement("query", "jabber:iq:auth") q.addElement("username", content=self.xmlstream.name) d = iq.send(self.xmlstream) d.addCallback(lambda _: self) return d def provideAuthFields(self): iq = IQRequest("set") iq.addElement("query", "jabber:iq:auth") iq.query.addElement("username", content=self.xmlstream.name) iq.query.addElement("digest", content="9f5e1dbdf5b65451bf6502eeda6eaa359319007c") if hasattr(self.xmlstream, "resource"): iq.query.addElement("resource", content=self.xmlstream.resource) d = iq.send(self.xmlstream) return d pass #callbacks def streamStarted(self, elm): if not self.xmlstream.initiating: self.xmlstream.addObserver(self.AUTH_FIELDS_REQUESTED_EVENT, self.authFieldsRequested) self.xmlstream.addObserver(self.AUTH_FIELDS_PROVIDED_EVENT, self.authFieldsProvided) def authFieldsRequested(self, elm): """return the types of auth fields that are supported""" print "auth fields requested!" resp = IQStanza(type="result", id=elm['id']) q = resp.addElement("query", "jabber:iq:auth") q.addElement("username", content=str(elm.query.username)) q.addElement("digest") q.addElement("password") q.addElement("resource") self.xmlstream.send(resp) def authFieldsProvided(self, elm): """authenticate the user or return an error""" # XXX andy: theoretically this defers the actual authentication to # the factory/service print "auth fields provided!" #user = JabberUser(self.xmlstream.host, str(elm.query.username), str(elm.query.resource)) resp = IQStanza(type="result", id=elm['id']) self.xmlstream.send(resp) self.xmlstream.dispatch(None, STREAM_AUTHD_EVENT)