Compare commits

..

1 Commits

Author SHA1 Message Date
Emmanuel Gil Peyrot
f4683546d9 Manual cleanup of the remaining set([…]) and set((…)). 2016-10-22 13:35:54 +01:00
35 changed files with 63 additions and 679 deletions

View File

@@ -1,8 +0,0 @@
test:
tags:
- docker
image: ubuntu:latest
script:
- apt update
- apt install -y python3 cython3
- ./run_tests.py

View File

@@ -1,7 +1,7 @@
.. _mucbot: .. _mucbot:
========================= =========================
Multi-User Chat (MUC) Bot Mulit-User Chat (MUC) Bot
========================= =========================
.. note:: .. note::

View File

@@ -13,7 +13,7 @@
from slixmpp import ClientXMPP from slixmpp import ClientXMPP
from argparse import ArgumentParser from optparse import OptionParser
import logging import logging
import getpass import getpass
@@ -58,40 +58,40 @@ if __name__ == '__main__':
# ./http_over_xmpp.py -J <jid> -P <pwd> -i <ip> -p <port> [-v] # ./http_over_xmpp.py -J <jid> -P <pwd> -i <ip> -p <port> [-v]
# #
parser = ArgumentParser() parser = OptionParser()
# Output verbosity options. # Output verbosity options.
parser.add_argument( parser.add_option(
'-v', '--verbose', help='set logging to DEBUG', action='store_const', '-v', '--verbose', help='set logging to DEBUG', action='store_const',
dest='loglevel', const=logging.DEBUG, default=logging.ERROR dest='loglevel', const=logging.DEBUG, default=logging.ERROR
) )
# JID and password options. # JID and password options.
parser.add_argument('-J', '--jid', dest='jid', help='JID') parser.add_option('-J', '--jid', dest='jid', help='JID')
parser.add_argument('-P', '--password', dest='password', help='Password') parser.add_option('-P', '--password', dest='password', help='Password')
# XMPP server ip and port options. # XMPP server ip and port options.
parser.add_argument( parser.add_option(
'-i', '--ipaddr', dest='ipaddr', '-i', '--ipaddr', dest='ipaddr',
help='IP Address of the XMPP server', default=None help='IP Address of the XMPP server', default=None
) )
parser.add_argument( parser.add_option(
'-p', '--port', dest='port', '-p', '--port', dest='port',
help='Port of the XMPP server', default=None help='Port of the XMPP server', default=None
) )
args = parser.parse_args() opts, args = parser.parse_args()
# Setup logging. # Setup logging.
logging.basicConfig(level=args.loglevel, logging.basicConfig(level=opts.loglevel,
format='%(levelname)-8s %(message)s') format='%(levelname)-8s %(message)s')
if args.jid is None: if opts.jid is None:
args.jid = input('Username: ') opts.jid = input('Username: ')
if args.password is None: if opts.password is None:
args.password = getpass.getpass('Password: ') opts.password = getpass.getpass('Password: ')
xmpp = HTTPOverXMPPClient(args.jid, args.password) xmpp = HTTPOverXMPPClient(opts.jid, opts.password)
xmpp.connect() xmpp.connect()
xmpp.process() xmpp.process()

View File

