diff options
author | Yann Leboulanger <asterix@lagaule.org> | 2011-06-21 01:03:06 +0400 |
---|---|---|
committer | Yann Leboulanger <asterix@lagaule.org> | 2011-06-21 01:03:06 +0400 |
commit | b47248f09d4a167c34bdd21786b6e39ed920fa1f (patch) | |
tree | bd8071662e5629eafa0b9e5eac75e727aec63d82 /src/common/xmpp | |
parent | ac0e0448b2626a6e0d7269119d2383ee69c7ea56 (diff) | |
parent | 21ae286039ccd2c361b795593979b904287e2e51 (diff) |
merge from trunk
Diffstat (limited to 'src/common/xmpp')
-rw-r--r-- | src/common/xmpp/bosh.py | 9 | ||||
-rw-r--r-- | src/common/xmpp/client_nb.py | 5 | ||||
-rw-r--r-- | src/common/xmpp/dispatcher_nb.py | 1 | ||||
-rw-r--r-- | src/common/xmpp/features_nb.py | 9 | ||||
-rw-r--r-- | src/common/xmpp/idlequeue.py | 13 | ||||
-rw-r--r-- | src/common/xmpp/protocol.py | 370 | ||||
-rw-r--r-- | src/common/xmpp/tls_nb.py | 10 | ||||
-rw-r--r-- | src/common/xmpp/transports_nb.py | 6 |
8 files changed, 234 insertions, 189 deletions
diff --git a/src/common/xmpp/bosh.py b/src/common/xmpp/bosh.py index 08796c4fe..353e79826 100644 --- a/src/common/xmpp/bosh.py +++ b/src/common/xmpp/bosh.py @@ -23,7 +23,7 @@ from hashlib import sha1 from transports_nb import NonBlockingTransport, NonBlockingHTTPBOSH,\ CONNECTED, CONNECTING, DISCONNECTED, DISCONNECTING,\ urisplit, DISCONNECT_TIMEOUT_SECONDS -from protocol import BOSHBody +from protocol import BOSHBody, Protocol, NS_CLIENT from simplexml import Node import logging @@ -190,13 +190,18 @@ class NonBlockingBOSH(NonBlockingTransport): # when called after HTTP response (Payload=None) and when there are already # some pending requests and no data to send, or when the socket is # disconnected, we do nothing - if payload is None and \ + if payload is None and \ total_pending_reqs > 0 and \ self.stanza_buffer == [] and \ self.prio_bosh_stanzas == [] or \ self.get_state()==DISCONNECTED: return + # Add xmlns to stanza to help ejabberd server + if payload and isinstance(payload, Protocol): + if not payload.getNamespace(): + payload.setNamespace(NS_CLIENT) + # now the payload is put to buffer and will be sent at some point self.append_stanza(payload) diff --git a/src/common/xmpp/client_nb.py b/src/common/xmpp/client_nb.py index 44ea3ba3e..dc4c4476b 100644 --- a/src/common/xmpp/client_nb.py +++ b/src/common/xmpp/client_nb.py @@ -60,6 +60,7 @@ class NonBlockingClient: self._owner = self self._registered_name = None # our full jid, set after successful auth self.connected = '' + self.ip_addresses = [] self.socket = None self.on_connect = None self.on_proxy_failure = None @@ -76,6 +77,9 @@ class NonBlockingClient: the client. """ # to avoid recursive calls + if self.ip_addresses: + self._try_next_ip() + return if self.disconnecting: return log.info('Disconnecting NBClient: %s' % message) @@ -317,6 +321,7 @@ class NonBlockingClient: elif mode == 'RECEIVE_DOCUMENT_ATTRIBUTES': if data: self.Dispatcher.ProcessNonBlocking(data) + self.ip_addresses = [] if not hasattr(self, 'Dispatcher') or \ self.Dispatcher.Stream._document_attrs is None: self._xmpp_connect_machine( diff --git a/src/common/xmpp/dispatcher_nb.py b/src/common/xmpp/dispatcher_nb.py index 54274928a..cca56f33a 100644 --- a/src/common/xmpp/dispatcher_nb.py +++ b/src/common/xmpp/dispatcher_nb.py @@ -154,6 +154,7 @@ class XMPPDispatcher(PlugIn): """ Send an initial stream header """ + self._owner.Connection.sendqueue = [] self.Stream = simplexml.NodeBuilder() self.Stream.dispatch = self.dispatch self.Stream._dispatch_depth = 2 diff --git a/src/common/xmpp/features_nb.py b/src/common/xmpp/features_nb.py index 19d216015..9dd39082e 100644 --- a/src/common/xmpp/features_nb.py +++ b/src/common/xmpp/features_nb.py @@ -58,23 +58,24 @@ def _ReceivedRegInfo(con, resp, agent): Iq('get', NS_REGISTER, to=agent) if not isResultNode(resp): error_msg = resp.getErrorMsg() - con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, None, False, error_msg)) + con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, None, False, error_msg, '')) return tag=resp.getTag('query', namespace=NS_REGISTER) if not tag: error_msg = resp.getErrorMsg() - con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, None, False, error_msg)) + con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, None, False, error_msg, '')) return df=tag.getTag('x', namespace=NS_DATA) if df: - con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, df, True, '')) + con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, df, True, '', + tag)) return df={} for i in resp.getQueryPayload(): if not isinstance(i, Node): continue df[i.getName()] = i.getData() - con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, df, False, '')) + con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, df, False, '', '')) def register(disp, host, info, cb, args=None): """ diff --git a/src/common/xmpp/idlequeue.py b/src/common/xmpp/idlequeue.py index 1b0bccb04..86e33418f 100644 --- a/src/common/xmpp/idlequeue.py +++ b/src/common/xmpp/idlequeue.py @@ -388,20 +388,25 @@ class IdleQueue: self.unplug_idle(fd) return False + read_write = False if flags & PENDING_READ: #print 'waiting read on %d, flags are %d' % (fd, flags) obj.pollin() - return True + read_write = True - elif flags & PENDING_WRITE: + elif flags & PENDING_WRITE and not flags & IS_CLOSED: obj.pollout() - return True + read_write = True - elif flags & IS_CLOSED: + if flags & IS_CLOSED: # io error, don't expect more events self.remove_timeout(obj.fd) self.unplug_idle(obj.fd) obj.pollend() + return False + + if read_write: + return True return False def process(self): diff --git a/src/common/xmpp/protocol.py b/src/common/xmpp/protocol.py index f1a1666ff..df4b57a82 100644 --- a/src/common/xmpp/protocol.py +++ b/src/common/xmpp/protocol.py @@ -22,132 +22,140 @@ sub- stanzas) handling routines from simplexml import Node, NodeBuilder import time - -NS_ACTIVITY ='http://jabber.org/protocol/activity' # XEP-0108 -NS_ADDRESS ='http://jabber.org/protocol/address' # XEP-0033 -NS_AGENTS ='jabber:iq:agents' -NS_AMP ='http://jabber.org/protocol/amp' -NS_AMP_ERRORS =NS_AMP+'#errors' -NS_ARCHIVE ='urn:xmpp:archive' #XEP-0136 -NS_ARCHIVE_AUTO =NS_ARCHIVE+':auto' #XEP-0136 -NS_ARCHIVE_MANAGE =NS_ARCHIVE+':manage' #XEP-0136 -NS_ARCHIVE_MANUAL =NS_ARCHIVE+':manual' #XEP-0136 -NS_ARCHIVE_PREF =NS_ARCHIVE+':pref' -NS_ATOM ='http://www.w3.org/2005/Atom' -NS_AUTH ='jabber:iq:auth' -NS_AVATAR ='http://www.xmpp.org/extensions/xep-0084.html#ns-metadata' -NS_BIND ='urn:ietf:params:xml:ns:xmpp-bind' -NS_BOB ='urn:xmpp:bob' #XEP-0231 -NS_BROWSE ='jabber:iq:browse' -NS_BROWSING ='http://jabber.org/protocol/browsing' # XEP-0195 -NS_BYTESTREAM ='http://jabber.org/protocol/bytestreams' # JEP-0065 -NS_CAPS ='http://jabber.org/protocol/caps' # JEP-0115 -NS_CAPTCHA ='urn:xmpp:captcha' # XEP-0158 -NS_CHATSTATES ='http://jabber.org/protocol/chatstates' # JEP-0085 -NS_CHATTING ='http://jabber.org/protocol/chatting' # XEP-0194 -NS_CLIENT ='jabber:client' -NS_COMMANDS ='http://jabber.org/protocol/commands' -NS_COMPONENT_ACCEPT='jabber:component:accept' -NS_COMPONENT_1 ='http://jabberd.jabberstudio.org/ns/component/1.0' -NS_COMPRESS ='http://jabber.org/protocol/compress' # XEP-0138 -NS_CONFERENCE ='jabber:x:conference' -NS_DATA ='jabber:x:data' # XEP-0004 -NS_DATA_MEDIA ='urn:xmpp:media-element' # XEP-0221 -NS_DELAY ='jabber:x:delay' -NS_DELAY2 ='urn:xmpp:delay' -NS_DIALBACK ='jabber:server:dialback' -NS_DISCO ='http://jabber.org/protocol/disco' -NS_DISCO_INFO =NS_DISCO+'#info' -NS_DISCO_ITEMS =NS_DISCO+'#items' -NS_ENCRYPTED ='jabber:x:encrypted' # XEP-0027 -NS_ESESSION ='http://www.xmpp.org/extensions/xep-0116.html#ns' -NS_ESESSION_INIT='http://www.xmpp.org/extensions/xep-0116.html#ns-init' # XEP-0116 -NS_EVENT ='jabber:x:event' # XEP-0022 -NS_FEATURE ='http://jabber.org/protocol/feature-neg' -NS_FILE ='http://jabber.org/protocol/si/profile/file-transfer' # JEP-0096 -NS_GAMING ='http://jabber.org/protocol/gaming' # XEP-0196 -NS_GEOLOC ='http://jabber.org/protocol/geoloc' # JEP-0080 -NS_GROUPCHAT ='gc-1.0' -NS_HTTP_AUTH ='http://jabber.org/protocol/http-auth' # XEP-0070 -NS_HTTP_BIND ='http://jabber.org/protocol/httpbind' # XEP-0124 -NS_IBB ='http://jabber.org/protocol/ibb' -NS_INVISIBLE ='presence-invisible' # Jabberd2 -NS_IQ ='iq' # Jabberd2 -NS_JINGLE ='urn:xmpp:jingle:1' # XEP-0166 -NS_JINGLE_ERRORS='urn:xmpp:jingle:errors:1' # XEP-0166 -NS_JINGLE_RTP ='urn:xmpp:jingle:apps:rtp:1' # XEP-0167 -NS_JINGLE_RTP_AUDIO='urn:xmpp:jingle:apps:rtp:audio' # XEP-0167 -NS_JINGLE_RTP_VIDEO='urn:xmpp:jingle:apps:rtp:video' # XEP-0167 -NS_JINGLE_FILE_TRANSFER='urn:xmpp:jingle:apps:file-transfer:1' # XEP-0234 -NS_JINGLE_XTLS='urn:xmpp:jingle:security:xtls:0' # XTLS: EXPERIMENTAL security layer of jingle -NS_JINGLE_RAW_UDP='urn:xmpp:jingle:transports:raw-udp:1' # XEP-0177 -NS_JINGLE_ICE_UDP='urn:xmpp:jingle:transports:ice-udp:1' # XEP-0176 -NS_JINGLE_BYTESTREAM ='urn:xmpp:jingle:transports:s5b:1' # XEP-0260 -NS_LAST ='jabber:iq:last' -NS_LOCATION ='http://jabber.org/protocol/geoloc' # XEP-0080 -NS_MESSAGE ='message' # Jabberd2 -NS_MOOD ='http://jabber.org/protocol/mood' # XEP-0107 -NS_MUC ='http://jabber.org/protocol/muc' -NS_MUC_USER =NS_MUC+'#user' -NS_MUC_ADMIN =NS_MUC+'#admin' -NS_MUC_OWNER =NS_MUC+'#owner' -NS_MUC_UNIQUE =NS_MUC+'#unique' -NS_MUC_CONFIG =NS_MUC+'#roomconfig' -NS_NICK ='http://jabber.org/protocol/nick' # XEP-0172 -NS_OFFLINE ='http://www.jabber.org/jeps/jep-0030.html' # XEP-0013 -NS_PHYSLOC ='http://jabber.org/protocol/physloc' # XEP-0112 -NS_PING ='urn:xmpp:ping' # SEP-0199 -NS_PRESENCE ='presence' # Jabberd2 -NS_PRIVACY ='jabber:iq:privacy' -NS_PRIVATE ='jabber:iq:private' -NS_PROFILE ='http://jabber.org/protocol/profile' # XEP-0154 -NS_PUBSUB ='http://jabber.org/protocol/pubsub' # XEP-0060 -NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event' -NS_PUBSUB_PUBLISH_OPTIONS = NS_PUBSUB + '#publish-options' # XEP-0060 -NS_PUBSUB_OWNER ='http://jabber.org/protocol/pubsub#owner' # JEP-0060 -NS_REGISTER ='jabber:iq:register' -NS_ROSTER ='jabber:iq:roster' -NS_ROSTERX ='http://jabber.org/protocol/rosterx' # XEP-0144 -NS_ROSTER_VER ='urn:xmpp:features:rosterver' # XEP-0273 -NS_RPC ='jabber:iq:rpc' # XEP-0009 -NS_RSM ='http://jabber.org/protocol/rsm' -NS_SASL ='urn:ietf:params:xml:ns:xmpp-sasl' -NS_SECLABEL ='urn:xmpp:sec-label:0' -NS_SECLABEL_CATALOG ='urn:xmpp:sec-label:catalog:0' -NS_SEARCH ='jabber:iq:search' -NS_SERVER ='jabber:server' -NS_SESSION ='urn:ietf:params:xml:ns:xmpp-session' -NS_SI ='http://jabber.org/protocol/si' # XEP-0096 -NS_SI_PUB ='http://jabber.org/protocol/sipub' # XEP-0137 -NS_SIGNED ='jabber:x:signed' # XEP-0027 -NS_SSN ='urn:xmpp:ssn' # XEP-0155 -NS_STANZA_CRYPTO='http://www.xmpp.org/extensions/xep-0200.html#ns' # XEP-0200 -NS_STANZAS ='urn:ietf:params:xml:ns:xmpp-stanzas' -NS_STREAM ='http://affinix.com/jabber/stream' -NS_STREAMS ='http://etherx.jabber.org/streams' -NS_TIME ='jabber:iq:time' # XEP-0900 -NS_TIME_REVISED ='urn:xmpp:time' # XEP-0202 -NS_TLS ='urn:ietf:params:xml:ns:xmpp-tls' -NS_TUNE ='http://jabber.org/protocol/tune' # XEP-0118 -NS_VACATION ='http://jabber.org/protocol/vacation' -NS_VCARD ='vcard-temp' -NS_GMAILNOTIFY ='google:mail:notify' -NS_GTALKSETTING ='google:setting' -NS_VCARD_UPDATE =NS_VCARD+':x:update' -NS_VERSION ='jabber:iq:version' -NS_VIEWING ='http://jabber.org/protocol/viewing' # XEP--197 -NS_WAITINGLIST ='http://jabber.org/protocol/waitinglist' # XEP-0130 -NS_XHTML_IM ='http://jabber.org/protocol/xhtml-im' # XEP-0071 -NS_XHTML = 'http://www.w3.org/1999/xhtml' # " -NS_DATA_LAYOUT ='http://jabber.org/protocol/xdata-layout' # XEP-0141 -NS_DATA_VALIDATE='http://jabber.org/protocol/xdata-validate' # XEP-0122 -NS_XMPP_STREAMS ='urn:ietf:params:xml:ns:xmpp-streams' -NS_RECEIPTS ='urn:xmpp:receipts' +import string + +def ascii_upper(s): + trans_table = string.maketrans(string.ascii_lowercase, + string.ascii_uppercase) + return s.translate(trans_table) + +NS_ACTIVITY = 'http://jabber.org/protocol/activity' # XEP-0108 +NS_ADDRESS = 'http://jabber.org/protocol/address' # XEP-0033 +NS_AGENTS = 'jabber:iq:agents' +NS_AMP = 'http://jabber.org/protocol/amp' +NS_AMP_ERRORS = NS_AMP + '#errors' +NS_ARCHIVE = 'urn:xmpp:archive' # XEP-0136 +NS_ARCHIVE_AUTO = NS_ARCHIVE + ':auto' # XEP-0136 +NS_ARCHIVE_MANAGE = NS_ARCHIVE + ':manage' # XEP-0136 +NS_ARCHIVE_MANUAL = NS_ARCHIVE + ':manual' # XEP-0136 +NS_ARCHIVE_PREF = NS_ARCHIVE + ':pref' +NS_ATOM = 'http://www.w3.org/2005/Atom' +NS_AUTH = 'jabber:iq:auth' +NS_AVATAR = 'http://www.xmpp.org/extensions/xep-0084.html#ns-metadata' +NS_BIND = 'urn:ietf:params:xml:ns:xmpp-bind' +NS_BOB = 'urn:xmpp:bob' # XEP-0231 +NS_BOOKMARKS = 'storage:bookmarks' # XEP-0048 +NS_BROWSE = 'jabber:iq:browse' +NS_BROWSING = 'http://jabber.org/protocol/browsing' # XEP-0195 +NS_BYTESTREAM = 'http://jabber.org/protocol/bytestreams' # JEP-0065 +NS_CAPS = 'http://jabber.org/protocol/caps' # JEP-0115 +NS_CAPTCHA = 'urn:xmpp:captcha' # XEP-0158 +NS_CHATSTATES = 'http://jabber.org/protocol/chatstates' # JEP-0085 +NS_CHATTING = 'http://jabber.org/protocol/chatting' # XEP-0194 +NS_CLIENT = 'jabber:client' +NS_COMMANDS = 'http://jabber.org/protocol/commands' +NS_COMPONENT_ACCEPT = 'jabber:component:accept' +NS_COMPONENT_1 = 'http://jabberd.jabberstudio.org/ns/component/1.0' +NS_COMPRESS = 'http://jabber.org/protocol/compress' # XEP-0138 +NS_CONFERENCE = 'jabber:x:conference' +NS_DATA = 'jabber:x:data' # XEP-0004 +NS_DATA_MEDIA = 'urn:xmpp:media-element' # XEP-0221 +NS_DELAY = 'jabber:x:delay' +NS_DELAY2 = 'urn:xmpp:delay' +NS_DIALBACK = 'jabber:server:dialback' +NS_DISCO = 'http://jabber.org/protocol/disco' +NS_DISCO_INFO = NS_DISCO + '#info' +NS_DISCO_ITEMS = NS_DISCO + '#items' +NS_ENCRYPTED = 'jabber:x:encrypted' # XEP-0027 +NS_ESESSION = 'http://www.xmpp.org/extensions/xep-0116.html#ns' +NS_ESESSION_INIT = 'http://www.xmpp.org/extensions/xep-0116.html#ns-init' # XEP-0116 +NS_EVENT = 'jabber:x:event' # XEP-0022 +NS_FEATURE = 'http://jabber.org/protocol/feature-neg' +NS_FILE = 'http://jabber.org/protocol/si/profile/file-transfer' # JEP-0096 +NS_GAMING = 'http://jabber.org/protocol/gaming' # XEP-0196 +NS_GATEWAY = 'jabber:iq:gateway' # XEP-0100 +NS_GEOLOC = 'http://jabber.org/protocol/geoloc' # XEP-0080 +NS_GROUPCHAT = 'gc-1.0' +NS_HTTP_AUTH = 'http://jabber.org/protocol/http-auth' # XEP-0070 +NS_HTTP_BIND = 'http://jabber.org/protocol/httpbind' # XEP-0124 +NS_IBB = 'http://jabber.org/protocol/ibb' +NS_INVISIBLE = 'presence-invisible' # Jabberd2 +NS_IQ = 'iq' # Jabberd2 +NS_JINGLE ='urn:xmpp:jingle:1' # XEP-0166 +NS_JINGLE_ERRORS = 'urn:xmpp:jingle:errors:1' # XEP-0166 +NS_JINGLE_RTP = 'urn:xmpp:jingle:apps:rtp:1' # XEP-0167 +NS_JINGLE_RTP_AUDIO = 'urn:xmpp:jingle:apps:rtp:audio' # XEP-0167 +NS_JINGLE_RTP_VIDEO = 'urn:xmpp:jingle:apps:rtp:video' # XEP-0167 +NS_JINGLE_FILE_TRANSFER='urn:xmpp:jingle:apps:file-transfer:1' # XEP-0234 +NS_JINGLE_XTLS='urn:xmpp:jingle:security:xtls:0' # XTLS: EXPERIMENTAL security layer of jingle +NS_JINGLE_RAW_UDP = 'urn:xmpp:jingle:transports:raw-udp:1' # XEP-0177 +NS_JINGLE_ICE_UDP = 'urn:xmpp:jingle:transports:ice-udp:1' # XEP-0176 +NS_JINGLE_BYTESTREAM ='urn:xmpp:jingle:transports:s5b:1' # XEP-0260 +NS_LAST = 'jabber:iq:last' +NS_LOCATION = 'http://jabber.org/protocol/geoloc' # XEP-0080 +NS_MESSAGE = 'message' # Jabberd2 +NS_MOOD = 'http://jabber.org/protocol/mood' # XEP-0107 +NS_MUC = 'http://jabber.org/protocol/muc' +NS_MUC_USER = NS_MUC + '#user' +NS_MUC_ADMIN = NS_MUC + '#admin' +NS_MUC_OWNER = NS_MUC + '#owner' +NS_MUC_UNIQUE = NS_MUC + '#unique' +NS_MUC_CONFIG = NS_MUC + '#roomconfig' +NS_NICK = 'http://jabber.org/protocol/nick' # XEP-0172 +NS_OFFLINE = 'http://www.jabber.org/jeps/jep-0030.html' # XEP-0013 +NS_PHYSLOC = 'http://jabber.org/protocol/physloc' # XEP-0112 +NS_PING = 'urn:xmpp:ping' # SEP-0199 +NS_PRESENCE = 'presence' # Jabberd2 +NS_PRIVACY = 'jabber:iq:privacy' +NS_PRIVATE = 'jabber:iq:private' +NS_PROFILE = 'http://jabber.org/protocol/profile' # XEP-0154 +NS_PUBSUB = 'http://jabber.org/protocol/pubsub' # XEP-0060 +NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event' +NS_PUBSUB_PUBLISH_OPTIONS = NS_PUBSUB + '#publish-options' # XEP-0060 +NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner' # JEP-0060 +NS_REGISTER = 'jabber:iq:register' +NS_ROSTER = 'jabber:iq:roster' +NS_ROSTERNOTES = 'storage:rosternotes' +NS_ROSTERX = 'http://jabber.org/protocol/rosterx' # XEP-0144 +NS_ROSTER_VER = 'urn:xmpp:features:rosterver' # XEP-0273 +NS_RPC = 'jabber:iq:rpc' # XEP-0009 +NS_RSM = 'http://jabber.org/protocol/rsm' +NS_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl' +NS_SECLABEL = 'urn:xmpp:sec-label:0' +NS_SECLABEL_CATALOG = 'urn:xmpp:sec-label:catalog:0' +NS_SEARCH = 'jabber:iq:search' +NS_SERVER = 'jabber:server' +NS_SESSION = 'urn:ietf:params:xml:ns:xmpp-session' +NS_SI = 'http://jabber.org/protocol/si' # XEP-0096 +NS_SI_PUB = 'http://jabber.org/protocol/sipub' # XEP-0137 +NS_SIGNED = 'jabber:x:signed' # XEP-0027 +NS_SSN = 'urn:xmpp:ssn' # XEP-0155 +NS_STANZA_CRYPTO = 'http://www.xmpp.org/extensions/xep-0200.html#ns' # XEP-0200 +NS_STANZAS = 'urn:ietf:params:xml:ns:xmpp-stanzas' +NS_STREAM = 'http://affinix.com/jabber/stream' +NS_STREAMS = 'http://etherx.jabber.org/streams' +NS_TIME = 'jabber:iq:time' # XEP-0900 +NS_TIME_REVISED = 'urn:xmpp:time' # XEP-0202 +NS_TLS = 'urn:ietf:params:xml:ns:xmpp-tls' +NS_TUNE = 'http://jabber.org/protocol/tune' # XEP-0118 +NS_VACATION = 'http://jabber.org/protocol/vacation' +NS_VCARD = 'vcard-temp' +NS_GMAILNOTIFY = 'google:mail:notify' +NS_GTALKSETTING = 'google:setting' +NS_VCARD_UPDATE = NS_VCARD + ':x:update' +NS_VERSION = 'jabber:iq:version' +NS_VIEWING = 'http://jabber.org/protocol/viewing' # XEP--197 +NS_WAITINGLIST = 'http://jabber.org/protocol/waitinglist' # XEP-0130 +NS_XHTML_IM = 'http://jabber.org/protocol/xhtml-im' # XEP-0071 +NS_XHTML = 'http://www.w3.org/1999/xhtml' # " +NS_DATA_LAYOUT = 'http://jabber.org/protocol/xdata-layout' # XEP-0141 +NS_DATA_VALIDATE = 'http://jabber.org/protocol/xdata-validate' # XEP-0122 +NS_XMPP_STREAMS = 'urn:ietf:params:xml:ns:xmpp-streams' +NS_RECEIPTS = 'urn:xmpp:receipts' NS_PUBKEY_PUBKEY='urn:xmpp:pubkey:2' # XEP-0189 NS_PUBKEY_REVOKE='urn:xmpp:revoke:2' NS_PUBKEY_ATTEST='urn:xmpp:attest:2' - xmpp_stream_error_conditions = ''' bad-format -- -- -- The entity has sent XML that cannot be processed. bad-namespace-prefix -- -- -- The entity has sent a namespace prefix that is unsupported, or has sent no namespace prefix on an element that requires such a prefix. @@ -208,12 +216,12 @@ not-authorized -- -- -- The authentication failed because the initiating entit temporary-auth-failure -- -- -- The authentication failed because of a temporary error condition within the receiving entity; sent in reply to an <auth/> element or <response/> element.''' ERRORS, _errorcodes = {}, {} -for ns, errname, errpool in ((NS_XMPP_STREAMS, 'STREAM', xmpp_stream_error_conditions), - (NS_STANZAS, 'ERR', xmpp_stanza_error_conditions), - (NS_SASL, 'SASL', sasl_error_conditions)): +for ns, errname, errpool in ((NS_XMPP_STREAMS, 'STREAM', +xmpp_stream_error_conditions), (NS_STANZAS, 'ERR', xmpp_stanza_error_conditions), +(NS_SASL, 'SASL', sasl_error_conditions)): for err in errpool.split('\n')[1:]: cond, code, typ, text = err.split(' -- ') - name = errname + '_' + cond.upper().replace('-', '_') + name = errname + '_' + ascii_upper(cond).replace('-', '_') locals()[name] = ns + ' ' + cond ERRORS[ns + ' ' + cond] = [code, typ, text] if code: @@ -318,29 +326,29 @@ class XMLNotWellFormed(StreamError): pass stream_exceptions = {'bad-format': BadFormat, - 'bad-namespace-prefix': BadNamespacePrefix, - 'conflict': Conflict, - 'connection-timeout': ConnectionTimeout, - 'host-gone': HostGone, - 'host-unknown': HostUnknown, - 'improper-addressing': ImproperAddressing, - 'internal-server-error': InternalServerError, - 'invalid-from': InvalidFrom, - 'invalid-id': InvalidID, - 'invalid-namespace': InvalidNamespace, - 'invalid-xml': InvalidXML, - 'not-authorized': NotAuthorized, - 'policy-violation': PolicyViolation, - 'remote-connection-failed': RemoteConnectionFailed, - 'resource-constraint': ResourceConstraint, - 'restricted-xml': RestrictedXML, - 'see-other-host': SeeOtherHost, - 'system-shutdown': SystemShutdown, - 'undefined-condition': UndefinedCondition, - 'unsupported-encoding': UnsupportedEncoding, - 'unsupported-stanza-type': UnsupportedStanzaType, - 'unsupported-version': UnsupportedVersion, - 'xml-not-well-formed': XMLNotWellFormed} + 'bad-namespace-prefix': BadNamespacePrefix, + 'conflict': Conflict, + 'connection-timeout': ConnectionTimeout, + 'host-gone': HostGone, + 'host-unknown': HostUnknown, + 'improper-addressing': ImproperAddressing, + 'internal-server-error': InternalServerError, + 'invalid-from': InvalidFrom, + 'invalid-id': InvalidID, + 'invalid-namespace': InvalidNamespace, + 'invalid-xml': InvalidXML, + 'not-authorized': NotAuthorized, + 'policy-violation': PolicyViolation, + 'remote-connection-failed': RemoteConnectionFailed, + 'resource-constraint': ResourceConstraint, + 'restricted-xml': RestrictedXML, + 'see-other-host': SeeOtherHost, + 'system-shutdown': SystemShutdown, + 'undefined-condition': UndefinedCondition, + 'unsupported-encoding': UnsupportedEncoding, + 'unsupported-stanza-type': UnsupportedStanzaType, + 'unsupported-version': UnsupportedVersion, + 'xml-not-well-formed': XMLNotWellFormed} class JID: """ @@ -358,7 +366,8 @@ class JID: if not jid and not domain: raise ValueError('JID must contain at least domain name') elif type(jid) == type(self): - self.node, self.domain, self.resource = jid.node, jid.domain, jid.resource + self.node, self.domain = jid.node, jid.domain + self.resource = jid.resource elif domain: self.node, self.domain, self.resource = node, domain, resource else: @@ -379,7 +388,8 @@ class JID: def setNode(self, node): """ - Set the node part of the JID to new value. Specify None to remove the node part + Set the node part of the JID to new value. Specify None to remove + the node part """ self.node = node.lower() @@ -422,7 +432,8 @@ class JID: other = JID(other) except ValueError: return 0 - return self.resource == other.resource and self.__str__(0) == other.__str__(0) + return self.resource == other.resource and \ + self.__str__(0) == other.__str__(0) def __ne__(self, other): """ @@ -450,7 +461,8 @@ class JID: def __hash__(self): """ - Produce hash of the JID, Allows to use JID objects as keys of the dictionary + Produce hash of the JID, Allows to use JID objects as keys of the + dictionary """ return hash(str(self)) @@ -473,7 +485,8 @@ class Protocol(Node): def __init__(self, name=None, to=None, typ=None, frm=None, attrs={}, payload=[], timestamp=None, xmlns=None, node=None): """ - Constructor, name is the name of the stanza i.e. 'message' or 'presence' or 'iq' + Constructor, name is the name of the stanza + i.e. 'message' or 'presence'or 'iq' to is the value of 'to' attribure, 'typ' - 'type' attribute frn - from attribure, attrs - other attributes mapping, @@ -497,7 +510,8 @@ class Protocol(Node): self.setTo(self['to']) if self['from']: self.setFrom(self['from']) - if node and type(self) == type(node) and self.__class__ == node.__class__ and self.attrs.has_key('id'): + if node and type(self) == type(node) and \ + self.__class__ == node.__class__ and self.attrs.has_key('id'): del self.attrs['id'] self.timestamp = None for d in self.getTags('delay', namespace=NS_DELAY2): @@ -588,19 +602,20 @@ class Protocol(Node): def getError(self): """ - Return the error-condition (if present) or the textual description of the - error (otherwise) + Return the error-condition (if present) or the textual description + of the error (otherwise) """ errtag = self.getTag('error') if errtag: for tag in errtag.getChildren(): - if tag.getName() <> 'text': + if tag.getName() != 'text': return tag.getName() return errtag.getData() def getErrorMsg(self): """ - Return the textual description of the error (if present) or the error condition + Return the textual description of the error (if present) + or the error condition """ errtag = self.getTag('error') if errtag: @@ -615,7 +630,7 @@ class Protocol(Node): """ return self.getTagAttr('error', 'code') - def setError(self,error,code=None): + def setError(self, error, code=None): """ Set the error code. Obsolete. Use error-conditions instead """ @@ -623,7 +638,8 @@ class Protocol(Node): if str(code) in _errorcodes.keys(): error = ErrorNode(_errorcodes[str(code)], text=error) else: - error = ErrorNode(ERR_UNDEFINED_CONDITION, code=code, typ='cancel', text=error) + error = ErrorNode(ERR_UNDEFINED_CONDITION, code=code, + typ='cancel', text=error) elif type(error) in [type(''), type(u'')]: error=ErrorNode(error) self.setType('error') @@ -664,8 +680,8 @@ class Message(Protocol): """ def __init__(self, to=None, body=None, xhtml=None, typ=None, subject=None, - attrs={}, frm=None, payload=[], timestamp=None, xmlns=NS_CLIENT, - node=None): + attrs={}, frm=None, payload=[], timestamp=None, xmlns=NS_CLIENT, + node=None): """ You can specify recipient, text of message, type of message any additional attributes, sender of the message, any additional payload @@ -675,7 +691,7 @@ class Message(Protocol): parameted to replicate it as message """ Protocol.__init__(self, 'message', to=to, typ=typ, attrs=attrs, frm=frm, - payload=payload, timestamp=timestamp, xmlns=xmlns, node=node) + payload=payload, timestamp=timestamp, xmlns=xmlns, node=node) if body: self.setBody(body) if xhtml: @@ -728,9 +744,11 @@ class Message(Protocol): """ try: if xmllang: - dom = NodeBuilder('<body xmlns="%s" xml:lang="%s">%s</body>' % (NS_XHTML, xmllang, val)).getDom() + dom = NodeBuilder('<body xmlns="%s" xml:lang="%s">%s</body>' \ + % (NS_XHTML, xmllang, val)).getDom() else: - dom = NodeBuilder('<body xmlns="%s">%s</body>, 0' % (NS_XHTML, val)).getDom() + dom = NodeBuilder('<body xmlns="%s">%s</body>' % (NS_XHTML, + val), 0).getDom() if self.getTag('html'): self.getTag('html').addChild(node=dom) else: @@ -776,8 +794,8 @@ class Message(Protocol): class Presence(Protocol): def __init__(self, to=None, typ=None, priority=None, show=None, status=None, - attrs={}, frm=None, timestamp=None, payload=[], xmlns=NS_CLIENT, - node=None): + attrs={}, frm=None, timestamp=None, payload=[], xmlns=NS_CLIENT, + node=None): """ You can specify recipient, type of message, priority, show and status values any additional attributes, sender of the presence, timestamp, any @@ -786,7 +804,7 @@ class Presence(Protocol): parameted to replicate it as presence """ Protocol.__init__(self, 'presence', to=to, typ=typ, attrs=attrs, frm=frm, - payload=payload, timestamp=timestamp, xmlns=xmlns, node=node) + payload=payload, timestamp=timestamp, xmlns=xmlns, node=node) if priority: self.setPriority(priority) if show: @@ -851,6 +869,7 @@ class Presence(Protocol): Return the presence role (for groupchat) """ return self._muc_getItemAttr('item', 'role') + def getAffiliation(self): """ Return the presence affiliation (for groupchat) @@ -906,7 +925,8 @@ class Iq(Protocol): Alternatively you can pass in the other XML object as the 'node' parameted to replicate it as an iq """ - Protocol.__init__(self, 'iq', to=to, typ=typ, attrs=attrs, frm=frm, xmlns=xmlns, node=node) + Protocol.__init__(self, 'iq', to=to, typ=typ, attrs=attrs, frm=frm, + xmlns=xmlns, node=node) if payload: self.setQueryPayload(payload) if queryNS: @@ -981,7 +1001,8 @@ class ErrorNode(Node): def __init__(self, name, code=None, typ=None, text=None): """ Mandatory parameter: name - name of error condition. - Optional parameters: code, typ, text. Used for backwards compartibility with older jabber protocol. + Optional parameters: code, typ, text. + Used for backwards compartibility with older jabber protocol. """ if name in ERRORS: cod, type_, txt = ERRORS[name] @@ -1046,8 +1067,8 @@ class DataField(Node): Create new data field of specified name,value and type Also 'required','desc' and 'options' fields can be set. Alternatively - other XML object can be passed in as the 'node' parameted to replicate it - as a new datafiled. + other XML object can be passed in as the 'node' parameted + to replicate it as a new datafiled. """ Node.__init__(self, 'field', node=node) if name: @@ -1156,7 +1177,8 @@ class DataField(Node): if isinstance(opt, basestring): self.addChild('option').setTagData('value', opt) else: - self.addChild('option', {'label': opt[0]}).setTagData('value', opt[1]) + self.addChild('option', {'label': opt[0]}).setTagData('value', + opt[1]) def getType(self): """ diff --git a/src/common/xmpp/tls_nb.py b/src/common/xmpp/tls_nb.py index 1cbb99c57..7a9c80f98 100644 --- a/src/common/xmpp/tls_nb.py +++ b/src/common/xmpp/tls_nb.py @@ -384,8 +384,13 @@ class NonBlockingTLS(PlugIn): else: # See http://docs.python.org/dev/library/ssl.html tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD) - tcpsock._sslContext.set_options(OpenSSL.SSL.OP_NO_SSLv2 | \ - OpenSSL.SSL.OP_NO_TICKET) + flags = OpenSSL.SSL.OP_NO_SSLv2 + try: + flags |= OpenSSL.SSL.OP_NO_TICKET + except AttributeError, e: + # py-OpenSSL < 0.9 or old OpenSSL + flags |= 16384 + tcpsock._sslContext.set_options(flags) tcpsock.ssl_errnum = 0 tcpsock._sslContext.set_verify(OpenSSL.SSL.VERIFY_PEER, @@ -444,6 +449,7 @@ class NonBlockingTLS(PlugIn): # Exceptions can't propagate up through this callback, so print them here. try: self._owner.ssl_fingerprint_sha1 = cert.digest('sha1') + self._owner.ssl_certificate = cert if errnum == 0: return True self._owner.ssl_errnum = errnum diff --git a/src/common/xmpp/transports_nb.py b/src/common/xmpp/transports_nb.py index 2b0a57c9d..9430ef654 100644 --- a/src/common/xmpp/transports_nb.py +++ b/src/common/xmpp/transports_nb.py @@ -740,15 +740,15 @@ class NonBlockingHTTP(NonBlockingTCP): httpbody - string with http body) http_rest - what is left in the message after a full HTTP header + body """ - message = message.replace('\r', '') - message = message.lstrip('\n') - splitted = message.split('\n\n') + splitted = message.split('\r\n\r\n') if len(splitted) < 2: # no complete http message. Keep filling the buffer until we find one buffer_rest = message return ('', '', '', buffer_rest) else: (header, httpbody) = splitted[:2] + header = header.replace('\r', '') + header = header.lstrip('\n') header = header.split('\n') statusline = header[0].split(' ', 2) header = header[1:] |