Compare commits
1 Commits
slix-1.2.4
...
compiler
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4683546d9 |
@@ -1,8 +0,0 @@
|
|||||||
test:
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
image: ubuntu:latest
|
|
||||||
script:
|
|
||||||
- apt update
|
|
||||||
- apt install -y python3 cython3
|
|
||||||
- ./run_tests.py
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
.. _mucbot:
|
.. _mucbot:
|
||||||
|
|
||||||
=========================
|
=========================
|
||||||
Multi-User Chat (MUC) Bot
|
Mulit-User Chat (MUC) Bot
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
23
setup.py
23
setup.py
@@ -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",
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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)
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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)
|
|
||||||
@@ -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
|
|
||||||
@@ -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)
|
|
||||||
@@ -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
|
|
||||||
@@ -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')
|
|
||||||
@@ -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'
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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 """
|
||||||
|
|||||||
@@ -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__)
|
||||||
|
|||||||
@@ -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)
|
|
||||||
@@ -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)
|
|
||||||
@@ -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'}
|
|
||||||
@@ -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'}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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:])
|
||||||
|
|||||||
@@ -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('[33;1mRECV[0m: %s', highlight(tostring(self.xml_root, xmlns=self.default_ns,
|
||||||
log.debug('[33;1mRECV[0m: %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 can’t 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
|
||||||
|
|||||||
@@ -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)
|
|
||||||
Reference in New Issue
Block a user