@@ -9,7 +9,7 @@
import os import os
from pathlib import Path from pathlib import Path
from subprocess import call, DEVNULL, check_output, CalledProcessError from subprocess import call, DEVNULL
from tempfile import TemporaryFile from tempfile import TemporaryFile
try: try:
from setuptools import setup from setuptools import setup
@@ -35,31 +35,18 @@ CLASSIFIERS = [
packages = [str(mod.parent) for mod in Path('slixmpp').rglob('__init__.py')] packages = [str(mod.parent) for mod in Path('slixmpp').rglob('__init__.py')]
def check_include(library_name, header): def check_include(header):
command = [os.environ.get('PKG_CONFIG', 'pkg-config'), '--cflags', library_name] command = [os.environ.get('CC', 'cc'), '-E', '-']
try:
cflags = check_output(command).decode('utf-8').split()
except FileNotFoundError:
print('pkg-config not found.')
return False
except CalledProcessError:
# pkg-config already prints the missing libraries on stderr.
return False
command = [os.environ.get('CC', 'cc')] + cflags + ['-E', '-']
with TemporaryFile('w+') as c_file: with TemporaryFile('w+') as c_file:
c_file.write('#include <%s>' % header) c_file.write('#include <%s>' % header)
c_file.seek(0) c_file.seek(0)
try: try:
return call(command, stdin=c_file, stdout=DEVNULL, stderr=DEVNULL) == 0 return call(command, stdin=c_file, stdout=DEVNULL, stderr=DEVNULL) == 0
except FileNotFoundError: except FileNotFoundError:
print('%s headers not found.' % library_name)
return False return False
HAS_PYTHON_HEADERS = check_include('python3', 'Python.h')
HAS_STRINGPREP_HEADERS = check_include('libidn', 'stringprep.h')
ext_modules = None ext_modules = None
if HAS_PYTHON_HEADERS and HAS_STRINGPREP_HEADERS: if check_include('stringprep.h'):
try: try:
from Cython.Build import cythonize from Cython.Build import cythonize
except ImportError: except ImportError:
@@ -67,7 +54,7 @@ if HAS_PYTHON_HEADERS and HAS_STRINGPREP_HEADERS:
else: else:
ext_modules = cythonize('slixmpp/stringprep.pyx') ext_modules = cythonize('slixmpp/stringprep.pyx')
else: else:
print('Falling back to the slow stringprep module.') print('libidn-dev not found, falling back to the slow stringprep module.')
setup( setup(
name="slixmpp", name="slixmpp",

View File

@@ -15,7 +15,6 @@
import asyncio import asyncio
import logging import logging
from slixmpp.jid import JID
from slixmpp.stanza import StreamFeatures from slixmpp.stanza import StreamFeatures
from slixmpp.basexmpp import BaseXMPP from slixmpp.basexmpp import BaseXMPP
from slixmpp.exceptions import XMPPError from slixmpp.exceptions import XMPPError
@@ -109,21 +108,10 @@ class ClientXMPP(BaseXMPP):
CoroutineCallback('Stream Features', CoroutineCallback('Stream Features',
MatchXPath('{%s}features' % self.stream_ns), MatchXPath('{%s}features' % self.stream_ns),
self._handle_stream_features)) self._handle_stream_features))
def roster_push_filter(iq):
from_ = iq['from']
if from_ and from_ != JID('') and from_ != self.boundjid.bare:
reply = iq.reply()
reply['type'] = 'error'
reply['error']['type'] = 'cancel'
reply['error']['code'] = 503
reply['error']['condition'] = 'service-unavailable'
reply.send()
return
self.event('roster_update', iq)
self.register_handler( self.register_handler(
Callback('Roster Update', Callback('Roster Update',
StanzaPath('iq@type=set/roster'), StanzaPath('iq@type=set/roster'),
roster_push_filter)) lambda iq: self.event('roster_update', iq)))
# Setup default stream features # Setup default stream features
self.register_plugin('feature_starttls') self.register_plugin('feature_starttls')

View File

@@ -1,47 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin, BasePlugin
from slixmpp.plugins.google.gmail import Gmail
from slixmpp.plugins.google.auth import GoogleAuth
from slixmpp.plugins.google.settings import GoogleSettings
from slixmpp.plugins.google.nosave import GoogleNoSave
class Google(BasePlugin):
"""
Google: Custom GTalk Features
Also see: <https://developers.google.com/talk/jep_extensions/extensions>
"""
name = 'google'
description = 'Google: Custom GTalk Features'
dependencies = set([
'gmail',
'google_settings',
'google_nosave',
'google_auth'
])
def __getitem__(self, attr):
if attr in ('settings', 'nosave', 'auth'):
return self.xmpp['google_%s' % attr]
elif attr == 'gmail':
return self.xmpp['gmail']
else:
raise KeyError(attr)
register_plugin(Gmail)
register_plugin(GoogleAuth)
register_plugin(GoogleSettings)
register_plugin(GoogleNoSave)
register_plugin(Google)

View File

@@ -1,10 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.google.auth import stanza
from slixmpp.plugins.google.auth.auth import GoogleAuth

View File

@@ -1,47 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.xmlstream import register_stanza_plugin
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.google.auth import stanza
class GoogleAuth(BasePlugin):
"""
Google: Auth Extensions (JID Domain Discovery, OAuth2)
Also see:
<https://developers.google.com/talk/jep_extensions/jid_domain_change>
<https://developers.google.com/talk/jep_extensions/oauth>
"""
name = 'google_auth'
description = 'Google: Auth Extensions (JID Domain Discovery, OAuth2)'
dependencies = set(['feature_mechanisms'])
stanza = stanza
def plugin_init(self):
self.xmpp.namespace_map['http://www.google.com/talk/protocol/auth'] = 'ga'
register_stanza_plugin(self.xmpp['feature_mechanisms'].stanza.Auth,
stanza.GoogleAuth)
self.xmpp.add_filter('out', self._auth)
def plugin_end(self):
self.xmpp.del_filter('out', self._auth)
def _auth(self, stanza):
if isinstance(stanza, self.xmpp['feature_mechanisms'].stanza.Auth):
stanza.stream = self.xmpp
stanza['google']['client_uses_full_bind_result'] = True
if stanza['mechanism'] == 'X-OAUTH2':
stanza['google']['service'] = 'oauth2'
print(stanza)
return stanza

View File

@@ -1,10 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.google.gmail import stanza
from slixmpp.plugins.google.gmail.notifications import Gmail

View File

@@ -1,101 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.xmlstream import ElementBase, register_stanza_plugin
class GmailQuery(ElementBase):
namespace = 'google:mail:notify'
name = 'query'
plugin_attrib = 'gmail'
interfaces = set(['newer_than_time', 'newer_than_tid', 'search'])
def get_search(self):
return self._get_attr('q', '')
def set_search(self, search):
self._set_attr('q', search)
def del_search(self):
self._del_attr('q')
def get_newer_than_time(self):
return self._get_attr('newer-than-time', '')
def set_newer_than_time(self, value):
self._set_attr('newer-than-time', value)
def del_newer_than_time(self):
self._del_attr('newer-than-time')
def get_newer_than_tid(self):
return self._get_attr('newer-than-tid', '')
def set_newer_than_tid(self, value):
self._set_attr('newer-than-tid', value)
def del_newer_than_tid(self):
self._del_attr('newer-than-tid')
class MailBox(ElementBase):
namespace = 'google:mail:notify'
name = 'mailbox'
plugin_attrib = 'gmail_messages'
interfaces = set(['result_time', 'url', 'matched', 'estimate'])
def get_matched(self):
return self._get_attr('total-matched', '')
def get_estimate(self):
return self._get_attr('total-estimate', '') == '1'
def get_result_time(self):
return self._get_attr('result-time', '')
class MailThread(ElementBase):
namespace = 'google:mail:notify'
name = 'mail-thread-info'
plugin_attrib = 'thread'
plugin_multi_attrib = 'threads'
interfaces = set(['tid', 'participation', 'messages', 'date',
'senders', 'url', 'labels', 'subject', 'snippet'])
sub_interfaces = set(['labels', 'subject', 'snippet'])
def get_senders(self):
result = []
senders = self.xml.findall('{%s}senders/{%s}sender' % (
self.namespace, self.namespace))
for sender in senders:
result.append(MailSender(xml=sender))
return result
class MailSender(ElementBase):
namespace = 'google:mail:notify'
name = 'sender'
plugin_attrib = name
interfaces = set(['address', 'name', 'originator', 'unread'])
def get_originator(self):
return self.xml.attrib.get('originator', '0') == '1'
def get_unread(self):
return self.xml.attrib.get('unread', '0') == '1'
class NewMail(ElementBase):
namespace = 'google:mail:notify'
name = 'new-mail'
plugin_attrib = 'gmail_notification'
register_stanza_plugin(MailBox, MailThread, iterable=True)

View File

@@ -1,10 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.google.nosave import stanza
from slixmpp.plugins.google.nosave.nosave import GoogleNoSave

View File

@@ -1,78 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.stanza import Iq, Message
from slixmpp.xmlstream.handler import Callback
from slixmpp.xmlstream.matcher import StanzaPath
from slixmpp.xmlstream import register_stanza_plugin
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.google.nosave import stanza
class GoogleNoSave(BasePlugin):
"""
Google: Off the Record Chats
NOTE: This is NOT an encryption method.
Also see <https://developers.google.com/talk/jep_extensions/otr>.
"""
name = 'google_nosave'
description = 'Google: Off the Record Chats'
dependencies = set(['google_settings'])
stanza = stanza
def plugin_init(self):
register_stanza_plugin(Message, stanza.NoSave)
register_stanza_plugin(Iq, stanza.NoSaveQuery)
self.xmpp.register_handler(
Callback('Google Nosave',
StanzaPath('iq@type=set/google_nosave'),
self._handle_nosave_change))
def plugin_end(self):
self.xmpp.remove_handler('Google Nosave')
def enable(self, jid=None, timeout=None, callback=None):
if jid is None:
self.xmpp['google_settings'].update({'archiving_enabled': False},
timeout=timeout, callback=callback)
else:
iq = self.xmpp.Iq()
iq['type'] = 'set'
iq['google_nosave']['item']['jid'] = jid
iq['google_nosave']['item']['value'] = True
return iq.send(timeout=timeout, callback=callback)
def disable(self, jid=None, timeout=None, callback=None):
if jid is None:
self.xmpp['google_settings'].update({'archiving_enabled': True},
timeout=timeout, callback=callback)
else:
iq = self.xmpp.Iq()
iq['type'] = 'set'
iq['google_nosave']['item']['jid'] = jid
iq['google_nosave']['item']['value'] = False
return iq.send(timeout=timeout, callback=callback)
def get(self, timeout=None, callback=None):
iq = self.xmpp.Iq()
iq['type'] = 'get'
iq.enable('google_nosave')
return iq.send(timeout=timeout, callback=callback)
def _handle_nosave_change(self, iq):
reply = self.xmpp.Iq()
reply['type'] = 'result'
reply['id'] = iq['id']
reply['to'] = iq['from']
reply.send()
self.xmpp.event('google_nosave_change', iq)

View File

@@ -1,10 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.google.settings import stanza
from slixmpp.plugins.google.settings.settings import GoogleSettings

View File

@@ -1,110 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
This file is part of slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.xmlstream import ET, ElementBase
class UserSettings(ElementBase):
name = 'usersetting'
namespace = 'google:setting'
plugin_attrib = 'google_settings'
interfaces = set(['auto_accept_suggestions',
'mail_notifications',
'archiving_enabled',
'gmail',
'email_verified',
'domain_privacy_notice',
'display_name'])
def _get_setting(self, setting):
xml = self.xml.find('{%s}%s' % (self.namespace, setting))
if xml is not None:
return xml.attrib.get('value', '') == 'true'
return False
def _set_setting(self, setting, value):
self._del_setting(setting)
if value in (True, False):
xml = ET.Element('{%s}%s' % (self.namespace, setting))
xml.attrib['value'] = 'true' if value else 'false'
self.xml.append(xml)
def _del_setting(self, setting):
xml = self.xml.find('{%s}%s' % (self.namespace, setting))
if xml is not None:
self.xml.remove(xml)
def get_display_name(self):
xml = self.xml.find('{%s}%s' % (self.namespace, 'displayname'))
if xml is not None:
return xml.attrib.get('value', '')
return ''
def set_display_name(self, value):
self._del_setting(setting)
if value:
xml = ET.Element('{%s}%s' % (self.namespace, 'displayname'))
xml.attrib['value'] = value
self.xml.append(xml)
def del_display_name(self):
self._del_setting('displayname')
def get_auto_accept_suggestions(self):
return self._get_setting('autoacceptsuggestions')
def get_mail_notifications(self):
return self._get_setting('mailnotifications')
def get_archiving_enabled(self):
return self._get_setting('archivingenabled')
def get_gmail(self):
return self._get_setting('gmail')
def get_email_verified(self):
return self._get_setting('emailverified')
def get_domain_privacy_notice(self):
return self._get_setting('domainprivacynotice')
def set_auto_accept_suggestions(self, value):
self._set_setting('autoacceptsuggestions', value)
def set_mail_notifications(self, value):
self._set_setting('mailnotifications', value)
def set_archiving_enabled(self, value):
self._set_setting('archivingenabled', value)
def set_gmail(self, value):
self._set_setting('gmail', value)
def set_email_verified(self, value):
self._set_setting('emailverified', value)
def set_domain_privacy_notice(self, value):
self._set_setting('domainprivacynotice', value)
def del_auto_accept_suggestions(self):
self._del_setting('autoacceptsuggestions')
def del_mail_notifications(self):
self._del_setting('mailnotifications')
def del_archiving_enabled(self):
self._del_setting('archivingenabled')
def del_gmail(self):
self._del_setting('gmail')
def del_email_verified(self):
self._del_setting('emailverified')
def del_domain_privacy_notice(self):
self._del_setting('domainprivacynotice')

View File

@@ -121,7 +121,7 @@ class XEP_0009(BasePlugin):
def _recipient_unvailable(self, iq): def _recipient_unvailable(self, iq):
payload = iq.get_payload() payload = iq.get_payload()
iq = iq.reply() iq = iq.reply()
iq.error().set_payload(payload) error().set_payload(payload)
iq['error']['code'] = '404' iq['error']['code'] = '404'
iq['error']['type'] = 'wait' iq['error']['type'] = 'wait'
iq['error']['condition'] = 'recipient-unavailable' iq['error']['condition'] = 'recipient-unavailable'

View File

@@ -55,7 +55,6 @@ class XEP_0065(BasePlugin):
"""Returns the socket associated to the SID.""" """Returns the socket associated to the SID."""
return self._sessions.get(sid, None) return self._sessions.get(sid, None)
@asyncio.coroutine
def handshake(self, to, ifrom=None, sid=None, timeout=None): def handshake(self, to, ifrom=None, sid=None, timeout=None):
""" Starts the handshake to establish the socks5 bytestreams """ Starts the handshake to establish the socks5 bytestreams
connection. connection.
@@ -105,7 +104,6 @@ class XEP_0065(BasePlugin):
iq['socks'].add_streamhost(proxy, host, port) iq['socks'].add_streamhost(proxy, host, port)
return iq.send(timeout=timeout, callback=callback) return iq.send(timeout=timeout, callback=callback)
@asyncio.coroutine
def discover_proxies(self, jid=None, ifrom=None, timeout=None): def discover_proxies(self, jid=None, ifrom=None, timeout=None):
"""Auto-discover the JIDs of SOCKS5 proxies on an XMPP server.""" """Auto-discover the JIDs of SOCKS5 proxies on an XMPP server."""
if jid is None: if jid is None:

View File

@@ -8,7 +8,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from slixmpp import JID
from slixmpp.xmlstream import ElementBase, register_stanza_plugin from slixmpp.xmlstream import ElementBase, register_stanza_plugin

View File

@@ -36,7 +36,7 @@ class URI(ElementBase):
self.xml.text = value self.xml.text = value
def del_value(self): def del_value(self):
self.xml.text = '' sel.xml.text = ''
register_stanza_plugin(Media, URI, iterable=True) register_stanza_plugin(Media, URI, iterable=True)

View File

@@ -28,7 +28,7 @@ class XEP_0222(BasePlugin):
profile = {'pubsub#persist_items': True, profile = {'pubsub#persist_items': True,
'pubsub#send_last_published_item': 'never'} 'pubsub#send_last_published_item': 'never'}
def configure(self, node, ifrom=None, callback=None, timeout=None): def configure(self, node):
""" """
Update a node's configuration to match the public storage profile. Update a node's configuration to match the public storage profile.
""" """

View File

@@ -28,7 +28,7 @@ class XEP_0223(BasePlugin):
profile = {'pubsub#persist_items': True, profile = {'pubsub#persist_items': True,
'pubsub#send_last_published_item': 'never'} 'pubsub#send_last_published_item': 'never'}
def configure(self, node, ifrom=None, callback=None, timeout=None): def configure(self, node):
""" """
Update a node's configuration to match the public storage profile. Update a node's configuration to match the public storage profile.
""" """

View File

@@ -8,7 +8,6 @@
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
from slixmpp import JID
from slixmpp.util import bytes from slixmpp.util import bytes
from slixmpp.xmlstream import ElementBase, ET, register_stanza_plugin from slixmpp.xmlstream import ElementBase, ET, register_stanza_plugin

View File

@@ -61,12 +61,10 @@ class XEP_0280(BasePlugin):
self.xmpp.plugin['xep_0030'].add_feature('urn:xmpp:carbons:2') self.xmpp.plugin['xep_0030'].add_feature('urn:xmpp:carbons:2')
def _handle_carbon_received(self, msg): def _handle_carbon_received(self, msg):
if msg['from'].bare == self.xmpp.boundjid.bare: self.xmpp.event('carbon_received', msg)
self.xmpp.event('carbon_received', msg)
def _handle_carbon_sent(self, msg): def _handle_carbon_sent(self, msg):
if msg['from'].bare == self.xmpp.boundjid.bare: self.xmpp.event('carbon_sent', msg)
self.xmpp.event('carbon_sent', msg)
def enable(self, ifrom=None, timeout=None, callback=None, def enable(self, ifrom=None, timeout=None, callback=None,
timeout_callback=None): timeout_callback=None):

View File

@@ -135,5 +135,5 @@ class Archived(ElementBase):
def get_by(self): def get_by(self):
return JID(self._get_attr('by')) return JID(self._get_attr('by'))
def set_by(self, value): def set_by(self):
return self._set_attr('by', str(value)) return self._set_attr('by', str(value))

View File

@@ -10,7 +10,7 @@
from slixmpp import Iq, Message from slixmpp import Iq, Message
from slixmpp.xmlstream import register_stanza_plugin, ElementBase, ET, JID from slixmpp.xmlstream import register_stanza_plugin, ElementBase, ET, JID
import re from re import match
class Sensordata(ElementBase): class Sensordata(ElementBase):
""" Placeholder for the namespace, not used as a stanza """ """ Placeholder for the namespace, not used as a stanza """

View File

@@ -11,8 +11,6 @@ import logging
from slixmpp import Message from slixmpp import Message
from slixmpp.plugins import BasePlugin from slixmpp.plugins import BasePlugin
from slixmpp.xmlstream import register_stanza_plugin from slixmpp.xmlstream import register_stanza_plugin
from slixmpp.xmlstream.handler import Callback
from slixmpp.xmlstream.matcher import StanzaPath
from slixmpp.plugins.xep_0333 import stanza, Markable, Received, Displayed, Acknowledged from slixmpp.plugins.xep_0333 import stanza, Markable, Received, Displayed, Acknowledged
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@@ -1,15 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2016 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin
from slixmpp.plugins.xep_0380.stanza import Encryption
from slixmpp.plugins.xep_0380.eme import XEP_0380
register_plugin(XEP_0380)

View File

@@ -1,69 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2016 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
import logging
import slixmpp
from slixmpp.stanza import Message
from slixmpp.xmlstream.handler import Callback
from slixmpp.xmlstream.matcher import StanzaPath
from slixmpp.xmlstream import register_stanza_plugin, ElementBase, ET
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0380 import stanza, Encryption
log = logging.getLogger(__name__)
class XEP_0380(BasePlugin):
"""
XEP-0380: Explicit Message Encryption
"""
name = 'xep_0380'
description = 'XEP-0380: Explicit Message Encryption'
dependencies = {'xep_0030'}
default_config = {
'template': 'This message is encrypted with {name} ({namespace})',
}
mechanisms = {
'jabber:x:encrypted': 'Legacy OpenPGP',
'urn:xmpp:ox:0': 'OpenPGP for XMPP',
'urn:xmpp:otr:0': 'OTR',
'eu.siacs.conversations.axolotl': 'Legacy OMEMO',
'urn:xmpp:omemo:0': 'OMEMO',
}
def plugin_init(self):
self.xmpp.register_handler(
Callback('Explicit Message Encryption',
StanzaPath('message/eme'),
self._handle_eme))
register_stanza_plugin(Message, Encryption)
def plugin_end(self):
self.xmpp.remove_handler('Chat State')
def session_bind(self, jid):
self.xmpp.plugin['xep_0030'].add_feature(Encryption.namespace)
def has_eme(self, msg):
return msg.xml.find('{%s}encryption' % Encryption.namespace) is not None
def replace_body_with_eme(self, msg):
eme = msg['eme']
namespace = eme['namespace']
name = self.mechanisms[namespace] if namespace in self.mechanisms else eme['name']
body = self.config['template'].format(name=name, namespace=namespace)
msg['body'] = body
def _handle_eme(self, msg):
self.xmpp.event('message_encryption', msg)

View File

@@ -1,16 +0,0 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2016 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.xmlstream import ElementBase
class Encryption(ElementBase):
name = 'encryption'
namespace = 'urn:xmpp:eme:0'
plugin_attrib = 'eme'
interfaces = {'namespace', 'name'}

View File

@@ -48,7 +48,7 @@ class Message(RootStanza):
namespace = 'jabber:client' namespace = 'jabber:client'
plugin_attrib = name plugin_attrib = name
interfaces = {'type', 'to', 'from', 'id', 'body', 'subject', 'thread', interfaces = {'type', 'to', 'from', 'id', 'body', 'subject', 'thread',
'parent_thread', 'mucroom', 'mucnick'} 'parent_thread', 'mucroom', 'mucnick'])
sub_interfaces = {'body', 'subject', 'thread'} sub_interfaces = {'body', 'subject', 'thread'}
lang_interfaces = sub_interfaces lang_interfaces = sub_interfaces
types = {'normal', 'chat', 'headline', 'error', 'groupchat'} types = {'normal', 'chat', 'headline', 'error', 'groupchat'}

