diff options
Diffstat (limited to 'sleekxmpp')
-rw-r--r-- | sleekxmpp/plugins/google/gmail/notifications.py | 4 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0009/remote.py | 54 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0065/proxy.py | 8 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0084/stanza.py | 9 | ||||
-rw-r--r-- | sleekxmpp/plugins/xep_0257/stanza.py | 2 | ||||
-rw-r--r-- | sleekxmpp/stanza/rootstanza.py | 4 | ||||
-rw-r--r-- | sleekxmpp/thirdparty/socks.py | 13 | ||||
-rw-r--r-- | sleekxmpp/util/__init__.py | 9 | ||||
-rw-r--r-- | sleekxmpp/util/sasl/mechanisms.py | 19 | ||||
-rw-r--r-- | sleekxmpp/xmlstream/xmlstream.py | 14 |
10 files changed, 98 insertions, 38 deletions
diff --git a/sleekxmpp/plugins/google/gmail/notifications.py b/sleekxmpp/plugins/google/gmail/notifications.py index 509a95fd..e65b2ca7 100644 --- a/sleekxmpp/plugins/google/gmail/notifications.py +++ b/sleekxmpp/plugins/google/gmail/notifications.py @@ -74,8 +74,8 @@ class Gmail(BasePlugin): return resp def _update_last_results(self, iq, callback=None): - self._last_result_time = data['gmail_messages']['result_time'] - threads = data['gmail_messages']['threads'] + self._last_result_time = iq['gmail_messages']['result_time'] + threads = iq['gmail_messages']['threads'] if threads: self._last_result_tid = threads[0]['tid'] if callback: diff --git a/sleekxmpp/plugins/xep_0009/remote.py b/sleekxmpp/plugins/xep_0009/remote.py index e85c3fa9..b02f587e 100644 --- a/sleekxmpp/plugins/xep_0009/remote.py +++ b/sleekxmpp/plugins/xep_0009/remote.py @@ -6,7 +6,7 @@ See the file LICENSE for copying permission. """ -from binding import py2xml, xml2py, xml2fault, fault2xml +from sleekxmpp.plugins.xep_0009.binding import py2xml, xml2py, xml2fault, fault2xml from threading import RLock import abc import inspect @@ -18,6 +18,45 @@ import traceback log = logging.getLogger(__name__) +# Define a function _isstr() to check if an object is a string in a way +# compatible with Python 2 and Python 3 (basestring does not exists in Python 3). +try: + basestring # This evaluation will throw an exception if basestring does not exists (Python 3). + def _isstr(obj): + return isinstance(obj, basestring) +except NameError: + def _isstr(obj): + return isinstance(obj, str) + + +# Class decorator to declare a metaclass to a class in a way compatible with Python 2 and 3. +# This decorator is copied from 'six' (https://bitbucket.org/gutworth/six): +# +# Copyright (c) 2010-2015 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +def _add_metaclass(metaclass): + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + def _intercept(method, name, public): def _resolver(instance, *args, **kwargs): log.debug("Locally calling %s.%s with arguments %s.", instance.FQN(), method.__name__, args) @@ -68,7 +107,7 @@ def remote(function_argument, public = True): if hasattr(function_argument, '__call__'): return _intercept(function_argument, None, public) else: - if not isinstance(function_argument, basestring): + if not _isstr(function_argument): if not isinstance(function_argument, bool): raise Exception('Expected an RPC method name or visibility modifier!') else: @@ -222,12 +261,11 @@ class TimeoutException(Exception): pass +@_add_metaclass(abc.ABCMeta) class Callback(object): ''' A base class for callback handlers. ''' - __metaclass__ = abc.ABCMeta - @abc.abstractproperty def set_value(self, value): @@ -291,7 +329,7 @@ class Future(Callback): self._event.set() - +@_add_metaclass(abc.ABCMeta) class Endpoint(object): ''' The Endpoint class is an abstract base class for all objects @@ -303,8 +341,6 @@ class Endpoint(object): which specifies which object an RPC call refers to. It is the first part in a RPC method name '<fqn>.<method>'. ''' - __metaclass__ = abc.ABCMeta - def __init__(self, session, target_jid): ''' @@ -491,7 +527,7 @@ class RemoteSession(object): def _find_key(self, dict, value): """return the key of dictionary dic given the value""" - search = [k for k, v in dict.iteritems() if v == value] + search = [k for k, v in dict.items() if v == value] if len(search) == 0: return None else: @@ -547,7 +583,7 @@ class RemoteSession(object): result = handler_cls(*args, **kwargs) Endpoint.__init__(result, self, self._client.boundjid.full) method_dict = result.get_methods() - for method_name, method in method_dict.iteritems(): + for method_name, method in method_dict.items(): #!!! self._client.plugin['xep_0009'].register_call(result.FQN(), method, method_name) self._register_call(result.FQN(), method, method_name) self._register_acl(result.FQN(), acl) diff --git a/sleekxmpp/plugins/xep_0065/proxy.py b/sleekxmpp/plugins/xep_0065/proxy.py index fdd9f97e..d890b57a 100644 --- a/sleekxmpp/plugins/xep_0065/proxy.py +++ b/sleekxmpp/plugins/xep_0065/proxy.py @@ -206,7 +206,7 @@ class XEP_0065(base_plugin): # Though this should not be neccessary remove the closed session anyway with self._sessions_lock: if sid in self._sessions: - log.warn(('SOCKS5 session with sid = "%s" was not ' + + log.warn(('SOCKS5 session with sid = "%s" was not ' + 'removed from _sessions by sock.close()') % sid) del self._sessions[sid] @@ -240,9 +240,9 @@ class XEP_0065(base_plugin): # The hostname MUST be SHA1(SID + Requester JID + Target JID) # where the output is hexadecimal-encoded (not binary). digest = sha1() - digest.update(sid) - digest.update(str(requester)) - digest.update(str(target)) + digest.update(sid.encode('utf-8')) + digest.update(str(requester).encode('utf-8')) + digest.update(str(target).encode('utf-8')) dest = digest.hexdigest() diff --git a/sleekxmpp/plugins/xep_0084/stanza.py b/sleekxmpp/plugins/xep_0084/stanza.py index 22f11b72..fd21e6f1 100644 --- a/sleekxmpp/plugins/xep_0084/stanza.py +++ b/sleekxmpp/plugins/xep_0084/stanza.py @@ -8,7 +8,7 @@ from base64 import b64encode, b64decode -from sleekxmpp.util import bytes +from sleekxmpp.util import bytes as sbytes from sleekxmpp.xmlstream import ET, ElementBase, register_stanza_plugin @@ -20,12 +20,15 @@ class Data(ElementBase): def get_value(self): if self.xml.text: - return b64decode(bytes(self.xml.text)) + return b64decode(sbytes(self.xml.text)) return '' def set_value(self, value): if value: - self.xml.text = b64encode(bytes(value)) + self.xml.text = b64encode(sbytes(value)) + # Python3 base64 encoded is bytes and needs to be decoded to string + if isinstance(self.xml.text, bytes): + self.xml.text = self.xml.text.decode() else: self.xml.text = '' diff --git a/sleekxmpp/plugins/xep_0257/stanza.py b/sleekxmpp/plugins/xep_0257/stanza.py index 17e20136..c3c41db2 100644 --- a/sleekxmpp/plugins/xep_0257/stanza.py +++ b/sleekxmpp/plugins/xep_0257/stanza.py @@ -10,7 +10,7 @@ from sleekxmpp.xmlstream import ElementBase, ET, register_stanza_plugin class Certs(ElementBase): - name = 'query' + name = 'items' namespace = 'urn:xmpp:saslcert:1' plugin_attrib = 'sasl_certs' interfaces = set() diff --git a/sleekxmpp/stanza/rootstanza.py b/sleekxmpp/stanza/rootstanza.py index a7c2b218..52b807e5 100644 --- a/sleekxmpp/stanza/rootstanza.py +++ b/sleekxmpp/stanza/rootstanza.py @@ -60,7 +60,9 @@ class RootStanza(StanzaBase): self.send() elif isinstance(e, XMPPError): # We raised this deliberately + keep_id = self['id'] self.reply(clear=e.clear) + self['id'] = keep_id self['error']['condition'] = e.condition self['error']['text'] = e.text self['error']['type'] = e.etype @@ -72,7 +74,9 @@ class RootStanza(StanzaBase): self.send() else: # We probably didn't raise this on purpose, so send an error stanza + keep_id = self['id'] self.reply() + self['id'] = keep_id self['error']['condition'] = 'undefined-condition' self['error']['text'] = "SleekXMPP got into trouble." self['error']['type'] = 'cancel' diff --git a/sleekxmpp/thirdparty/socks.py b/sleekxmpp/thirdparty/socks.py index 0c1f6eba..34090d51 100644 --- a/sleekxmpp/thirdparty/socks.py +++ b/sleekxmpp/thirdparty/socks.py @@ -28,6 +28,9 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. This module provides a standard socket-like interface for Python for tunneling connections through SOCKS proxies. +""" + +""" Minor modifications made by Christopher Gilbert (http://motomastyle.com/) for use in PyLoris (http://pyloris.sourceforge.net/) @@ -35,10 +38,13 @@ for use in PyLoris (http://pyloris.sourceforge.net/) Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/) mainly to merge bug fixes found in Sourceforge +Minor modifications made by Eugene Dementiev (http://www.dementiev.eu/) + """ import socket import struct +import sys PROXY_TYPE_SOCKS4 = 1 PROXY_TYPE_SOCKS5 = 2 @@ -208,7 +214,7 @@ class socksocket(socket.socket): if self.__proxy[3]: # Resolve remotely ipaddr = None - req = req + chr(0x03).encode() + chr(len(destaddr)).encode() + destaddr + req = req + chr(0x03).encode() + chr(len(destaddr)).encode() + destaddr.encode() else: # Resolve locally ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) @@ -323,7 +329,10 @@ class socksocket(socket.socket): # We read the response until we get the string "\r\n\r\n" resp = self.recv(1) while resp.find("\r\n\r\n".encode()) == -1: - resp = resp + self.recv(1) + recv = self.recv(1) + if not recv: + raise GeneralProxyError((1, _generalerrors[1])) + resp = resp + recv # We just need the first line to check if the connection # was successful statusline = resp.splitlines()[0].split(" ".encode(), 2) diff --git a/sleekxmpp/util/__init__.py b/sleekxmpp/util/__init__.py index 05286d33..47a935af 100644 --- a/sleekxmpp/util/__init__.py +++ b/sleekxmpp/util/__init__.py @@ -32,12 +32,17 @@ def _gevent_threads_enabled(): if _gevent_threads_enabled(): import gevent.queue as queue - Queue = queue.JoinableQueue + _queue = queue.JoinableQueue else: try: import queue except ImportError: import Queue as queue - Queue = queue.Queue + _queue = queue.Queue +class Queue(_queue): + def put(self, item, block=True, timeout=None): + if _queue.full(self): + _queue.get(self) + return _queue.put(self, item, block, timeout) QueueEmpty = queue.Empty diff --git a/sleekxmpp/util/sasl/mechanisms.py b/sleekxmpp/util/sasl/mechanisms.py index d341ed3e..7a7ebf7b 100644 --- a/sleekxmpp/util/sasl/mechanisms.py +++ b/sleekxmpp/util/sasl/mechanisms.py @@ -223,17 +223,16 @@ class SCRAM(Mech): return self.hash(text).digest() def saslname(self, value): - escaped = b'' - for char in bytes(value): - if char == b',': - escaped += b'=2C' - elif char == b'=': - escaped += b'=3D' + value = value.decode("utf-8") + escaped = [] + for char in value: + if char == ',': + escaped += '=2C' + elif char == '=': + escaped += '=3D' else: - if isinstance(char, int): - char = chr(char) - escaped += bytes(char) - return escaped + escaped += char + return "".join(escaped).encode("utf-8") def parse(self, challenge): items = {} diff --git a/sleekxmpp/xmlstream/xmlstream.py b/sleekxmpp/xmlstream/xmlstream.py index 01787b5e..f9ec4947 100644 --- a/sleekxmpp/xmlstream/xmlstream.py +++ b/sleekxmpp/xmlstream/xmlstream.py @@ -291,7 +291,7 @@ class XMLStream(object): self.event_queue = Queue() #: A queue of string data to be sent over the stream. - self.send_queue = Queue() + self.send_queue = Queue(maxsize=256) self.send_queue_lock = threading.Lock() self.send_lock = threading.RLock() @@ -460,9 +460,11 @@ class XMLStream(object): def _connect(self, reattempt=True): self.scheduler.remove('Session timeout check') - if self.reconnect_delay is None or not reattempt: + if self.reconnect_delay is None: delay = 1.0 - else: + self.reconnect_delay = delay + + if reattempt: delay = min(self.reconnect_delay * 2, self.reconnect_max_delay) delay = random.normalvariate(delay, delay * 0.1) log.debug('Waiting %s seconds before connecting.', delay) @@ -523,7 +525,8 @@ class XMLStream(object): 'keyfile': self.keyfile, 'ca_certs': self.ca_certs, 'cert_reqs': cert_policy, - 'do_handshake_on_connect': False + 'do_handshake_on_connect': False, + "ssl_version": self.ssl_version }) if sys.version_info >= (2, 7): @@ -847,7 +850,8 @@ class XMLStream(object): 'keyfile': self.keyfile, 'ca_certs': self.ca_certs, 'cert_reqs': cert_policy, - 'do_handshake_on_connect': False + 'do_handshake_on_connect': False, + "ssl_version": self.ssl_version }) if sys.version_info >= (2, 7): |