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_0030/stanza',
|
||||||
'sleekxmpp/plugins/xep_0033',
|
'sleekxmpp/plugins/xep_0033',
|
||||||
'sleekxmpp/plugins/xep_0047',
|
'sleekxmpp/plugins/xep_0047',
|
||||||
|
'sleekxmpp/plugins/xep_0049',
|
||||||
'sleekxmpp/plugins/xep_0050',
|
'sleekxmpp/plugins/xep_0050',
|
||||||
'sleekxmpp/plugins/xep_0054',
|
'sleekxmpp/plugins/xep_0054',
|
||||||
'sleekxmpp/plugins/xep_0059',
|
'sleekxmpp/plugins/xep_0059',
|
||||||
@ -98,8 +99,10 @@ packages = [ 'sleekxmpp',
|
|||||||
'sleekxmpp/plugins/xep_0221',
|
'sleekxmpp/plugins/xep_0221',
|
||||||
'sleekxmpp/plugins/xep_0224',
|
'sleekxmpp/plugins/xep_0224',
|
||||||
'sleekxmpp/plugins/xep_0231',
|
'sleekxmpp/plugins/xep_0231',
|
||||||
|
'sleekxmpp/plugins/xep_0235',
|
||||||
'sleekxmpp/plugins/xep_0249',
|
'sleekxmpp/plugins/xep_0249',
|
||||||
'sleekxmpp/plugins/xep_0258',
|
'sleekxmpp/plugins/xep_0258',
|
||||||
|
'sleekxmpp/plugins/xep_0279',
|
||||||
'sleekxmpp/features',
|
'sleekxmpp/features',
|
||||||
'sleekxmpp/features/feature_mechanisms',
|
'sleekxmpp/features/feature_mechanisms',
|
||||||
'sleekxmpp/features/feature_mechanisms/stanza',
|
'sleekxmpp/features/feature_mechanisms/stanza',
|
||||||
|
@ -24,6 +24,7 @@ __all__ = [
|
|||||||
'xep_0033', # Extended Stanza Addresses
|
'xep_0033', # Extended Stanza Addresses
|
||||||
'xep_0045', # Multi-User Chat (Client)
|
'xep_0045', # Multi-User Chat (Client)
|
||||||
'xep_0047', # In-Band Bytestreams
|
'xep_0047', # In-Band Bytestreams
|
||||||
|
'xep_0049', # Private XML Storage
|
||||||
'xep_0050', # Ad-hoc Commands
|
'xep_0050', # Ad-hoc Commands
|
||||||
'xep_0054', # vcard-temp
|
'xep_0054', # vcard-temp
|
||||||
'xep_0059', # Result Set Management
|
'xep_0059', # Result Set Management
|
||||||
@ -61,10 +62,12 @@ __all__ = [
|
|||||||
'xep_0223', # Persistent Storage of Private Data via Pubsub
|
'xep_0223', # Persistent Storage of Private Data via Pubsub
|
||||||
'xep_0224', # Attention
|
'xep_0224', # Attention
|
||||||
'xep_0231', # Bits of Binary
|
'xep_0231', # Bits of Binary
|
||||||
|
'xep_0235', # OAuth Over XMPP
|
||||||
'xep_0242', # XMPP Client Compliance 2009
|
'xep_0242', # XMPP Client Compliance 2009
|
||||||
'xep_0249', # Direct MUC Invitations
|
'xep_0249', # Direct MUC Invitations
|
||||||
'xep_0256', # Last Activity in Presence
|
'xep_0256', # Last Activity in Presence
|
||||||
'xep_0258', # Security Labels in XMPP
|
'xep_0258', # Security Labels in XMPP
|
||||||
'xep_0270', # XMPP Compliance Suites 2010
|
'xep_0270', # XMPP Compliance Suites 2010
|
||||||
|
'xep_0279', # Server IP Check
|
||||||
'xep_0302', # XMPP Compliance Suites 2012
|
'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']):
|
if str(existing_verstring) == str(pres['caps']['ver']):
|
||||||
return
|
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:
|
if pres['caps']['hash'] not in self.hashes:
|
||||||
try:
|
try:
|
||||||
log.debug("Unknown caps hash: %s", pres['caps']['hash'])
|
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']
|
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)
|
@sasl_mech(3)
|
||||||
class X_GOOGLE_TOKEN(Mech):
|
class X_GOOGLE_TOKEN(Mech):
|
||||||
|
|
||||||
|
@ -147,7 +147,10 @@ def verify(expected, raw_cert):
|
|||||||
raise CertificateError(
|
raise CertificateError(
|
||||||
'Certificate has expired.')
|
'Certificate has expired.')
|
||||||
|
|
||||||
|
if '.' in expected:
|
||||||
expected_wild = expected[expected.index('.'):]
|
expected_wild = expected[expected.index('.'):]
|
||||||
|
else:
|
||||||
|
expected_wild = expected
|
||||||
expected_srv = '_xmpp-client.%s' % expected
|
expected_srv = '_xmpp-client.%s' % expected
|
||||||
|
|
||||||
for name in cert_names['XMPPAddr']:
|
for name in cert_names['XMPPAddr']:
|
||||||
@ -160,7 +163,10 @@ def verify(expected, raw_cert):
|
|||||||
if name == expected:
|
if name == expected:
|
||||||
return True
|
return True
|
||||||
if name.startswith('*'):
|
if name.startswith('*'):
|
||||||
|
if '.' in name:
|
||||||
name_wild = name[name.index('.'):]
|
name_wild = name[name.index('.'):]
|
||||||
|
else:
|
||||||
|
name_wild = name
|
||||||
if expected_wild == name_wild:
|
if expected_wild == name_wild:
|
||||||
return True
|
return True
|
||||||
for name in cert_names['URI']:
|
for name in cert_names['URI']:
|
||||||
|
Loading…
Reference in New Issue
Block a user