View File

@@ -75,7 +75,7 @@ def sasl_mech(score):
MECH_SEC_SCORES[mech.name] = mech.score MECH_SEC_SCORES[mech.name] = mech.score
if mech.channel_binding: if mech.channel_binding:
MECHANISMS[mech.name + '-PLUS'] = mech MECHANISMS[mech.name + '-PLUS'] = mech
MECH_SEC_SCORES[mech.name] = mech.score + 10 MECH_SEC_SCORES[name] = mech.score + 10
return mech return mech
return register return register

View File

@@ -146,7 +146,6 @@ def create(nfkc=True, bidi=True, mappings=None,
if bidi: if bidi:
check_bidi(data) check_bidi(data)
if query and unassigned: if query and unassigned:
#check_unassigned(data, unassigned) check_unassigned(data, unassigned)
raise StringPrepError('Query profile with unassigned data is unimplemented.')
return data return data
return profile return profile

View File

@@ -9,5 +9,5 @@
# We don't want to have to import the entire library # We don't want to have to import the entire library
# just to get the version info for setup.py # just to get the version info for setup.py
__version__ = '1.2.4' __version__ = '1.2.1'
__version_info__ = (1, 2, 4) __version_info__ = (1, 2, 1)

View File

@@ -76,7 +76,7 @@ def extract_names(raw_cert):
name_type = name.getName() name_type = name.getName()
if name_type == 'dNSName': if name_type == 'dNSName':
results['DNS'].add(decode_str(name.getComponent())) results['DNS'].add(decode_str(name.getComponent()))
elif name_type == 'uniformResourceIdentifier': if name_type == 'uniformResourceIdentifier':
value = decode_str(name.getComponent()) value = decode_str(name.getComponent())
if value.startswith('xmpp:'): if value.startswith('xmpp:'):
results['URI'].add(value[5:]) results['URI'].add(value[5:])

View File

@@ -19,7 +19,7 @@ import ssl
import weakref import weakref
import uuid import uuid
import xml.etree.ElementTree as ET import xml.etree.ElementTree
from slixmpp.xmlstream.asyncio import asyncio from slixmpp.xmlstream.asyncio import asyncio
from slixmpp.xmlstream import tostring, highlight from slixmpp.xmlstream import tostring, highlight
@@ -339,7 +339,7 @@ class XMLStream(asyncio.BaseProtocol):
""" """
self.xml_depth = 0 self.xml_depth = 0
self.xml_root = None self.xml_root = None
self.parser = ET.XMLPullParser(("start", "end")) self.parser = xml.etree.ElementTree.XMLPullParser(("start", "end"))
def connection_made(self, transport): def connection_made(self, transport):
"""Called when the TCP connection has been established with the server """Called when the TCP connection has been established with the server
@@ -359,46 +359,32 @@ class XMLStream(asyncio.BaseProtocol):
the stream is opened, etc). the stream is opened, etc).
""" """
self.parser.feed(data) self.parser.feed(data)
try: for event, xml in self.parser.read_events():
for event, xml in self.parser.read_events(): if event == 'start':
if event == 'start': if self.xml_depth == 0:
if self.xml_depth == 0: # We have received the start of the root element.
# We have received the start of the root element. self.xml_root = xml
self.xml_root = xml log.debug('RECV: %s', highlight(tostring(self.xml_root, xmlns=self.default_ns,
log.debug('RECV: %s', stream=self,
highlight(tostring(self.xml_root, top_level=True,
xmlns=self.default_ns, open_only=True)))
stream=self, self.start_stream_handler(self.xml_root)
top_level=True, self.xml_depth += 1
open_only=True))) if event == 'end':
self.start_stream_handler(self.xml_root) self.xml_depth -= 1
self.xml_depth += 1 if self.xml_depth == 0:
if event == 'end': # The stream's root element has closed,
self.xml_depth -= 1 # terminating the stream.
if self.xml_depth == 0: log.debug("End of stream received")
# The stream's root element has closed, self.abort()
# terminating the stream. elif self.xml_depth == 1:
log.debug("End of stream received") # A stanza is an XML element that is a direct child of
self.abort() # the root element, hence the check of depth == 1
elif self.xml_depth == 1: self._spawn_event(xml)
# A stanza is an XML element that is a direct child of if self.xml_root is not None:
# the root element, hence the check of depth == 1 # Keep the root element empty of children to
self._spawn_event(xml) # save on memory use.
if self.xml_root is not None: self.xml_root.clear()
# Keep the root element empty of children to
# save on memory use.
self.xml_root.clear()
except ET.ParseError:
log.error('Parse error: %r', data)
# Due to cyclic dependencies, this cant be imported at the module
# level.
from slixmpp.stanza.stream_error import StreamError
error = StreamError()
error['condition'] = 'not-well-formed'
error['text'] = 'Server sent: %r' % data
self.send(error)
self.disconnect()
def is_connected(self): def is_connected(self):
return self.transport is not None return self.transport is not None

View File

@@ -1,37 +0,0 @@
import unittest
from slixmpp import Message
from slixmpp.test import SlixTest
import slixmpp.plugins.xep_0380 as xep_0380
from slixmpp.xmlstream import register_stanza_plugin
class TestEME(SlixTest):
def setUp(self):
register_stanza_plugin(Message, xep_0380.stanza.Encryption)
def testCreateEME(self):
"""Testing creating EME."""
xmlstring = """
<message>
<encryption xmlns="urn:xmpp:eme:0" namespace="%s"%s />
</message>
"""
msg = self.Message()
self.check(msg, "<message />")
msg['eme']['namespace'] = 'urn:xmpp:otr:0'
self.check(msg, xmlstring % ('urn:xmpp:otr:0', ''))
msg['eme']['namespace'] = 'urn:xmpp:openpgp:0'
self.check(msg, xmlstring % ('urn:xmpp:openpgp:0', ''))
msg['eme']['name'] = 'OX'
self.check(msg, xmlstring % ('urn:xmpp:openpgp:0', ' name="OX"'))
del msg['eme']
self.check(msg, "<message />")
suite = unittest.TestLoader().loadTestsFromTestCase(TestEME)