diff options
Diffstat (limited to 'slixmpp')
-rw-r--r-- | slixmpp/features/feature_mechanisms/mechanisms.py | 5 | ||||
-rw-r--r-- | slixmpp/jid.py | 61 | ||||
-rw-r--r-- | slixmpp/plugins/xep_0030/disco.py | 16 | ||||
-rw-r--r-- | slixmpp/plugins/xep_0077/register.py | 2 | ||||
-rw-r--r-- | slixmpp/plugins/xep_0153/vcard_avatar.py | 5 | ||||
-rw-r--r-- | slixmpp/plugins/xep_0163.py | 10 | ||||
-rw-r--r-- | slixmpp/plugins/xep_0199/ping.py | 5 | ||||
-rw-r--r-- | slixmpp/plugins/xep_0223.py | 2 | ||||
-rw-r--r-- | slixmpp/plugins/xep_0363/http_upload.py | 25 | ||||
-rw-r--r-- | slixmpp/stanza/iq.py | 4 | ||||
-rw-r--r-- | slixmpp/test/slixtest.py | 12 | ||||
-rw-r--r-- | slixmpp/util/sasl/mechanisms.py | 6 | ||||
-rw-r--r-- | slixmpp/version.py | 4 | ||||
-rw-r--r-- | slixmpp/xmlstream/stanzabase.py | 14 | ||||
-rw-r--r-- | slixmpp/xmlstream/tostring.py | 15 | ||||
-rw-r--r-- | slixmpp/xmlstream/xmlstream.py | 22 |
16 files changed, 96 insertions, 112 deletions
diff --git a/slixmpp/features/feature_mechanisms/mechanisms.py b/slixmpp/features/feature_mechanisms/mechanisms.py index 30449de0..26af1947 100644 --- a/slixmpp/features/feature_mechanisms/mechanisms.py +++ b/slixmpp/features/feature_mechanisms/mechanisms.py @@ -97,7 +97,10 @@ class FeatureMechanisms(BasePlugin): jid = self.xmpp.requested_jid.bare result[value] = creds.get('email', jid) elif value == 'channel_binding': - result[value] = self.xmpp.socket.get_channel_binding() + if isinstance(self.xmpp.socket, (ssl.SSLSocket, ssl.SSLObject)): + result[value] = self.xmpp.socket.get_channel_binding() + else: + result[value] = None elif value == 'host': result[value] = creds.get('host', self.xmpp.requested_jid.domain) elif value == 'realm': diff --git a/slixmpp/jid.py b/slixmpp/jid.py index 9cb815db..dd6c1047 100644 --- a/slixmpp/jid.py +++ b/slixmpp/jid.py @@ -347,30 +347,10 @@ class JID: return self._node @property - def user(self): - return self._node - - @property - def local(self): - return self._node - - @property - def username(self): - return self._node - - @property def domain(self): return self._domain @property - def server(self): - return self._domain - - @property - def host(self): - return self._domain - - @property def resource(self): return self._resource @@ -382,45 +362,16 @@ class JID: def full(self): return self._full - @property - def jid(self): - return self._full - @node.setter def node(self, value): self._node = _validate_node(value) self._update_bare_full() - @user.setter - def user(self, value): - self._node = _validate_node(value) - self._update_bare_full() - - @local.setter - def local(self, value): - self._node = _validate_node(value) - self._update_bare_full() - - @username.setter - def username(self, value): - self._node = _validate_node(value) - self._update_bare_full() - @domain.setter def domain(self, value): self._domain = _validate_domain(value) self._update_bare_full() - @server.setter - def server(self, value): - self._domain = _validate_domain(value) - self._update_bare_full() - - @host.setter - def host(self, value): - self._domain = _validate_domain(value) - self._update_bare_full() - @bare.setter def bare(self, value): node, domain, resource = _parse_jid(value) @@ -439,10 +390,14 @@ class JID: self._node, self._domain, self._resource = _parse_jid(value) self._update_bare_full() - @jid.setter - def jid(self, value): - self._node, self._domain, self._resource = _parse_jid(value) - self._update_bare_full() + user = node + local = node + username = node + + server = domain + host = domain + + jid = full def __str__(self): """Use the full JID as the string value.""" diff --git a/slixmpp/plugins/xep_0030/disco.py b/slixmpp/plugins/xep_0030/disco.py index ea9a33f4..59b1e0cc 100644 --- a/slixmpp/plugins/xep_0030/disco.py +++ b/slixmpp/plugins/xep_0030/disco.py @@ -299,23 +299,27 @@ class XEP_0030(BasePlugin): return self.api['has_identity'](jid, node, ifrom, data) async def get_info_from_domain(self, domain=None, timeout=None, - cached=True, callback=None, **kwargs): + cached=True, callback=None): if domain is None: domain = self.xmpp.boundjid.domain if not cached or domain not in self.domain_infos: infos = [self.get_info( - domain, timeout=timeout, **kwargs)] + domain, timeout=timeout)] iq_items = await self.get_items( - domain, timeout=timeout, **kwargs) + domain, timeout=timeout) items = iq_items['disco_items']['items'] infos += [ - self.get_info(item[0], timeout=timeout, **kwargs) + self.get_info(item[0], timeout=timeout) for item in items] - info_futures, _ = await asyncio.wait(infos, timeout=timeout) + info_futures, _ = await asyncio.wait( + infos, + timeout=timeout, + loop=self.xmpp.loop + ) self.domain_infos[domain] = [ - future.result() for future in info_futures] + future.result() for future in info_futures if not future.exception()] results = self.domain_infos[domain] diff --git a/slixmpp/plugins/xep_0077/register.py b/slixmpp/plugins/xep_0077/register.py index 8c0c6f09..a7c6780f 100644 --- a/slixmpp/plugins/xep_0077/register.py +++ b/slixmpp/plugins/xep_0077/register.py @@ -59,7 +59,7 @@ class XEP_0077(BasePlugin): def _force_stream_feature(self, stanza): if isinstance(stanza, StreamFeatures): - if self.xmpp.use_tls or self.xmpp.use_ssl: + if not self.xmpp.disable_starttls: if 'starttls' not in self.xmpp.features: return stanza elif not isinstance(self.xmpp.socket, ssl.SSLSocket): diff --git a/slixmpp/plugins/xep_0153/vcard_avatar.py b/slixmpp/plugins/xep_0153/vcard_avatar.py index 6430e8d6..cf10283a 100644 --- a/slixmpp/plugins/xep_0153/vcard_avatar.py +++ b/slixmpp/plugins/xep_0153/vcard_avatar.py @@ -167,10 +167,7 @@ class XEP_0153(BasePlugin): data = pres['vcard_temp_update']['photo'] if data is None: return - elif data == '' or data != self.api['get_hash'](pres['from']): - ifrom = pres['to'] if self.xmpp.is_component else None - self.api['reset_hash'](pres['from'], ifrom=ifrom) - self.xmpp.event('vcard_avatar_update', pres) + self.xmpp.event('vcard_avatar_update', pres) # ================================================================= diff --git a/slixmpp/plugins/xep_0163.py b/slixmpp/plugins/xep_0163.py index 047ca5d3..4c302efa 100644 --- a/slixmpp/plugins/xep_0163.py +++ b/slixmpp/plugins/xep_0163.py @@ -62,7 +62,10 @@ class XEP_0163(BasePlugin): for ns in namespace: self.xmpp['xep_0030'].add_feature('%s+notify' % ns, jid=jid) - asyncio.ensure_future(self.xmpp['xep_0115'].update_caps(jid)) + asyncio.ensure_future( + self.xmpp['xep_0115'].update_caps(jid), + loop=self.xmpp.loop, + ) def remove_interest(self, namespace, jid=None): """ @@ -81,7 +84,10 @@ class XEP_0163(BasePlugin): for ns in namespace: self.xmpp['xep_0030'].del_feature(jid=jid, feature='%s+notify' % namespace) - asyncio.ensure_future(self.xmpp['xep_0115'].update_caps(jid)) + asyncio.ensure_future( + self.xmpp['xep_0115'].update_caps(jid), + loop=self.xmpp.loop, + ) def publish(self, stanza, node=None, id=None, options=None, ifrom=None, timeout_callback=None, callback=None, timeout=None): diff --git a/slixmpp/plugins/xep_0199/ping.py b/slixmpp/plugins/xep_0199/ping.py index 1153389b..f1070305 100644 --- a/slixmpp/plugins/xep_0199/ping.py +++ b/slixmpp/plugins/xep_0199/ping.py @@ -95,7 +95,10 @@ class XEP_0199(BasePlugin): self.timeout = timeout self.keepalive = True - handler = lambda event=None: asyncio.ensure_future(self._keepalive(event)) + handler = lambda event=None: asyncio.ensure_future( + self._keepalive(event), + loop=self.xmpp.loop, + ) self.xmpp.schedule('Ping keepalive', self.interval, handler, diff --git a/slixmpp/plugins/xep_0223.py b/slixmpp/plugins/xep_0223.py index 65d591f6..18875eee 100644 --- a/slixmpp/plugins/xep_0223.py +++ b/slixmpp/plugins/xep_0223.py @@ -26,7 +26,7 @@ class XEP_0223(BasePlugin): dependencies = {'xep_0163', 'xep_0060', 'xep_0004'} profile = {'pubsub#persist_items': True, - 'pubsub#send_last_published_item': 'never'} + 'pubsub#access_model': 'whitelist'} def configure(self, node, ifrom=None, callback=None, timeout=None): """ diff --git a/slixmpp/plugins/xep_0363/http_upload.py b/slixmpp/plugins/xep_0363/http_upload.py index 65894975..266fc656 100644 --- a/slixmpp/plugins/xep_0363/http_upload.py +++ b/slixmpp/plugins/xep_0363/http_upload.py @@ -6,7 +6,6 @@ See the file LICENSE for copying permission. """ -import asyncio import logging import os.path @@ -31,6 +30,10 @@ class UploadServiceNotFound(FileUploadError): class FileTooBig(FileUploadError): pass +class HTTPError(FileUploadError): + def __str__(self): + return 'Could not upload file: %d (%s)' % (self.args[0], self.args[1]) + class XEP_0363(BasePlugin): ''' This plugin only supports Python 3.5+ ''' @@ -68,12 +71,18 @@ class XEP_0363(BasePlugin): def _handle_request(self, iq): self.xmpp.event('http_upload_request', iq) - async def find_upload_service(self, timeout=None): - results = await self.xmpp['xep_0030'].get_info_from_domain() + async def find_upload_service(self, domain=None, timeout=None): + results = await self.xmpp['xep_0030'].get_info_from_domain( + domain=domain, timeout=timeout) + candidates = [] for info in results: for identity in info['disco_info']['identities']: if identity[0] == 'store' and identity[1] == 'file': + candidates.append(info) + for info in candidates: + for feature in info['disco_info']['features']: + if feature == Request.namespace: return info def request_slot(self, jid, filename, size, content_type=None, ifrom=None, @@ -90,11 +99,12 @@ class XEP_0363(BasePlugin): timeout_callback=timeout_callback) async def upload_file(self, filename, size=None, content_type=None, *, - input_file=None, ifrom=None, timeout=None, + input_file=None, ifrom=None, domain=None, timeout=None, callback=None, timeout_callback=None): ''' Helper function which does all of the uploading process. ''' if self.upload_service is None: - info_iq = await self.find_upload_service(timeout=timeout) + info_iq = await self.find_upload_service( + domain=domain, timeout=timeout) if info_iq is None: raise UploadServiceNotFound() self.upload_service = info_iq['from'] @@ -125,7 +135,8 @@ class XEP_0363(BasePlugin): basename = os.path.basename(filename) slot_iq = await self.request_slot(self.upload_service, basename, size, - content_type, ifrom, timeout) + content_type, ifrom, timeout, + timeout_callback=timeout_callback) slot = slot_iq['http_upload_slot'] headers = { @@ -141,6 +152,8 @@ class XEP_0363(BasePlugin): data=input_file, headers=headers, timeout=timeout) + if response.status >= 400: + raise HTTPError(response.status, await response.text()) log.info('Response code: %d (%s)', response.status, await response.text()) response.close() return slot['get']['url'] diff --git a/slixmpp/stanza/iq.py b/slixmpp/stanza/iq.py index 385bbbd9..a3f16e2f 100644 --- a/slixmpp/stanza/iq.py +++ b/slixmpp/stanza/iq.py @@ -187,6 +187,10 @@ class Iq(RootStanza): future = asyncio.Future() + # Prevents handlers from existing forever. + if timeout is None: + timeout = 120 + def callback_success(result): type_ = result['type'] if type_ == 'result': diff --git a/slixmpp/test/slixtest.py b/slixmpp/test/slixtest.py index b307b5c6..ff185368 100644 --- a/slixmpp/test/slixtest.py +++ b/slixmpp/test/slixtest.py @@ -222,7 +222,7 @@ class SlixTest(unittest.TestCase): if Matcher is None: raise ValueError("Unknown matching method.") test = Matcher(criteria) - self.failUnless(test.match(stanza), + self.assertTrue(test.match(stanza), "Stanza did not match using %s method:\n" % method + \ "Criteria:\n%s\n" % str(criteria) + \ "Stanza:\n%s" % str(stanza)) @@ -280,7 +280,7 @@ class SlixTest(unittest.TestCase): debug += "Generated stanza:\n%s\n" % highlight(tostring(stanza2.xml)) result = self.compare(xml, stanza.xml, stanza2.xml) - self.failUnless(result, debug) + self.assertTrue(result, debug) # ------------------------------------------------------------------ # Methods for simulating stanza streams. @@ -487,7 +487,7 @@ class SlixTest(unittest.TestCase): recv_xml.clear() recv_xml.attrib = attrib - self.failUnless( + self.assertTrue( self.compare(xml, recv_xml), "Stream headers do not match:\nDesired:\n%s\nReceived:\n%s" % ( '%s %s' % (xml.tag, xml.attrib), @@ -543,7 +543,7 @@ class SlixTest(unittest.TestCase): xml = self.parse_xml(header2) sent_xml = self.parse_xml(sent_header2) - self.failUnless( + self.assertTrue( self.compare(xml, sent_xml), "Stream headers do not match:\nDesired:\n%s\nSent:\n%s" % ( header, sent_header)) @@ -557,12 +557,12 @@ class SlixTest(unittest.TestCase): if sent_data is None: self.fail("No stanza was sent.") if method == 'exact': - self.failUnless(self.compare(xml, sent_xml), + self.assertTrue(self.compare(xml, sent_xml), "Features do not match.\nDesired:\n%s\nReceived:\n%s" % ( highlight(tostring(xml)), highlight(tostring(sent_xml)))) elif method == 'mask': matcher = MatchXMLMask(xml) - self.failUnless(matcher.match(sent_xml), + self.assertTrue(matcher.match(sent_xml), "Stanza did not match using %s method:\n" % method + \ "Criteria:\n%s\n" % highlight(tostring(xml)) + \ "Stanza:\n%s" % highlight(tostring(sent_xml))) diff --git a/slixmpp/util/sasl/mechanisms.py b/slixmpp/util/sasl/mechanisms.py index 36b2795c..874787a9 100644 --- a/slixmpp/util/sasl/mechanisms.py +++ b/slixmpp/util/sasl/mechanisms.py @@ -516,13 +516,13 @@ else: def setup(self, name): authzid = self.credentials['authzid'] if not authzid: - authzid = 'xmpp@%s' % self.credentials['service-name'] + authzid = 'xmpp@' + self.credentials['service-name'].decode() _, self.gss = kerberos.authGSSClientInit(authzid) self.step = 0 def process(self, challenge=b''): - b64_challenge = b64encode(challenge) + b64_challenge = b64encode(challenge).decode('ascii') try: if self.step == 0: result = kerberos.authGSSClientStep(self.gss, b64_challenge) @@ -536,7 +536,7 @@ else: kerberos.authGSSClientUnwrap(self.gss, b64_challenge) resp = kerberos.authGSSClientResponse(self.gss) - kerberos.authGSSClientWrap(self.gss, resp, username) + kerberos.authGSSClientWrap(self.gss, resp, username.decode()) resp = kerberos.authGSSClientResponse(self.gss) except kerberos.GSSError as e: diff --git a/slixmpp/version.py b/slixmpp/version.py index a3d98366..4d767f1c 100644 --- a/slixmpp/version.py +++ b/slixmpp/version.py @@ -9,5 +9,5 @@ # We don't want to have to import the entire library # just to get the version info for setup.py -__version__ = '1.4.0' -__version_info__ = (1, 4, 0) +__version__ = '1.4.1' +__version_info__ = (1, 4, 1) diff --git a/slixmpp/xmlstream/stanzabase.py b/slixmpp/xmlstream/stanzabase.py index 605dbb61..1c000b69 100644 --- a/slixmpp/xmlstream/stanzabase.py +++ b/slixmpp/xmlstream/stanzabase.py @@ -177,8 +177,9 @@ def fix_ns(xpath, split=False, propagate_ns=True, default_ns=''): if '}' in ns_block: # Apply the found namespace to following elements # that do not have namespaces. - namespace = ns_block.split('}')[0] - elements = ns_block.split('}')[1].split('/') + ns_block_split = ns_block.split('}') + namespace = ns_block_split[0] + elements = ns_block_split[1].split('/') else: # Apply the stanza's namespace to the following # elements since no namespace was provided. @@ -1291,15 +1292,6 @@ class ElementBase(object): def __bool__(self): """Stanza objects should be treated as True in boolean contexts. - - Python 3.x version. - """ - return True - - def __nonzero__(self): - """Stanza objects should be treated as True in boolean contexts. - - Python 2.x version. """ return True diff --git a/slixmpp/xmlstream/tostring.py b/slixmpp/xmlstream/tostring.py index 6726bf1e..d6cc85dd 100644 --- a/slixmpp/xmlstream/tostring.py +++ b/slixmpp/xmlstream/tostring.py @@ -45,11 +45,12 @@ def tostring(xml=None, xmlns='', stream=None, outbuffer='', output = [outbuffer] # Extract the element's tag name. - tag_name = xml.tag.split('}', 1)[-1] + tag_split = xml.tag.split('}', 1) + tag_name = tag_split[-1] # Extract the element's namespace if it is defined. if '}' in xml.tag: - tag_xmlns = xml.tag.split('}', 1)[0][1:] + tag_xmlns = tag_split[0][1:] else: tag_xmlns = '' @@ -82,8 +83,9 @@ def tostring(xml=None, xmlns='', stream=None, outbuffer='', if '}' not in attrib: output.append(' %s="%s"' % (attrib, value)) else: - attrib_ns = attrib.split('}')[0][1:] - attrib = attrib.split('}')[1] + attrib_split = attrib.split('}') + attrib_ns = attrib_split[0][1:] + attrib = attrib_split[1] if attrib_ns == XML_NS: output.append(' xml:%s="%s"' % (attrib, value)) elif stream and attrib_ns in stream.namespace_map: @@ -144,10 +146,7 @@ def escape(text, use_cdata=False): '"': '"'} if not use_cdata: - text = list(text) - for i, c in enumerate(text): - text[i] = escapes.get(c, c) - return ''.join(text) + return ''.join(escapes.get(c, c) for c in text) else: escape_needed = False for c in text: diff --git a/slixmpp/xmlstream/xmlstream.py b/slixmpp/xmlstream/xmlstream.py index 0367db02..60557fff 100644 --- a/slixmpp/xmlstream/xmlstream.py +++ b/slixmpp/xmlstream/xmlstream.py @@ -285,7 +285,10 @@ class XMLStream(asyncio.BaseProtocol): self.disable_starttls = disable_starttls self.event("connecting") - self._current_connection_attempt = asyncio.ensure_future(self._connect_routine()) + self._current_connection_attempt = asyncio.ensure_future( + self._connect_routine(), + loop=self.loop, + ) async def _connect_routine(self): self.event_when_connected = "connected" @@ -306,7 +309,7 @@ class XMLStream(asyncio.BaseProtocol): else: ssl_context = None - await asyncio.sleep(self.connect_loop_wait) + await asyncio.sleep(self.connect_loop_wait, loop=self.loop) try: await self.loop.create_connection(lambda: self, self.address[0], @@ -321,7 +324,10 @@ class XMLStream(asyncio.BaseProtocol): log.debug('Connection failed: %s', e) self.event("connection_failed", e) self.connect_loop_wait = self.connect_loop_wait * 2 + 1 - self._current_connection_attempt = asyncio.ensure_future(self._connect_routine()) + self._current_connection_attempt = asyncio.ensure_future( + self._connect_routine(), + loop=self.loop, + ) def process(self, *, forever=True, timeout=None): """Process all the available XMPP events (receiving or sending data on the @@ -336,10 +342,10 @@ class XMLStream(asyncio.BaseProtocol): else: self.loop.run_until_complete(self.disconnected) else: - tasks = [asyncio.sleep(timeout)] + tasks = [asyncio.sleep(timeout, loop=self.loop)] if not forever: tasks.append(self.disconnected) - self.loop.run_until_complete(asyncio.wait(tasks)) + self.loop.run_until_complete(asyncio.wait(tasks, loop=self.loop)) def init_parser(self): """init the XML parser. The parser must always be reset for each new @@ -781,7 +787,10 @@ class XMLStream(asyncio.BaseProtocol): old_exception(e) else: self.exception(e) - asyncio.ensure_future(handler_callback_routine(handler_callback)) + asyncio.ensure_future( + handler_callback_routine(handler_callback), + loop=self.loop, + ) else: try: handler_callback(data) @@ -995,4 +1004,3 @@ class XMLStream(asyncio.BaseProtocol): :param exception: An unhandled exception object. """ pass - |