| Index: third_party/twisted_8_1/twisted/words/protocols/jabber/client.py
|
| diff --git a/third_party/twisted_8_1/twisted/words/protocols/jabber/client.py b/third_party/twisted_8_1/twisted/words/protocols/jabber/client.py
|
| deleted file mode 100644
|
| index 1cd126654d11919307b1f2e93ef39319cf15e205..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/words/protocols/jabber/client.py
|
| +++ /dev/null
|
| @@ -1,369 +0,0 @@
|
| -# -*- test-case-name: twisted.words.test.test_jabberclient -*-
|
| -#
|
| -# Copyright (c) 2001-2005 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -from twisted.internet import defer
|
| -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
|
| -
|
| - """
|
| - def __init__(self, xmlstream, type = "set"):
|
| - """
|
| - @type xmlstream: L{xmlstream.XmlStream}
|
| - @param xmlstream: XmlStream to use for transmission of this IQ
|
| -
|
| - @type type: L{str}
|
| - @param type: IQ type identifier ('get' or 'set')
|
| - """
|
| -
|
| - domish.Element.__init__(self, ("jabber:client", "iq"))
|
| - self.addUniqueId()
|
| - self["type"] = type
|
| - self._xmlstream = xmlstream
|
| - self.callbacks = utility.CallbackList()
|
| -
|
| - def addCallback(self, fn, *args, **kwargs):
|
| - """
|
| - Register a callback for notification when the IQ result is available.
|
| - """
|
| -
|
| - self.callbacks.addCallback(True, fn, *args, **kwargs)
|
| -
|
| - def send(self, to = None):
|
| - """
|
| - Call this method to send this IQ request via the associated XmlStream.
|
| -
|
| - @param to: Jabber ID of the entity to send the request to
|
| - @type to: L{str}
|
| -
|
| - @returns: Callback list for this IQ. Any callbacks added to this list
|
| - will be fired when the result comes back.
|
| - """
|
| - if to != None:
|
| - self["to"] = to
|
| - self._xmlstream.addOnetimeObserver("/iq[@id='%s']" % self["id"], \
|
| - self._resultEvent)
|
| - self._xmlstream.send(self)
|
| -
|
| - def _resultEvent(self, iq):
|
| - self.callbacks.callback(iq)
|
| - self.callbacks = None
|
| -
|
| -
|
| -
|
| -class IQAuthInitializer(object):
|
| - """
|
| - Non-SASL Authentication initializer for the initiating entity.
|
| -
|
| - This protocol is defined in
|
| - U{JEP-0078<http://www.jabber.org/jeps/jep-0078.html>} and mainly serves for
|
| - compatibility with pre-XMPP-1.0 server implementations.
|
| - """
|
| -
|
| - INVALID_USER_EVENT = "//event/client/basicauth/invaliduser"
|
| - AUTH_FAILED_EVENT = "//event/client/basicauth/authfailed"
|
| -
|
| - def __init__(self, xs):
|
| - self.xmlstream = xs
|
| -
|
| -
|
| - def initialize(self):
|
| - # Send request for auth fields
|
| - iq = xmlstream.IQ(self.xmlstream, "get")
|
| - iq.addElement(("jabber:iq:auth", "query"))
|
| - jid = self.xmlstream.authenticator.jid
|
| - iq.query.addElement("username", content = jid.user)
|
| -
|
| - d = iq.send()
|
| - d.addCallbacks(self._cbAuthQuery, self._ebAuthQuery)
|
| - return d
|
| -
|
| -
|
| - def _cbAuthQuery(self, iq):
|
| - jid = self.xmlstream.authenticator.jid
|
| - password = self.xmlstream.authenticator.password
|
| -
|
| - # Construct auth request
|
| - reply = xmlstream.IQ(self.xmlstream, "set")
|
| - reply.addElement(("jabber:iq:auth", "query"))
|
| - reply.query.addElement("username", content = jid.user)
|
| - reply.query.addElement("resource", content = jid.resource)
|
| -
|
| - # Prefer digest over plaintext
|
| - if DigestAuthQry.matches(iq):
|
| - digest = xmlstream.hashPassword(self.xmlstream.sid, password)
|
| - reply.query.addElement("digest", content = digest)
|
| - else:
|
| - reply.query.addElement("password", content = password)
|
| -
|
| - d = reply.send()
|
| - d.addCallbacks(self._cbAuth, self._ebAuth)
|
| - return d
|
| -
|
| -
|
| - def _ebAuthQuery(self, failure):
|
| - failure.trap(error.StanzaError)
|
| - e = failure.value
|
| - if e.condition == 'not-authorized':
|
| - self.xmlstream.dispatch(e.stanza, self.INVALID_USER_EVENT)
|
| - else:
|
| - self.xmlstream.dispatch(e.stanza, self.AUTH_FAILED_EVENT)
|
| -
|
| - return failure
|
| -
|
| -
|
| - def _cbAuth(self, iq):
|
| - pass
|
| -
|
| -
|
| - def _ebAuth(self, failure):
|
| - failure.trap(error.StanzaError)
|
| - self.xmlstream.dispatch(failure.value.stanza, self.AUTH_FAILED_EVENT)
|
| - return failure
|
| -
|
| -
|
| -
|
| -class BasicAuthenticator(xmlstream.ConnectAuthenticator):
|
| - """
|
| - Authenticates an XmlStream against a Jabber server as a Client.
|
| -
|
| - This only implements non-SASL authentication, per
|
| - U{JEP-0078<http://www.jabber.org/jeps/jep-0078.html>}. Additionally, this
|
| - authenticator provides the ability to perform inline registration, per
|
| - U{JEP-0077<http://www.jabber.org/jeps/jep-0077.html>}.
|
| -
|
| - Under normal circumstances, the BasicAuthenticator generates the
|
| - L{xmlstream.STREAM_AUTHD_EVENT} once the stream has authenticated. However,
|
| - it can also generate other events, such as:
|
| - - L{INVALID_USER_EVENT} : Authentication failed, due to invalid username
|
| - - L{AUTH_FAILED_EVENT} : Authentication failed, due to invalid password
|
| - - L{REGISTER_FAILED_EVENT} : Registration failed
|
| -
|
| - If authentication fails for any reason, you can attempt to register by
|
| - calling the L{registerAccount} method. If the registration succeeds, a
|
| - L{xmlstream.STREAM_AUTHD_EVENT} will be fired. Otherwise, one of the above
|
| - errors will be generated (again).
|
| - """
|
| -
|
| - namespace = "jabber:client"
|
| -
|
| - INVALID_USER_EVENT = IQAuthInitializer.INVALID_USER_EVENT
|
| - AUTH_FAILED_EVENT = IQAuthInitializer.AUTH_FAILED_EVENT
|
| - REGISTER_FAILED_EVENT = "//event/client/basicauth/registerfailed"
|
| -
|
| - def __init__(self, jid, password):
|
| - xmlstream.ConnectAuthenticator.__init__(self, jid.host)
|
| - self.jid = jid
|
| - self.password = password
|
| -
|
| - def associateWithStream(self, xs):
|
| - xs.version = (0, 0)
|
| - xmlstream.ConnectAuthenticator.associateWithStream(self, xs)
|
| -
|
| - inits = [ (xmlstream.TLSInitiatingInitializer, False),
|
| - (IQAuthInitializer, True),
|
| - ]
|
| -
|
| - for initClass, required in inits:
|
| - init = initClass(xs)
|
| - init.required = required
|
| - xs.initializers.append(init)
|
| -
|
| - # TODO: move registration into an Initializer?
|
| -
|
| - def registerAccount(self, username = None, password = None):
|
| - if username:
|
| - self.jid.user = username
|
| - if password:
|
| - self.password = password
|
| -
|
| - iq = IQ(self.xmlstream, "set")
|
| - iq.addElement(("jabber:iq:register", "query"))
|
| - iq.query.addElement("username", content = self.jid.user)
|
| - iq.query.addElement("password", content = self.password)
|
| -
|
| - iq.addCallback(self._registerResultEvent)
|
| -
|
| - iq.send()
|
| -
|
| - def _registerResultEvent(self, iq):
|
| - if iq["type"] == "result":
|
| - # Registration succeeded -- go ahead and auth
|
| - self.streamStarted()
|
| - else:
|
| - # Registration failed
|
| - self.xmlstream.dispatch(iq, self.REGISTER_FAILED_EVENT)
|
| -
|
| -
|
| -
|
| -class CheckVersionInitializer(object):
|
| - """
|
| - Initializer that checks if the minimum common stream version number is 1.0.
|
| - """
|
| -
|
| - def __init__(self, xs):
|
| - self.xmlstream = xs
|
| -
|
| -
|
| - def initialize(self):
|
| - if self.xmlstream.version < (1, 0):
|
| - raise error.StreamError('unsupported-version')
|
| -
|
| -
|
| -
|
| -class BindInitializer(xmlstream.BaseFeatureInitiatingInitializer):
|
| - """
|
| - Initializer that implements Resource Binding for the initiating entity.
|
| -
|
| - This protocol is documented in U{RFC 3920, section
|
| - 7<http://www.xmpp.org/specs/rfc3920.html#bind>}.
|
| - """
|
| -
|
| - feature = (NS_XMPP_BIND, 'bind')
|
| -
|
| - def start(self):
|
| - iq = xmlstream.IQ(self.xmlstream, 'set')
|
| - bind = iq.addElement((NS_XMPP_BIND, 'bind'))
|
| - resource = self.xmlstream.authenticator.jid.resource
|
| - if resource:
|
| - bind.addElement('resource', content=resource)
|
| - d = iq.send()
|
| - d.addCallback(self.onBind)
|
| - return d
|
| -
|
| -
|
| - def onBind(self, iq):
|
| - if iq.bind:
|
| - self.xmlstream.authenticator.jid = JID(unicode(iq.bind.jid))
|
| -
|
| -
|
| -
|
| -class SessionInitializer(xmlstream.BaseFeatureInitiatingInitializer):
|
| - """
|
| - Initializer that implements session establishment for the initiating
|
| - entity.
|
| -
|
| - This protocol is defined in U{RFC 3921, section
|
| - 3<http://www.xmpp.org/specs/rfc3921.html#session>}.
|
| - """
|
| -
|
| - feature = (NS_XMPP_SESSION, 'session')
|
| -
|
| - def start(self):
|
| - iq = xmlstream.IQ(self.xmlstream, 'set')
|
| - session = iq.addElement((NS_XMPP_SESSION, 'session'))
|
| - return iq.send()
|
| -
|
| -
|
| -
|
| -def XMPPClientFactory(jid, password):
|
| - """
|
| - Client factory for XMPP 1.0 (only).
|
| -
|
| - This returns a L{xmlstream.XmlStreamFactory} with an L{XMPPAuthenticator}
|
| - object to perform the stream initialization steps (such as authentication).
|
| -
|
| - @see: The notes at L{XMPPAuthenticator} describe how the L{jid} and
|
| - L{password} parameters are to be used.
|
| -
|
| - @param jid: Jabber ID to connect with.
|
| - @type jid: L{jid.JID}
|
| - @param password: password to authenticate with.
|
| - @type password: L{unicode}
|
| - @return: XML stream factory.
|
| - @rtype: L{xmlstream.XmlStreamFactory}
|
| - """
|
| - a = XMPPAuthenticator(jid, password)
|
| - return xmlstream.XmlStreamFactory(a)
|
| -
|
| -
|
| -
|
| -class XMPPAuthenticator(xmlstream.ConnectAuthenticator):
|
| - """
|
| - Initializes an XmlStream connecting to an XMPP server as a Client.
|
| -
|
| - This authenticator performs the initialization steps needed to start
|
| - exchanging XML stanzas with an XMPP server as an XMPP client. It checks if
|
| - the server advertises XML stream version 1.0, negotiates TLS (when
|
| - available), performs SASL authentication, binds a resource and establishes
|
| - a session.
|
| -
|
| - Upon successful stream initialization, the L{xmlstream.STREAM_AUTHD_EVENT}
|
| - event will be dispatched through the XML stream object. Otherwise, the
|
| - L{xmlstream.INIT_FAILED_EVENT} event will be dispatched with a failure
|
| - object.
|
| -
|
| - After inspection of the failure, initialization can then be restarted by
|
| - calling L{initializeStream}. For example, in case of authentication
|
| - failure, a user may be given the opportunity to input the correct password.
|
| - By setting the L{password} instance variable and restarting initialization,
|
| - the stream authentication step is then retried, and subsequent steps are
|
| - performed if succesful.
|
| -
|
| - @ivar jid: Jabber ID to authenticate with. This may contain a resource
|
| - part, as a suggestion to the server for resource binding. A
|
| - server may override this, though. If the resource part is left
|
| - off, the server will generate a unique resource identifier.
|
| - The server will always return the full Jabber ID in the
|
| - resource binding step, and this is stored in this instance
|
| - variable.
|
| - @type jid: L{jid.JID}
|
| - @ivar password: password to be used during SASL authentication.
|
| - @type password: L{unicode}
|
| - """
|
| -
|
| - namespace = 'jabber:client'
|
| -
|
| - def __init__(self, jid, password):
|
| - xmlstream.ConnectAuthenticator.__init__(self, jid.host)
|
| - self.jid = jid
|
| - self.password = password
|
| -
|
| -
|
| - def associateWithStream(self, xs):
|
| - """
|
| - Register with the XML stream.
|
| -
|
| - Populates stream's list of initializers, along with their
|
| - requiredness. This list is used by
|
| - L{ConnectAuthenticator.initializeStream} to perform the initalization
|
| - steps.
|
| - """
|
| - xmlstream.ConnectAuthenticator.associateWithStream(self, xs)
|
| -
|
| - xs.initializers = [CheckVersionInitializer(xs)]
|
| - inits = [ (xmlstream.TLSInitiatingInitializer, False),
|
| - (sasl.SASLInitiatingInitializer, True),
|
| - (BindInitializer, False),
|
| - (SessionInitializer, False),
|
| - ]
|
| -
|
| - for initClass, required in inits:
|
| - init = initClass(xs)
|
| - init.required = required
|
| - xs.initializers.append(init)
|
|
|