Merge branch 'master' into develop
This commit is contained in:
commit
67147570e9
3
setup.py
3
setup.py
@ -66,6 +66,7 @@ packages = [ 'sleekxmpp',
|
||||
'sleekxmpp/plugins/xep_0030/stanza',
|
||||
'sleekxmpp/plugins/xep_0033',
|
||||
'sleekxmpp/plugins/xep_0047',
|
||||
'sleekxmpp/plugins/xep_0049',
|
||||
'sleekxmpp/plugins/xep_0050',
|
||||
'sleekxmpp/plugins/xep_0054',
|
||||
'sleekxmpp/plugins/xep_0059',
|
||||
@ -98,8 +99,10 @@ packages = [ 'sleekxmpp',
|
||||
'sleekxmpp/plugins/xep_0221',
|
||||
'sleekxmpp/plugins/xep_0224',
|
||||
'sleekxmpp/plugins/xep_0231',
|
||||
'sleekxmpp/plugins/xep_0235',
|
||||
'sleekxmpp/plugins/xep_0249',
|
||||
'sleekxmpp/plugins/xep_0258',
|
||||
'sleekxmpp/plugins/xep_0279',
|
||||
'sleekxmpp/features',
|
||||
'sleekxmpp/features/feature_mechanisms',
|
||||
'sleekxmpp/features/feature_mechanisms/stanza',
|
||||
|
@ -24,6 +24,7 @@ __all__ = [
|
||||
'xep_0033', # Extended Stanza Addresses
|
||||
'xep_0045', # Multi-User Chat (Client)
|
||||
'xep_0047', # In-Band Bytestreams
|
||||
'xep_0049', # Private XML Storage
|
||||
'xep_0050', # Ad-hoc Commands
|
||||
'xep_0054', # vcard-temp
|
||||
'xep_0059', # Result Set Management
|
||||
@ -61,10 +62,12 @@ __all__ = [
|
||||
'xep_0223', # Persistent Storage of Private Data via Pubsub
|
||||
'xep_0224', # Attention
|
||||
'xep_0231', # Bits of Binary
|
||||
'xep_0235', # OAuth Over XMPP
|
||||
'xep_0242', # XMPP Client Compliance 2009
|
||||
'xep_0249', # Direct MUC Invitations
|
||||
'xep_0256', # Last Activity in Presence
|
||||
'xep_0258', # Security Labels in XMPP
|
||||
'xep_0270', # XMPP Compliance Suites 2010
|
||||
'xep_0279', # Server IP Check
|
||||
'xep_0302', # XMPP Compliance Suites 2012
|
||||
]
|
||||
|
15
sleekxmpp/plugins/xep_0049/__init__.py
Normal file
15
sleekxmpp/plugins/xep_0049/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from sleekxmpp.plugins.base import register_plugin
|
||||
|
||||
from sleekxmpp.plugins.xep_0049.stanza import PrivateXML
|
||||
from sleekxmpp.plugins.xep_0049.private_storage import XEP_0049
|
||||
|
||||
|
||||
register_plugin(XEP_0049)
|
53
sleekxmpp/plugins/xep_0049/private_storage.py
Normal file
53
sleekxmpp/plugins/xep_0049/private_storage.py
Normal file
@ -0,0 +1,53 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from sleekxmpp import Iq
|
||||
from sleekxmpp.plugins import BasePlugin
|
||||
from sleekxmpp.xmlstream.handler import Callback
|
||||
from sleekxmpp.xmlstream.matcher import StanzaPath
|
||||
from sleekxmpp.xmlstream import register_stanza_plugin
|
||||
from sleekxmpp.plugins.xep_0049 import stanza, PrivateXML
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class XEP_0049(BasePlugin):
|
||||
|
||||
name = 'xep_0049'
|
||||
description = 'XEP-0049: Private XML Storage'
|
||||
dependencies = set([])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
register_stanza_plugin(Iq, PrivateXML)
|
||||
|
||||
def register(self, stanza):
|
||||
register_stanza_plugin(PrivateXML, stanza, iterable=True)
|
||||
|
||||
def store(self, data, ifrom=None, block=True, timeout=None, callback=None):
|
||||
iq = self.xmpp.Iq()
|
||||
iq['type'] = 'set'
|
||||
iq['from'] = ifrom
|
||||
|
||||
if not isinstance(data, list):
|
||||
data = [data]
|
||||
|
||||
for elem in data:
|
||||
iq['private'].append(elem)
|
||||
|
||||
return iq.send(block=block, timeout=timeout, callback=callback)
|
||||
|
||||
def retrieve(self, name, ifrom=None, block=True, timeout=None, callback=None):
|
||||
iq = self.xmpp.Iq()
|
||||
iq['type'] = 'get'
|
||||
iq['from'] = ifrom
|
||||
iq['private'].enable(name)
|
||||
return iq.send(block=block, timeout=timeout, callback=callback)
|
17
sleekxmpp/plugins/xep_0049/stanza.py
Normal file
17
sleekxmpp/plugins/xep_0049/stanza.py
Normal file
@ -0,0 +1,17 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from sleekxmpp.xmlstream import ET, ElementBase
|
||||
|
||||
|
||||
class PrivateXML(ElementBase):
|
||||
|
||||
name = 'query'
|
||||
namespace = 'jabber:iq:private'
|
||||
plugin_attrib = 'private'
|
||||
interfaces = set()
|
@ -143,6 +143,11 @@ class XEP_0115(BasePlugin):
|
||||
if str(existing_verstring) == str(pres['caps']['ver']):
|
||||
return
|
||||
|
||||
existing_caps = self.get_caps(verstring=pres['caps']['ver'])
|
||||
if existing_caps is not None:
|
||||
self.assign_verstring(pres['from'], pres['caps']['ver'])
|
||||
return
|
||||
|
||||
if pres['caps']['hash'] not in self.hashes:
|
||||
try:
|
||||
log.debug("Unknown caps hash: %s", pres['caps']['hash'])
|
||||
|
16
sleekxmpp/plugins/xep_0235/__init__.py
Normal file
16
sleekxmpp/plugins/xep_0235/__init__.py
Normal file
@ -0,0 +1,16 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from sleekxmpp.plugins.base import register_plugin
|
||||
|
||||
from sleekxmpp.plugins.xep_0235 import stanza
|
||||
from sleekxmpp.plugins.xep_0235.stanza import OAuth
|
||||
from sleekxmpp.plugins.xep_0235.oauth import XEP_0235
|
||||
|
||||
|
||||
register_plugin(XEP_0235)
|
32
sleekxmpp/plugins/xep_0235/oauth.py
Normal file
32
sleekxmpp/plugins/xep_0235/oauth.py
Normal file
@ -0,0 +1,32 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from sleekxmpp import Message
|
||||
from sleekxmpp.plugins import BasePlugin
|
||||
from sleekxmpp.xmlstream import register_stanza_plugin
|
||||
from sleekxmpp.plugins.xep_0235 import stanza, OAuth
|
||||
|
||||
|
||||
class XEP_0235(BasePlugin):
|
||||
|
||||
name = 'xep_0235'
|
||||
description = 'XEP-0235: OAuth Over XMPP'
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
register_stanza_plugin(Message, OAuth)
|
||||
|
||||
def session_bind(self, jid):
|
||||
self.xmpp['xep_0030'].add_feature('urn:xmpp:oauth:0')
|
||||
|
||||
def plugin_end(self):
|
||||
self.xmpp['xep_0030'].del_feature(feature='urn:xmpp:oauth:0')
|
80
sleekxmpp/plugins/xep_0235/stanza.py
Normal file
80
sleekxmpp/plugins/xep_0235/stanza.py
Normal file
@ -0,0 +1,80 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
import hmac
|
||||
import hashlib
|
||||
import urllib
|
||||
import base64
|
||||
|
||||
from sleekxmpp.xmlstream import ET, ElementBase, JID
|
||||
|
||||
|
||||
class OAuth(ElementBase):
|
||||
|
||||
name = 'oauth'
|
||||
namespace = 'urn:xmpp:oauth:0'
|
||||
plugin_attrib = 'oauth'
|
||||
interfaces = set(['oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
|
||||
'oauth_signature_method', 'oauth_timestamp',
|
||||
'oauth_token', 'oauth_version'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
def generate_signature(self, stanza, sfrom, sto, consumer_secret,
|
||||
token_secret, method='HMAC-SHA1'):
|
||||
self['oauth_signature_method'] = method
|
||||
|
||||
request = urllib.quote('%s&%s' % (sfrom, sto), '')
|
||||
parameters = urllib.quote('&'.join([
|
||||
'oauth_consumer_key=%s' % self['oauth_consumer_key'],
|
||||
'oauth_nonce=%s' % self['oauth_nonce'],
|
||||
'oauth_signature_method=%s' % self['oauth_signature_method'],
|
||||
'oauth_timestamp=%s' % self['oauth_timestamp'],
|
||||
'oauth_token=%s' % self['oauth_token'],
|
||||
'oauth_version=%s' % self['oauth_version']
|
||||
]), '')
|
||||
|
||||
sigbase = '%s&%s&%s' % (stanza, request, parameters)
|
||||
|
||||
consumer_secret = urllib.quote(consumer_secret, '')
|
||||
token_secret = urllib.quote(token_secret, '')
|
||||
key = '%s&%s' % (consumer_secret, token_secret)
|
||||
|
||||
if method == 'HMAC-SHA1':
|
||||
sig = base64.b64encode(hmac.new(key, sigbase, hashlib.sha1).digest())
|
||||
elif method == 'PLAINTEXT':
|
||||
sig = key
|
||||
|
||||
self['oauth_signature'] = sig
|
||||
return sig
|
||||
|
||||
def verify_signature(self, stanza, sfrom, sto, consumer_secret,
|
||||
token_secret):
|
||||
method = self['oauth_signature_method']
|
||||
|
||||
request = urllib.quote('%s&%s' % (sfrom, sto), '')
|
||||
parameters = urllib.quote('&'.join([
|
||||
'oauth_consumer_key=%s' % self['oauth_consumer_key'],
|
||||
'oauth_nonce=%s' % self['oauth_nonce'],
|
||||
'oauth_signature_method=%s' % self['oauth_signature_method'],
|
||||
'oauth_timestamp=%s' % self['oauth_timestamp'],
|
||||
'oauth_token=%s' % self['oauth_token'],
|
||||
'oauth_version=%s' % self['oauth_version']
|
||||
]), '')
|
||||
|
||||
sigbase = '%s&%s&%s' % (stanza, request, parameters)
|
||||
|
||||
consumer_secret = urllib.quote(consumer_secret, '')
|
||||
token_secret = urllib.quote(token_secret, '')
|
||||
key = '%s&%s' % (consumer_secret, token_secret)
|
||||
|
||||
if method == 'HMAC-SHA1':
|
||||
sig = base64.b64encode(hmac.new(key, sigbase, hashlib.sha1).digest())
|
||||
elif method == 'PLAINTEXT':
|
||||
sig = key
|
||||
|
||||
return self['oauth_signature'] == sig
|
16
sleekxmpp/plugins/xep_0279/__init__.py
Normal file
16
sleekxmpp/plugins/xep_0279/__init__.py
Normal file
@ -0,0 +1,16 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from sleekxmpp.plugins.base import register_plugin
|
||||
|
||||
from sleekxmpp.plugins.xep_0279 import stanza
|
||||
from sleekxmpp.plugins.xep_0279.stanza import IPCheck
|
||||
from sleekxmpp.plugins.xep_0279.ipcheck import XEP_0279
|
||||
|
||||
|
||||
register_plugin(XEP_0279)
|
39
sleekxmpp/plugins/xep_0279/ipcheck.py
Normal file
39
sleekxmpp/plugins/xep_0279/ipcheck.py
Normal file
@ -0,0 +1,39 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from sleekxmpp import Iq
|
||||
from sleekxmpp.plugins import BasePlugin
|
||||
from sleekxmpp.xmlstream import register_stanza_plugin
|
||||
from sleekxmpp.plugins.xep_0279 import stanza, IPCheck
|
||||
|
||||
|
||||
class XEP_0279(BasePlugin):
|
||||
|
||||
name = 'xep_0279'
|
||||
description = 'XEP-0279: Server IP Check'
|
||||
dependencies = set(['xep_0030'])
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
register_stanza_plugin(Iq, IPCheck)
|
||||
|
||||
def session_bind(self, jid):
|
||||
self.xmpp['xep_0030'].add_feature('urn:xmpp:sic:0')
|
||||
|
||||
def plugin_end(self):
|
||||
self.xmpp['xep_0030'].del_feature(feature='urn:xmpp:sic:0')
|
||||
|
||||
def check_ip(self, ifrom=None, block=True, timeout=None, callback=None):
|
||||
iq = self.xmpp.Iq()
|
||||
iq['type'] = 'get'
|
||||
iq['from'] = ifrom
|
||||
iq.enable('ip_check')
|
||||
return iq.send(block=block, timeout=timeout, callback=callback)
|
30
sleekxmpp/plugins/xep_0279/stanza.py
Normal file
30
sleekxmpp/plugins/xep_0279/stanza.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from sleekxmpp.xmlstream import ElementBase
|
||||
|
||||
|
||||
class IPCheck(ElementBase):
|
||||
|
||||
name = 'ip'
|
||||
namespace = 'urn:xmpp:sic:0'
|
||||
plugin_attrib = 'ip_check'
|
||||
interfaces = set(['ip_check'])
|
||||
is_extension = True
|
||||
|
||||
def get_ip_check(self):
|
||||
return self.xml.text
|
||||
|
||||
def set_ip_check(self, value):
|
||||
if value:
|
||||
self.xml.text = value
|
||||
else:
|
||||
self.xml.text = ''
|
||||
|
||||
def del_ip_check(self):
|
||||
self.xml.text = ''
|
@ -123,6 +123,17 @@ class X_MESSENGER_OAUTH2(Mech):
|
||||
return self.credentials['access_token']
|
||||
|
||||
|
||||
@sasl_mech(10)
|
||||
class X_OAUTH2(Mech):
|
||||
|
||||
name = 'X-OAUTH2'
|
||||
required_credentials = set(['username', 'access_token'])
|
||||
|
||||
def process(self, challenge=b''):
|
||||
return b'\x00' + self.credentials['username'] + \
|
||||
b'\x00' + self.credentials['access_token']
|
||||
|
||||
|
||||
@sasl_mech(3)
|
||||
class X_GOOGLE_TOKEN(Mech):
|
||||
|
||||
|
@ -147,7 +147,10 @@ def verify(expected, raw_cert):
|
||||
raise CertificateError(
|
||||
'Certificate has expired.')
|
||||
|
||||
if '.' in expected:
|
||||
expected_wild = expected[expected.index('.'):]
|
||||
else:
|
||||
expected_wild = expected
|
||||
expected_srv = '_xmpp-client.%s' % expected
|
||||
|
||||
for name in cert_names['XMPPAddr']:
|
||||
@ -160,7 +163,10 @@ def verify(expected, raw_cert):
|
||||
if name == expected:
|
||||
return True
|
||||
if name.startswith('*'):
|
||||
if '.' in name:
|
||||
name_wild = name[name.index('.'):]
|
||||
else:
|
||||
name_wild = name
|
||||
if expected_wild == name_wild:
|
||||
return True
|
||||
for name in cert_names['URI']:
|
||||
|
Loading…
Reference in New Issue
Block a user