mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-24 03:00:15 +00:00
Merge branch 'roster' of github.com:fritzy/SleekXMPP into roster
Conflicts: sleekxmpp/basexmpp.py sleekxmpp/roster.py sleekxmpp/test/sleektest.py tests/test_stream_presence.py tests/test_stream_roster.py
This commit is contained in:
commit
26aca2b789
47 changed files with 920 additions and 938 deletions
BIN
sleekxmpp/__init__$py.class
Normal file
BIN
sleekxmpp/__init__$py.class
Normal file
Binary file not shown.
|
@ -27,13 +27,7 @@ from sleekxmpp.xmlstream.matcher import *
|
||||||
from sleekxmpp.xmlstream.handler import *
|
from sleekxmpp.xmlstream.handler import *
|
||||||
|
|
||||||
|
|
||||||
# Flag indicating if DNS SRV records are available for use.
|
log = logging.getLogger(__name__)
|
||||||
SRV_SUPPORT = True
|
|
||||||
try:
|
|
||||||
import dns.resolver
|
|
||||||
except:
|
|
||||||
SRV_SUPPORT = False
|
|
||||||
|
|
||||||
|
|
||||||
# In order to make sure that Unicode is handled properly
|
# In order to make sure that Unicode is handled properly
|
||||||
# in Python 2.x, reset the default encoding.
|
# in Python 2.x, reset the default encoding.
|
||||||
|
@ -205,9 +199,9 @@ class BaseXMPP(XMLStream):
|
||||||
xep = "(XEP-%s) " % self.plugin[plugin].xep
|
xep = "(XEP-%s) " % self.plugin[plugin].xep
|
||||||
|
|
||||||
desc = (xep, self.plugin[plugin].description)
|
desc = (xep, self.plugin[plugin].description)
|
||||||
logging.debug("Loaded Plugin %s%s" % desc)
|
log.debug("Loaded Plugin %s%s" % desc)
|
||||||
except:
|
except:
|
||||||
logging.exception("Unable to load plugin: %s", plugin)
|
log.exception("Unable to load plugin: %s", plugin)
|
||||||
|
|
||||||
def register_plugins(self):
|
def register_plugins(self):
|
||||||
"""
|
"""
|
||||||
|
@ -241,7 +235,7 @@ class BaseXMPP(XMLStream):
|
||||||
if key in self.plugin:
|
if key in self.plugin:
|
||||||
return self.plugin[key]
|
return self.plugin[key]
|
||||||
else:
|
else:
|
||||||
logging.warning("""Plugin "%s" is not loaded.""" % key)
|
log.warning("""Plugin "%s" is not loaded.""" % key)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get(self, key, default):
|
def get(self, key, default):
|
||||||
|
@ -459,12 +453,12 @@ class BaseXMPP(XMLStream):
|
||||||
"""
|
"""
|
||||||
Attribute accessor for bare jid
|
Attribute accessor for bare jid
|
||||||
"""
|
"""
|
||||||
logging.warning("jid property deprecated. Use boundjid.bare")
|
log.warning("jid property deprecated. Use boundjid.bare")
|
||||||
return self.boundjid.bare
|
return self.boundjid.bare
|
||||||
|
|
||||||
@jid.setter
|
@jid.setter
|
||||||
def jid(self, value):
|
def jid(self, value):
|
||||||
logging.warning("jid property deprecated. Use boundjid.bare")
|
log.warning("jid property deprecated. Use boundjid.bare")
|
||||||
self.boundjid.bare = value
|
self.boundjid.bare = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -472,12 +466,12 @@ class BaseXMPP(XMLStream):
|
||||||
"""
|
"""
|
||||||
Attribute accessor for full jid
|
Attribute accessor for full jid
|
||||||
"""
|
"""
|
||||||
logging.warning("fulljid property deprecated. Use boundjid.full")
|
log.warning("fulljid property deprecated. Use boundjid.full")
|
||||||
return self.boundjid.full
|
return self.boundjid.full
|
||||||
|
|
||||||
@fulljid.setter
|
@fulljid.setter
|
||||||
def fulljid(self, value):
|
def fulljid(self, value):
|
||||||
logging.warning("fulljid property deprecated. Use boundjid.full")
|
log.warning("fulljid property deprecated. Use boundjid.full")
|
||||||
self.boundjid.full = value
|
self.boundjid.full = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -485,12 +479,12 @@ class BaseXMPP(XMLStream):
|
||||||
"""
|
"""
|
||||||
Attribute accessor for jid resource
|
Attribute accessor for jid resource
|
||||||
"""
|
"""
|
||||||
logging.warning("resource property deprecated. Use boundjid.resource")
|
log.warning("resource property deprecated. Use boundjid.resource")
|
||||||
return self.boundjid.resource
|
return self.boundjid.resource
|
||||||
|
|
||||||
@resource.setter
|
@resource.setter
|
||||||
def resource(self, value):
|
def resource(self, value):
|
||||||
logging.warning("fulljid property deprecated. Use boundjid.full")
|
log.warning("fulljid property deprecated. Use boundjid.full")
|
||||||
self.boundjid.resource = value
|
self.boundjid.resource = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -498,12 +492,12 @@ class BaseXMPP(XMLStream):
|
||||||
"""
|
"""
|
||||||
Attribute accessor for jid usernode
|
Attribute accessor for jid usernode
|
||||||
"""
|
"""
|
||||||
logging.warning("username property deprecated. Use boundjid.user")
|
log.warning("username property deprecated. Use boundjid.user")
|
||||||
return self.boundjid.user
|
return self.boundjid.user
|
||||||
|
|
||||||
@username.setter
|
@username.setter
|
||||||
def username(self, value):
|
def username(self, value):
|
||||||
logging.warning("username property deprecated. Use boundjid.user")
|
log.warning("username property deprecated. Use boundjid.user")
|
||||||
self.boundjid.user = value
|
self.boundjid.user = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -511,17 +505,17 @@ class BaseXMPP(XMLStream):
|
||||||
"""
|
"""
|
||||||
Attribute accessor for jid host
|
Attribute accessor for jid host
|
||||||
"""
|
"""
|
||||||
logging.warning("server property deprecated. Use boundjid.host")
|
log.warning("server property deprecated. Use boundjid.host")
|
||||||
return self.boundjid.server
|
return self.boundjid.server
|
||||||
|
|
||||||
@server.setter
|
@server.setter
|
||||||
def server(self, value):
|
def server(self, value):
|
||||||
logging.warning("server property deprecated. Use boundjid.host")
|
log.warning("server property deprecated. Use boundjid.host")
|
||||||
self.boundjid.server = value
|
self.boundjid.server = value
|
||||||
|
|
||||||
def set_jid(self, jid):
|
def set_jid(self, jid):
|
||||||
"""Rip a JID apart and claim it as our own."""
|
"""Rip a JID apart and claim it as our own."""
|
||||||
logging.debug("setting jid to %s" % jid)
|
log.debug("setting jid to %s" % jid)
|
||||||
self.boundjid.full = jid
|
self.boundjid.full = jid
|
||||||
|
|
||||||
def getjidresource(self, fulljid):
|
def getjidresource(self, fulljid):
|
||||||
|
@ -596,6 +590,5 @@ class BaseXMPP(XMLStream):
|
||||||
return
|
return
|
||||||
self.event("changed_status", presence)
|
self.event("changed_status", presence)
|
||||||
|
|
||||||
|
|
||||||
# Restore the old, lowercased name for backwards compatibility.
|
# Restore the old, lowercased name for backwards compatibility.
|
||||||
basexmpp = BaseXMPP
|
basexmpp = BaseXMPP
|
||||||
|
|
|
@ -32,6 +32,9 @@ except:
|
||||||
SRV_SUPPORT = False
|
SRV_SUPPORT = False
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ClientXMPP(BaseXMPP):
|
class ClientXMPP(BaseXMPP):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -132,7 +135,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
|
|
||||||
def _session_timeout_check(self):
|
def _session_timeout_check(self):
|
||||||
if not self.session_started_event.isSet():
|
if not self.session_started_event.isSet():
|
||||||
logging.debug("Session start has taken more than 15 seconds")
|
log.debug("Session start has taken more than 15 seconds")
|
||||||
self.disconnect(reconnect=self.auto_reconnect)
|
self.disconnect(reconnect=self.auto_reconnect)
|
||||||
|
|
||||||
def connect(self, address=tuple()):
|
def connect(self, address=tuple()):
|
||||||
|
@ -149,19 +152,19 @@ class ClientXMPP(BaseXMPP):
|
||||||
self.session_started_event.clear()
|
self.session_started_event.clear()
|
||||||
if not address or len(address) < 2:
|
if not address or len(address) < 2:
|
||||||
if not self.srv_support:
|
if not self.srv_support:
|
||||||
logging.debug("Did not supply (address, port) to connect" + \
|
log.debug("Did not supply (address, port) to connect" + \
|
||||||
" to and no SRV support is installed" + \
|
" to and no SRV support is installed" + \
|
||||||
" (http://www.dnspython.org)." + \
|
" (http://www.dnspython.org)." + \
|
||||||
" Continuing to attempt connection, using" + \
|
" Continuing to attempt connection, using" + \
|
||||||
" server hostname from JID.")
|
" server hostname from JID.")
|
||||||
else:
|
else:
|
||||||
logging.debug("Since no address is supplied," + \
|
log.debug("Since no address is supplied," + \
|
||||||
"attempting SRV lookup.")
|
"attempting SRV lookup.")
|
||||||
try:
|
try:
|
||||||
xmpp_srv = "_xmpp-client._tcp.%s" % self.server
|
xmpp_srv = "_xmpp-client._tcp.%s" % self.server
|
||||||
answers = dns.resolver.query(xmpp_srv, dns.rdatatype.SRV)
|
answers = dns.resolver.query(xmpp_srv, dns.rdatatype.SRV)
|
||||||
except dns.resolver.NXDOMAIN:
|
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
||||||
logging.debug("No appropriate SRV record found." + \
|
log.debug("No appropriate SRV record found." + \
|
||||||
" Using JID server name.")
|
" Using JID server name.")
|
||||||
else:
|
else:
|
||||||
# Pick a random server, weighted by priority.
|
# Pick a random server, weighted by priority.
|
||||||
|
@ -275,7 +278,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
self.send_xml(xml)
|
self.send_xml(xml)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logging.warning("The module tlslite is required to log in" +\
|
log.warning("The module tlslite is required to log in" +\
|
||||||
" to some servers, and has not been found.")
|
" to some servers, and has not been found.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -285,7 +288,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
|
|
||||||
Restarts the stream.
|
Restarts the stream.
|
||||||
"""
|
"""
|
||||||
logging.debug("Starting TLS")
|
log.debug("Starting TLS")
|
||||||
if self.start_tls():
|
if self.start_tls():
|
||||||
raise RestartStream()
|
raise RestartStream()
|
||||||
|
|
||||||
|
@ -299,7 +302,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
if '{urn:ietf:params:xml:ns:xmpp-tls}starttls' in self.features:
|
if '{urn:ietf:params:xml:ns:xmpp-tls}starttls' in self.features:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logging.debug("Starting SASL Auth")
|
log.debug("Starting SASL Auth")
|
||||||
sasl_ns = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
sasl_ns = 'urn:ietf:params:xml:ns:xmpp-sasl'
|
||||||
self.add_handler("<success xmlns='%s' />" % sasl_ns,
|
self.add_handler("<success xmlns='%s' />" % sasl_ns,
|
||||||
self._handle_auth_success,
|
self._handle_auth_success,
|
||||||
|
@ -333,7 +336,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
sasl_ns,
|
sasl_ns,
|
||||||
'ANONYMOUS'))
|
'ANONYMOUS'))
|
||||||
else:
|
else:
|
||||||
logging.error("No appropriate login method.")
|
log.error("No appropriate login method.")
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -355,7 +358,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
Arguments:
|
Arguments:
|
||||||
xml -- The SASL authentication failure element.
|
xml -- The SASL authentication failure element.
|
||||||
"""
|
"""
|
||||||
logging.info("Authentication failed.")
|
log.info("Authentication failed.")
|
||||||
self.event("failed_auth", direct=True)
|
self.event("failed_auth", direct=True)
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
|
@ -366,7 +369,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
Arguments:
|
Arguments:
|
||||||
xml -- The bind feature element.
|
xml -- The bind feature element.
|
||||||
"""
|
"""
|
||||||
logging.debug("Requesting resource: %s" % self.boundjid.resource)
|
log.debug("Requesting resource: %s" % self.boundjid.resource)
|
||||||
xml.clear()
|
xml.clear()
|
||||||
iq = self.Iq(stype='set')
|
iq = self.Iq(stype='set')
|
||||||
if self.boundjid.resource:
|
if self.boundjid.resource:
|
||||||
|
@ -380,10 +383,10 @@ class ClientXMPP(BaseXMPP):
|
||||||
self.set_jid(response.xml.find('{%s}bind/{%s}jid' % (bind_ns,
|
self.set_jid(response.xml.find('{%s}bind/{%s}jid' % (bind_ns,
|
||||||
bind_ns)).text)
|
bind_ns)).text)
|
||||||
self.bound = True
|
self.bound = True
|
||||||
logging.info("Node set to: %s" % self.boundjid.fulljid)
|
log.info("Node set to: %s" % self.boundjid.fulljid)
|
||||||
session_ns = 'urn:ietf:params:xml:ns:xmpp-session'
|
session_ns = 'urn:ietf:params:xml:ns:xmpp-session'
|
||||||
if "{%s}session" % session_ns not in self.features or self.bindfail:
|
if "{%s}session" % session_ns not in self.features or self.bindfail:
|
||||||
logging.debug("Established Session")
|
log.debug("Established Session")
|
||||||
self.sessionstarted = True
|
self.sessionstarted = True
|
||||||
self.session_started_event.set()
|
self.session_started_event.set()
|
||||||
self.event("session_start")
|
self.event("session_start")
|
||||||
|
@ -398,7 +401,7 @@ class ClientXMPP(BaseXMPP):
|
||||||
if self.authenticated and self.bound:
|
if self.authenticated and self.bound:
|
||||||
iq = self.makeIqSet(xml)
|
iq = self.makeIqSet(xml)
|
||||||
response = iq.send()
|
response = iq.send()
|
||||||
logging.debug("Established Session")
|
log.debug("Established Session")
|
||||||
self.sessionstarted = True
|
self.sessionstarted = True
|
||||||
self.session_started_event.set()
|
self.session_started_event.set()
|
||||||
self.event("session_start")
|
self.event("session_start")
|
||||||
|
|
|
@ -15,13 +15,16 @@ import hashlib
|
||||||
|
|
||||||
from sleekxmpp import plugins
|
from sleekxmpp import plugins
|
||||||
from sleekxmpp import stanza
|
from sleekxmpp import stanza
|
||||||
from sleekxmpp.basexmpp import BaseXMPP, SRV_SUPPORT
|
from sleekxmpp.basexmpp import BaseXMPP
|
||||||
from sleekxmpp.xmlstream import XMLStream, RestartStream
|
from sleekxmpp.xmlstream import XMLStream, RestartStream
|
||||||
from sleekxmpp.xmlstream import StanzaBase, ET
|
from sleekxmpp.xmlstream import StanzaBase, ET
|
||||||
from sleekxmpp.xmlstream.matcher import *
|
from sleekxmpp.xmlstream.matcher import *
|
||||||
from sleekxmpp.xmlstream.handler import *
|
from sleekxmpp.xmlstream.handler import *
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ComponentXMPP(BaseXMPP):
|
class ComponentXMPP(BaseXMPP):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -82,7 +85,7 @@ class ComponentXMPP(BaseXMPP):
|
||||||
|
|
||||||
Overrides XMLStream.connect.
|
Overrides XMLStream.connect.
|
||||||
"""
|
"""
|
||||||
logging.debug("Connecting to %s:%s" % (self.server_host,
|
log.debug("Connecting to %s:%s" % (self.server_host,
|
||||||
self.server_port))
|
self.server_port))
|
||||||
return XMLStream.connect(self, self.server_host,
|
return XMLStream.connect(self, self.server_host,
|
||||||
self.server_port)
|
self.server_port)
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
__all__ = ['xep_0004', 'xep_0012', 'xep_0030', 'xep_0033', 'xep_0045',
|
__all__ = ['xep_0004', 'xep_0012', 'xep_0030', 'xep_0033', 'xep_0045',
|
||||||
'xep_0050', 'xep_0078', 'xep_0085', 'xep_0092', 'xep_0199',
|
'xep_0050', 'xep_0085', 'xep_0092', 'xep_0199', 'gmail_notify',
|
||||||
'gmail_notify', 'xep_0060', 'xep_0202']
|
'xep_0060', 'xep_0202']
|
||||||
|
|
|
@ -14,6 +14,9 @@ from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET, JID
|
||||||
from .. stanza.iq import Iq
|
from .. stanza.iq import Iq
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class GmailQuery(ElementBase):
|
class GmailQuery(ElementBase):
|
||||||
namespace = 'google:mail:notify'
|
namespace = 'google:mail:notify'
|
||||||
name = 'query'
|
name = 'query'
|
||||||
|
@ -118,12 +121,12 @@ class gmail_notify(base.base_plugin):
|
||||||
def handle_gmail(self, iq):
|
def handle_gmail(self, iq):
|
||||||
mailbox = iq['mailbox']
|
mailbox = iq['mailbox']
|
||||||
approx = ' approximately' if mailbox['estimated'] else ''
|
approx = ' approximately' if mailbox['estimated'] else ''
|
||||||
logging.info('Gmail: Received%s %s emails' % (approx, mailbox['total-matched']))
|
log.info('Gmail: Received%s %s emails' % (approx, mailbox['total-matched']))
|
||||||
self.last_result_time = mailbox['result-time']
|
self.last_result_time = mailbox['result-time']
|
||||||
self.xmpp.event('gmail_messages', iq)
|
self.xmpp.event('gmail_messages', iq)
|
||||||
|
|
||||||
def handle_new_mail(self, iq):
|
def handle_new_mail(self, iq):
|
||||||
logging.info("Gmail: New emails received!")
|
log.info("Gmail: New emails received!")
|
||||||
self.xmpp.event('gmail_notify')
|
self.xmpp.event('gmail_notify')
|
||||||
self.checkEmail()
|
self.checkEmail()
|
||||||
|
|
||||||
|
@ -135,9 +138,9 @@ class gmail_notify(base.base_plugin):
|
||||||
|
|
||||||
def search(self, query=None, newer=None):
|
def search(self, query=None, newer=None):
|
||||||
if query is None:
|
if query is None:
|
||||||
logging.info("Gmail: Checking for new emails")
|
log.info("Gmail: Checking for new emails")
|
||||||
else:
|
else:
|
||||||
logging.info('Gmail: Searching for emails matching: "%s"' % query)
|
log.info('Gmail: Searching for emails matching: "%s"' % query)
|
||||||
iq = self.xmpp.Iq()
|
iq = self.xmpp.Iq()
|
||||||
iq['type'] = 'get'
|
iq['type'] = 'get'
|
||||||
iq['to'] = self.xmpp.jid
|
iq['to'] = self.xmpp.jid
|
||||||
|
|
|
@ -3,6 +3,10 @@ import logging
|
||||||
from xml.etree import cElementTree as ET
|
from xml.etree import cElementTree as ET
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class jobs(base.base_plugin):
|
class jobs(base.base_plugin):
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.xep = 'pubsubjob'
|
self.xep = 'pubsubjob'
|
||||||
|
@ -40,7 +44,7 @@ class jobs(base.base_plugin):
|
||||||
iq['psstate']['payload'] = state
|
iq['psstate']['payload'] = state
|
||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is None or type(result) == types.BooleanType or result['type'] != 'result':
|
if result is None or type(result) == types.BooleanType or result['type'] != 'result':
|
||||||
logging.error("Unable to change %s:%s to %s" % (node, jobid, state))
|
log.error("Unable to change %s:%s to %s" % (node, jobid, state))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,16 @@
|
||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
from . import base
|
from . import base
|
||||||
import logging
|
import log
|
||||||
from xml.etree import cElementTree as ET
|
from xml.etree import cElementTree as ET
|
||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
#TODO support item groups and results
|
#TODO support item groups and results
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class old_0004(base.base_plugin):
|
class old_0004(base.base_plugin):
|
||||||
|
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
|
@ -22,7 +26,7 @@ class old_0004(base.base_plugin):
|
||||||
def post_init(self):
|
def post_init(self):
|
||||||
base.base_plugin.post_init(self)
|
base.base_plugin.post_init(self)
|
||||||
self.xmpp.plugin['xep_0030'].add_feature('jabber:x:data')
|
self.xmpp.plugin['xep_0030'].add_feature('jabber:x:data')
|
||||||
logging.warning("This implementation of XEP-0004 is deprecated.")
|
log.warning("This implementation of XEP-0004 is deprecated.")
|
||||||
|
|
||||||
def handler_message_xform(self, xml):
|
def handler_message_xform(self, xml):
|
||||||
object = self.handle_form(xml)
|
object = self.handle_form(xml)
|
||||||
|
|
|
@ -16,6 +16,9 @@ from .. stanza.message import Message
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Form(ElementBase):
|
class Form(ElementBase):
|
||||||
namespace = 'jabber:x:data'
|
namespace = 'jabber:x:data'
|
||||||
name = 'x'
|
name = 'x'
|
||||||
|
@ -55,11 +58,11 @@ class Form(ElementBase):
|
||||||
return field
|
return field
|
||||||
|
|
||||||
def getXML(self, type='submit'):
|
def getXML(self, type='submit'):
|
||||||
logging.warning("Form.getXML() is deprecated API compatibility with plugins/old_0004.py")
|
log.warning("Form.getXML() is deprecated API compatibility with plugins/old_0004.py")
|
||||||
return self.xml
|
return self.xml
|
||||||
|
|
||||||
def fromXML(self, xml):
|
def fromXML(self, xml):
|
||||||
logging.warning("Form.fromXML() is deprecated API compatibility with plugins/old_0004.py")
|
log.warning("Form.fromXML() is deprecated API compatibility with plugins/old_0004.py")
|
||||||
n = Form(xml=xml)
|
n = Form(xml=xml)
|
||||||
return n
|
return n
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ from .. xmlstream.matcher.xpath import MatchXPath
|
||||||
from .. xmlstream import ElementBase, ET, JID, register_stanza_plugin
|
from .. xmlstream import ElementBase, ET, JID, register_stanza_plugin
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LastActivity(ElementBase):
|
class LastActivity(ElementBase):
|
||||||
name = 'query'
|
name = 'query'
|
||||||
namespace = 'jabber:iq:last'
|
namespace = 'jabber:iq:last'
|
||||||
|
@ -68,10 +71,10 @@ class xep_0012(base.base_plugin):
|
||||||
|
|
||||||
def handle_last_activity_query(self, iq):
|
def handle_last_activity_query(self, iq):
|
||||||
if iq['type'] == 'get':
|
if iq['type'] == 'get':
|
||||||
logging.debug("Last activity requested by %s" % iq['from'])
|
log.debug("Last activity requested by %s" % iq['from'])
|
||||||
self.xmpp.event('last_activity_request', iq)
|
self.xmpp.event('last_activity_request', iq)
|
||||||
elif iq['type'] == 'result':
|
elif iq['type'] == 'result':
|
||||||
logging.debug("Last activity result from %s" % iq['from'])
|
log.debug("Last activity result from %s" % iq['from'])
|
||||||
self.xmpp.event('last_activity', iq)
|
self.xmpp.event('last_activity', iq)
|
||||||
|
|
||||||
def handle_last_activity(self, iq):
|
def handle_last_activity(self, iq):
|
||||||
|
|
|
@ -13,315 +13,317 @@ from .. xmlstream.matcher.xpath import MatchXPath
|
||||||
from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET, JID
|
from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET, JID
|
||||||
from .. stanza.iq import Iq
|
from .. stanza.iq import Iq
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DiscoInfo(ElementBase):
|
class DiscoInfo(ElementBase):
|
||||||
namespace = 'http://jabber.org/protocol/disco#info'
|
namespace = 'http://jabber.org/protocol/disco#info'
|
||||||
name = 'query'
|
name = 'query'
|
||||||
plugin_attrib = 'disco_info'
|
plugin_attrib = 'disco_info'
|
||||||
interfaces = set(('node', 'features', 'identities'))
|
interfaces = set(('node', 'features', 'identities'))
|
||||||
|
|
||||||
def getFeatures(self):
|
def getFeatures(self):
|
||||||
features = []
|
features = []
|
||||||
featuresXML = self.xml.findall('{%s}feature' % self.namespace)
|
featuresXML = self.xml.findall('{%s}feature' % self.namespace)
|
||||||
for feature in featuresXML:
|
for feature in featuresXML:
|
||||||
features.append(feature.attrib['var'])
|
features.append(feature.attrib['var'])
|
||||||
return features
|
return features
|
||||||
|
|
||||||
def setFeatures(self, features):
|
def setFeatures(self, features):
|
||||||
self.delFeatures()
|
self.delFeatures()
|
||||||
for name in features:
|
for name in features:
|
||||||
self.addFeature(name)
|
self.addFeature(name)
|
||||||
|
|
||||||
def delFeatures(self):
|
def delFeatures(self):
|
||||||
featuresXML = self.xml.findall('{%s}feature' % self.namespace)
|
featuresXML = self.xml.findall('{%s}feature' % self.namespace)
|
||||||
for feature in featuresXML:
|
for feature in featuresXML:
|
||||||
self.xml.remove(feature)
|
self.xml.remove(feature)
|
||||||
|
|
||||||
def addFeature(self, feature):
|
def addFeature(self, feature):
|
||||||
featureXML = ET.Element('{%s}feature' % self.namespace,
|
featureXML = ET.Element('{%s}feature' % self.namespace,
|
||||||
{'var': feature})
|
{'var': feature})
|
||||||
self.xml.append(featureXML)
|
self.xml.append(featureXML)
|
||||||
|
|
||||||
def delFeature(self, feature):
|
def delFeature(self, feature):
|
||||||
featuresXML = self.xml.findall('{%s}feature' % self.namespace)
|
featuresXML = self.xml.findall('{%s}feature' % self.namespace)
|
||||||
for featureXML in featuresXML:
|
for featureXML in featuresXML:
|
||||||
if featureXML.attrib['var'] == feature:
|
if featureXML.attrib['var'] == feature:
|
||||||
self.xml.remove(featureXML)
|
self.xml.remove(featureXML)
|
||||||
|
|
||||||
def getIdentities(self):
|
def getIdentities(self):
|
||||||
ids = []
|
ids = []
|
||||||
idsXML = self.xml.findall('{%s}identity' % self.namespace)
|
idsXML = self.xml.findall('{%s}identity' % self.namespace)
|
||||||
for idXML in idsXML:
|
for idXML in idsXML:
|
||||||
idData = (idXML.attrib['category'],
|
idData = (idXML.attrib['category'],
|
||||||
idXML.attrib['type'],
|
idXML.attrib['type'],
|
||||||
idXML.attrib.get('name', ''))
|
idXML.attrib.get('name', ''))
|
||||||
ids.append(idData)
|
ids.append(idData)
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
def setIdentities(self, ids):
|
def setIdentities(self, ids):
|
||||||
self.delIdentities()
|
self.delIdentities()
|
||||||
for idData in ids:
|
for idData in ids:
|
||||||
self.addIdentity(*idData)
|
self.addIdentity(*idData)
|
||||||
|
|
||||||
def delIdentities(self):
|
def delIdentities(self):
|
||||||
idsXML = self.xml.findall('{%s}identity' % self.namespace)
|
idsXML = self.xml.findall('{%s}identity' % self.namespace)
|
||||||
for idXML in idsXML:
|
for idXML in idsXML:
|
||||||
self.xml.remove(idXML)
|
self.xml.remove(idXML)
|
||||||
|
|
||||||
def addIdentity(self, category, id_type, name=''):
|
def addIdentity(self, category, id_type, name=''):
|
||||||
idXML = ET.Element('{%s}identity' % self.namespace,
|
idXML = ET.Element('{%s}identity' % self.namespace,
|
||||||
{'category': category,
|
{'category': category,
|
||||||
'type': id_type,
|
'type': id_type,
|
||||||
'name': name})
|
'name': name})
|
||||||
self.xml.append(idXML)
|
self.xml.append(idXML)
|
||||||
|
|
||||||
def delIdentity(self, category, id_type, name=''):
|
def delIdentity(self, category, id_type, name=''):
|
||||||
idsXML = self.xml.findall('{%s}identity' % self.namespace)
|
idsXML = self.xml.findall('{%s}identity' % self.namespace)
|
||||||
for idXML in idsXML:
|
for idXML in idsXML:
|
||||||
idData = (idXML.attrib['category'],
|
idData = (idXML.attrib['category'],
|
||||||
idXML.attrib['type'])
|
idXML.attrib['type'])
|
||||||
delId = (category, id_type)
|
delId = (category, id_type)
|
||||||
if idData == delId:
|
if idData == delId:
|
||||||
self.xml.remove(idXML)
|
self.xml.remove(idXML)
|
||||||
|
|
||||||
|
|
||||||
class DiscoItems(ElementBase):
|
class DiscoItems(ElementBase):
|
||||||
namespace = 'http://jabber.org/protocol/disco#items'
|
namespace = 'http://jabber.org/protocol/disco#items'
|
||||||
name = 'query'
|
name = 'query'
|
||||||
plugin_attrib = 'disco_items'
|
plugin_attrib = 'disco_items'
|
||||||
interfaces = set(('node', 'items'))
|
interfaces = set(('node', 'items'))
|
||||||
|
|
||||||
def getItems(self):
|
def getItems(self):
|
||||||
items = []
|
items = []
|
||||||
itemsXML = self.xml.findall('{%s}item' % self.namespace)
|
itemsXML = self.xml.findall('{%s}item' % self.namespace)
|
||||||
for item in itemsXML:
|
for item in itemsXML:
|
||||||
itemData = (item.attrib['jid'],
|
itemData = (item.attrib['jid'],
|
||||||
item.attrib.get('node'),
|
item.attrib.get('node'),
|
||||||
item.attrib.get('name'))
|
item.attrib.get('name'))
|
||||||
items.append(itemData)
|
items.append(itemData)
|
||||||
return items
|
return items
|
||||||
|
|
||||||
def setItems(self, items):
|
def setItems(self, items):
|
||||||
self.delItems()
|
self.delItems()
|
||||||
for item in items:
|
for item in items:
|
||||||
self.addItem(*item)
|
self.addItem(*item)
|
||||||
|
|
||||||
def delItems(self):
|
def delItems(self):
|
||||||
itemsXML = self.xml.findall('{%s}item' % self.namespace)
|
itemsXML = self.xml.findall('{%s}item' % self.namespace)
|
||||||
for item in itemsXML:
|
for item in itemsXML:
|
||||||
self.xml.remove(item)
|
self.xml.remove(item)
|
||||||
|
|
||||||
def addItem(self, jid, node='', name=''):
|
def addItem(self, jid, node='', name=''):
|
||||||
itemXML = ET.Element('{%s}item' % self.namespace, {'jid': jid})
|
itemXML = ET.Element('{%s}item' % self.namespace, {'jid': jid})
|
||||||
if name:
|
if name:
|
||||||
itemXML.attrib['name'] = name
|
itemXML.attrib['name'] = name
|
||||||
if node:
|
if node:
|
||||||
itemXML.attrib['node'] = node
|
itemXML.attrib['node'] = node
|
||||||
self.xml.append(itemXML)
|
self.xml.append(itemXML)
|
||||||
|
|
||||||
def delItem(self, jid, node=''):
|
def delItem(self, jid, node=''):
|
||||||
itemsXML = self.xml.findall('{%s}item' % self.namespace)
|
itemsXML = self.xml.findall('{%s}item' % self.namespace)
|
||||||
for itemXML in itemsXML:
|
for itemXML in itemsXML:
|
||||||
itemData = (itemXML.attrib['jid'],
|
itemData = (itemXML.attrib['jid'],
|
||||||
itemXML.attrib.get('node', ''))
|
itemXML.attrib.get('node', ''))
|
||||||
itemDel = (jid, node)
|
itemDel = (jid, node)
|
||||||
if itemData == itemDel:
|
if itemData == itemDel:
|
||||||
self.xml.remove(itemXML)
|
self.xml.remove(itemXML)
|
||||||
|
|
||||||
|
|
||||||
class DiscoNode(object):
|
class DiscoNode(object):
|
||||||
"""
|
"""
|
||||||
Collection object for grouping info and item information
|
Collection object for grouping info and item information
|
||||||
into nodes.
|
into nodes.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.info = DiscoInfo()
|
self.info = DiscoInfo()
|
||||||
self.items = DiscoItems()
|
self.items = DiscoItems()
|
||||||
|
|
||||||
self.info['node'] = name
|
self.info['node'] = name
|
||||||
self.items['node'] = name
|
self.items['node'] = name
|
||||||
|
|
||||||
# This is a bit like poor man's inheritance, but
|
# This is a bit like poor man's inheritance, but
|
||||||
# to simplify adding information to the node we
|
# to simplify adding information to the node we
|
||||||
# map node functions to either the info or items
|
# map node functions to either the info or items
|
||||||
# stanza objects.
|
# stanza objects.
|
||||||
#
|
#
|
||||||
# We don't want to make DiscoNode inherit from
|
# We don't want to make DiscoNode inherit from
|
||||||
# DiscoInfo and DiscoItems because DiscoNode is
|
# DiscoInfo and DiscoItems because DiscoNode is
|
||||||
# not an actual stanza, and doing so would create
|
# not an actual stanza, and doing so would create
|
||||||
# confusion and potential bugs.
|
# confusion and potential bugs.
|
||||||
|
|
||||||
self._map(self.items, 'items', ['get', 'set', 'del'])
|
self._map(self.items, 'items', ['get', 'set', 'del'])
|
||||||
self._map(self.items, 'item', ['add', 'del'])
|
self._map(self.items, 'item', ['add', 'del'])
|
||||||
self._map(self.info, 'identities', ['get', 'set', 'del'])
|
self._map(self.info, 'identities', ['get', 'set', 'del'])
|
||||||
self._map(self.info, 'identity', ['add', 'del'])
|
self._map(self.info, 'identity', ['add', 'del'])
|
||||||
self._map(self.info, 'features', ['get', 'set', 'del'])
|
self._map(self.info, 'features', ['get', 'set', 'del'])
|
||||||
self._map(self.info, 'feature', ['add', 'del'])
|
self._map(self.info, 'feature', ['add', 'del'])
|
||||||
|
|
||||||
def isEmpty(self):
|
def isEmpty(self):
|
||||||
"""
|
"""
|
||||||
Test if the node contains any information. Useful for
|
Test if the node contains any information. Useful for
|
||||||
determining if a node can be deleted.
|
determining if a node can be deleted.
|
||||||
"""
|
"""
|
||||||
ids = self.getIdentities()
|
ids = self.getIdentities()
|
||||||
features = self.getFeatures()
|
features = self.getFeatures()
|
||||||
items = self.getItems()
|
items = self.getItems()
|
||||||
|
|
||||||
if not ids and not features and not items:
|
if not ids and not features and not items:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _map(self, obj, interface, access):
|
def _map(self, obj, interface, access):
|
||||||
"""
|
"""
|
||||||
Map functions of the form obj.accessInterface
|
Map functions of the form obj.accessInterface
|
||||||
to self.accessInterface for each given access type.
|
to self.accessInterface for each given access type.
|
||||||
"""
|
"""
|
||||||
interface = interface.title()
|
interface = interface.title()
|
||||||
for access_type in access:
|
for access_type in access:
|
||||||
method = access_type + interface
|
method = access_type + interface
|
||||||
if hasattr(obj, method):
|
if hasattr(obj, method):
|
||||||
setattr(self, method, getattr(obj, method))
|
setattr(self, method, getattr(obj, method))
|
||||||
|
|
||||||
|
|
||||||
class xep_0030(base.base_plugin):
|
class xep_0030(base.base_plugin):
|
||||||
"""
|
"""
|
||||||
XEP-0030 Service Discovery
|
XEP-0030 Service Discovery
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.xep = '0030'
|
self.xep = '0030'
|
||||||
self.description = 'Service Discovery'
|
self.description = 'Service Discovery'
|
||||||
|
|
||||||
self.xmpp.registerHandler(
|
self.xmpp.registerHandler(
|
||||||
Callback('Disco Items',
|
Callback('Disco Items',
|
||||||
MatchXPath('{%s}iq/{%s}query' % (self.xmpp.default_ns,
|
MatchXPath('{%s}iq/{%s}query' % (self.xmpp.default_ns,
|
||||||
DiscoItems.namespace)),
|
DiscoItems.namespace)),
|
||||||
self.handle_item_query))
|
self.handle_item_query))
|
||||||
|
|
||||||
self.xmpp.registerHandler(
|
self.xmpp.registerHandler(
|
||||||
Callback('Disco Info',
|
Callback('Disco Info',
|
||||||
MatchXPath('{%s}iq/{%s}query' % (self.xmpp.default_ns,
|
MatchXPath('{%s}iq/{%s}query' % (self.xmpp.default_ns,
|
||||||
DiscoInfo.namespace)),
|
DiscoInfo.namespace)),
|
||||||
self.handle_info_query))
|
self.handle_info_query))
|
||||||
|
|
||||||
registerStanzaPlugin(Iq, DiscoInfo)
|
registerStanzaPlugin(Iq, DiscoInfo)
|
||||||
registerStanzaPlugin(Iq, DiscoItems)
|
registerStanzaPlugin(Iq, DiscoItems)
|
||||||
|
|
||||||
self.xmpp.add_event_handler('disco_items_request', self.handle_disco_items)
|
self.xmpp.add_event_handler('disco_items_request', self.handle_disco_items)
|
||||||
self.xmpp.add_event_handler('disco_info_request', self.handle_disco_info)
|
self.xmpp.add_event_handler('disco_info_request', self.handle_disco_info)
|
||||||
|
|
||||||
self.nodes = {'main': DiscoNode('main')}
|
self.nodes = {'main': DiscoNode('main')}
|
||||||
|
|
||||||
def add_node(self, node):
|
def add_node(self, node):
|
||||||
if node not in self.nodes:
|
if node not in self.nodes:
|
||||||
self.nodes[node] = DiscoNode(node)
|
self.nodes[node] = DiscoNode(node)
|
||||||
|
|
||||||
def del_node(self, node):
|
def del_node(self, node):
|
||||||
if node in self.nodes:
|
if node in self.nodes:
|
||||||
del self.nodes[node]
|
del self.nodes[node]
|
||||||
|
|
||||||
def handle_item_query(self, iq):
|
def handle_item_query(self, iq):
|
||||||
if iq['type'] == 'get':
|
if iq['type'] == 'get':
|
||||||
logging.debug("Items requested by %s" % iq['from'])
|
log.debug("Items requested by %s" % iq['from'])
|
||||||
self.xmpp.event('disco_items_request', iq)
|
self.xmpp.event('disco_items_request', iq)
|
||||||
elif iq['type'] == 'result':
|
elif iq['type'] == 'result':
|
||||||
logging.debug("Items result from %s" % iq['from'])
|
log.debug("Items result from %s" % iq['from'])
|
||||||
self.xmpp.event('disco_items', iq)
|
self.xmpp.event('disco_items', iq)
|
||||||
|
|
||||||
def handle_info_query(self, iq):
|
def handle_info_query(self, iq):
|
||||||
if iq['type'] == 'get':
|
if iq['type'] == 'get':
|
||||||
logging.debug("Info requested by %s" % iq['from'])
|
log.debug("Info requested by %s" % iq['from'])
|
||||||
self.xmpp.event('disco_info_request', iq)
|
self.xmpp.event('disco_info_request', iq)
|
||||||
elif iq['type'] == 'result':
|
elif iq['type'] == 'result':
|
||||||
logging.debug("Info result from %s" % iq['from'])
|
log.debug("Info result from %s" % iq['from'])
|
||||||
self.xmpp.event('disco_info', iq)
|
self.xmpp.event('disco_info', iq)
|
||||||
|
|
||||||
def handle_disco_info(self, iq, forwarded=False):
|
def handle_disco_info(self, iq, forwarded=False):
|
||||||
"""
|
"""
|
||||||
A default handler for disco#info requests. If another
|
A default handler for disco#info requests. If another
|
||||||
handler is registered, this one will defer and not run.
|
handler is registered, this one will defer and not run.
|
||||||
"""
|
"""
|
||||||
handlers = self.xmpp.event_handlers['disco_info_request']
|
if not forwarded and self.xmpp.event_handled('disco_info_request'):
|
||||||
if not forwarded and len(handlers) > 1:
|
return
|
||||||
return
|
|
||||||
|
|
||||||
node_name = iq['disco_info']['node']
|
node_name = iq['disco_info']['node']
|
||||||
if not node_name:
|
if not node_name:
|
||||||
node_name = 'main'
|
node_name = 'main'
|
||||||
|
|
||||||
logging.debug("Using default handler for disco#info on node '%s'." % node_name)
|
log.debug("Using default handler for disco#info on node '%s'." % node_name)
|
||||||
|
|
||||||
if node_name in self.nodes:
|
if node_name in self.nodes:
|
||||||
node = self.nodes[node_name]
|
node = self.nodes[node_name]
|
||||||
iq.reply().setPayload(node.info.xml).send()
|
iq.reply().setPayload(node.info.xml).send()
|
||||||
else:
|
else:
|
||||||
logging.debug("Node %s requested, but does not exist." % node_name)
|
log.debug("Node %s requested, but does not exist." % node_name)
|
||||||
iq.reply().error().setPayload(iq['disco_info'].xml)
|
iq.reply().error().setPayload(iq['disco_info'].xml)
|
||||||
iq['error']['code'] = '404'
|
iq['error']['code'] = '404'
|
||||||
iq['error']['type'] = 'cancel'
|
iq['error']['type'] = 'cancel'
|
||||||
iq['error']['condition'] = 'item-not-found'
|
iq['error']['condition'] = 'item-not-found'
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def handle_disco_items(self, iq, forwarded=False):
|
def handle_disco_items(self, iq, forwarded=False):
|
||||||
"""
|
"""
|
||||||
A default handler for disco#items requests. If another
|
A default handler for disco#items requests. If another
|
||||||
handler is registered, this one will defer and not run.
|
handler is registered, this one will defer and not run.
|
||||||
|
|
||||||
If this handler is called by your own custom handler with
|
If this handler is called by your own custom handler with
|
||||||
forwarded set to True, then it will run as normal.
|
forwarded set to True, then it will run as normal.
|
||||||
"""
|
"""
|
||||||
handlers = self.xmpp.event_handlers['disco_items_request']
|
if not forwarded and self.xmpp.event_handled('disco_items_request'):
|
||||||
if not forwarded and len(handlers) > 1:
|
return
|
||||||
return
|
|
||||||
|
|
||||||
node_name = iq['disco_items']['node']
|
node_name = iq['disco_items']['node']
|
||||||
if not node_name:
|
if not node_name:
|
||||||
node_name = 'main'
|
node_name = 'main'
|
||||||
|
|
||||||
logging.debug("Using default handler for disco#items on node '%s'." % node_name)
|
log.debug("Using default handler for disco#items on node '%s'." % node_name)
|
||||||
|
|
||||||
if node_name in self.nodes:
|
if node_name in self.nodes:
|
||||||
node = self.nodes[node_name]
|
node = self.nodes[node_name]
|
||||||
iq.reply().setPayload(node.items.xml).send()
|
iq.reply().setPayload(node.items.xml).send()
|
||||||
else:
|
else:
|
||||||
logging.debug("Node %s requested, but does not exist." % node_name)
|
log.debug("Node %s requested, but does not exist." % node_name)
|
||||||
iq.reply().error().setPayload(iq['disco_items'].xml)
|
iq.reply().error().setPayload(iq['disco_items'].xml)
|
||||||
iq['error']['code'] = '404'
|
iq['error']['code'] = '404'
|
||||||
iq['error']['type'] = 'cancel'
|
iq['error']['type'] = 'cancel'
|
||||||
iq['error']['condition'] = 'item-not-found'
|
iq['error']['condition'] = 'item-not-found'
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
# Older interface methods for backwards compatibility
|
# Older interface methods for backwards compatibility
|
||||||
|
|
||||||
def getInfo(self, jid, node='', dfrom=None):
|
def getInfo(self, jid, node='', dfrom=None):
|
||||||
iq = self.xmpp.Iq()
|
iq = self.xmpp.Iq()
|
||||||
iq['type'] = 'get'
|
iq['type'] = 'get'
|
||||||
iq['to'] = jid
|
iq['to'] = jid
|
||||||
iq['from'] = dfrom
|
iq['from'] = dfrom
|
||||||
iq['disco_info']['node'] = node
|
iq['disco_info']['node'] = node
|
||||||
return iq.send()
|
return iq.send()
|
||||||
|
|
||||||
def getItems(self, jid, node='', dfrom=None):
|
def getItems(self, jid, node='', dfrom=None):
|
||||||
iq = self.xmpp.Iq()
|
iq = self.xmpp.Iq()
|
||||||
iq['type'] = 'get'
|
iq['type'] = 'get'
|
||||||
iq['to'] = jid
|
iq['to'] = jid
|
||||||
iq['from'] = dfrom
|
iq['from'] = dfrom
|
||||||
iq['disco_items']['node'] = node
|
iq['disco_items']['node'] = node
|
||||||
return iq.send()
|
return iq.send()
|
||||||
|
|
||||||
def add_feature(self, feature, node='main'):
|
def add_feature(self, feature, node='main'):
|
||||||
self.add_node(node)
|
self.add_node(node)
|
||||||
self.nodes[node].addFeature(feature)
|
self.nodes[node].addFeature(feature)
|
||||||
|
|
||||||
def add_identity(self, category='', itype='', name='', node='main'):
|
def add_identity(self, category='', itype='', name='', node='main'):
|
||||||
self.add_node(node)
|
self.add_node(node)
|
||||||
self.nodes[node].addIdentity(category=category,
|
self.nodes[node].addIdentity(category=category,
|
||||||
id_type=itype,
|
id_type=itype,
|
||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
def add_item(self, jid=None, name='', node='main', subnode=''):
|
def add_item(self, jid=None, name='', node='main', subnode=''):
|
||||||
self.add_node(node)
|
self.add_node(node)
|
||||||
self.add_node(subnode)
|
self.add_node(subnode)
|
||||||
if jid is None:
|
if jid is None:
|
||||||
jid = self.xmpp.fulljid
|
jid = self.xmpp.fulljid
|
||||||
self.nodes[node].addItem(jid=jid, name=name, node=subnode)
|
self.nodes[node].addItem(jid=jid, name=name, node=subnode)
|
||||||
|
|
|
@ -15,6 +15,10 @@ from .. xmlstream.handler.callback import Callback
|
||||||
from .. xmlstream.matcher.xpath import MatchXPath
|
from .. xmlstream.matcher.xpath import MatchXPath
|
||||||
from .. xmlstream.matcher.xmlmask import MatchXMLMask
|
from .. xmlstream.matcher.xmlmask import MatchXMLMask
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MUCPresence(ElementBase):
|
class MUCPresence(ElementBase):
|
||||||
name = 'x'
|
name = 'x'
|
||||||
namespace = 'http://jabber.org/protocol/muc#user'
|
namespace = 'http://jabber.org/protocol/muc#user'
|
||||||
|
@ -87,19 +91,19 @@ class MUCPresence(ElementBase):
|
||||||
return self.parent()['from'].bare
|
return self.parent()['from'].bare
|
||||||
|
|
||||||
def setNick(self, value):
|
def setNick(self, value):
|
||||||
logging.warning("Cannot set nick through mucpresence plugin.")
|
log.warning("Cannot set nick through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def setRoom(self, value):
|
def setRoom(self, value):
|
||||||
logging.warning("Cannot set room through mucpresence plugin.")
|
log.warning("Cannot set room through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delNick(self):
|
def delNick(self):
|
||||||
logging.warning("Cannot delete nick through mucpresence plugin.")
|
log.warning("Cannot delete nick through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delRoom(self):
|
def delRoom(self):
|
||||||
logging.warning("Cannot delete room through mucpresence plugin.")
|
log.warning("Cannot delete room through mucpresence plugin.")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
class xep_0045(base.base_plugin):
|
class xep_0045(base.base_plugin):
|
||||||
|
@ -116,6 +120,7 @@ class xep_0045(base.base_plugin):
|
||||||
registerStanzaPlugin(Presence, MUCPresence)
|
registerStanzaPlugin(Presence, MUCPresence)
|
||||||
self.xmpp.registerHandler(Callback('MUCPresence', MatchXMLMask("<presence xmlns='%s' />" % self.xmpp.default_ns), self.handle_groupchat_presence))
|
self.xmpp.registerHandler(Callback('MUCPresence', MatchXMLMask("<presence xmlns='%s' />" % self.xmpp.default_ns), self.handle_groupchat_presence))
|
||||||
self.xmpp.registerHandler(Callback('MUCMessage', MatchXMLMask("<message xmlns='%s' type='groupchat'><body/></message>" % self.xmpp.default_ns), self.handle_groupchat_message))
|
self.xmpp.registerHandler(Callback('MUCMessage', MatchXMLMask("<message xmlns='%s' type='groupchat'><body/></message>" % self.xmpp.default_ns), self.handle_groupchat_message))
|
||||||
|
self.xmpp.registerHandler(Callback('MUCSubject', MatchXMLMask("<message xmlns='%s' type='groupchat'><subject/></message>" % self.xmpp.default_ns), self.handle_groupchat_subject))
|
||||||
|
|
||||||
def handle_groupchat_presence(self, pr):
|
def handle_groupchat_presence(self, pr):
|
||||||
""" Handle a presence in a muc.
|
""" Handle a presence in a muc.
|
||||||
|
@ -135,7 +140,7 @@ class xep_0045(base.base_plugin):
|
||||||
if entry['nick'] not in self.rooms[entry['room']]:
|
if entry['nick'] not in self.rooms[entry['room']]:
|
||||||
got_online = True
|
got_online = True
|
||||||
self.rooms[entry['room']][entry['nick']] = entry
|
self.rooms[entry['room']][entry['nick']] = entry
|
||||||
logging.debug("MUC presence from %s/%s : %s" % (entry['room'],entry['nick'], entry))
|
log.debug("MUC presence from %s/%s : %s" % (entry['room'],entry['nick'], entry))
|
||||||
self.xmpp.event("groupchat_presence", pr)
|
self.xmpp.event("groupchat_presence", pr)
|
||||||
self.xmpp.event("muc::%s::presence" % entry['room'], pr)
|
self.xmpp.event("muc::%s::presence" % entry['room'], pr)
|
||||||
if got_offline:
|
if got_offline:
|
||||||
|
@ -149,6 +154,12 @@ class xep_0045(base.base_plugin):
|
||||||
self.xmpp.event('groupchat_message', msg)
|
self.xmpp.event('groupchat_message', msg)
|
||||||
self.xmpp.event("muc::%s::message" % msg['from'].bare, msg)
|
self.xmpp.event("muc::%s::message" % msg['from'].bare, msg)
|
||||||
|
|
||||||
|
def handle_groupchat_subject(self, msg):
|
||||||
|
""" Handle a message coming from a muc indicating
|
||||||
|
a change of subject (or announcing it when joining the room)
|
||||||
|
"""
|
||||||
|
self.xmpp.event('groupchat_subject', msg)
|
||||||
|
|
||||||
def jidInRoom(self, room, jid):
|
def jidInRoom(self, room, jid):
|
||||||
for nick in self.rooms[room]:
|
for nick in self.rooms[room]:
|
||||||
entry = self.rooms[room][nick]
|
entry = self.rooms[room][nick]
|
||||||
|
|
|
@ -6,6 +6,10 @@ from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET
|
||||||
from . import stanza_pubsub
|
from . import stanza_pubsub
|
||||||
from . xep_0004 import Form
|
from . xep_0004 import Form
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class xep_0060(base.base_plugin):
|
class xep_0060(base.base_plugin):
|
||||||
"""
|
"""
|
||||||
XEP-0060 Publish Subscribe
|
XEP-0060 Publish Subscribe
|
||||||
|
@ -110,14 +114,14 @@ class xep_0060(base.base_plugin):
|
||||||
#self.xmpp.add_handler("<iq id='%s'/>" % id, self.handlerCreateNodeResponse)
|
#self.xmpp.add_handler("<iq id='%s'/>" % id, self.handlerCreateNodeResponse)
|
||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is None or result == False or result['type'] == 'error':
|
if result is None or result == False or result['type'] == 'error':
|
||||||
logging.warning("got error instead of config")
|
log.warning("got error instead of config")
|
||||||
return False
|
return False
|
||||||
if node is not None:
|
if node is not None:
|
||||||
form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}configure/{jabber:x:data}x')
|
form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}configure/{jabber:x:data}x')
|
||||||
else:
|
else:
|
||||||
form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}default/{jabber:x:data}x')
|
form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}default/{jabber:x:data}x')
|
||||||
if not form or form is None:
|
if not form or form is None:
|
||||||
logging.error("No form found.")
|
log.error("No form found.")
|
||||||
return False
|
return False
|
||||||
return Form(xml=form)
|
return Form(xml=form)
|
||||||
|
|
||||||
|
@ -133,7 +137,7 @@ class xep_0060(base.base_plugin):
|
||||||
id = iq['id']
|
id = iq['id']
|
||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is None or result == False or result['type'] == 'error':
|
if result is None or result == False or result['type'] == 'error':
|
||||||
logging.warning("got error instead of config")
|
log.warning("got error instead of config")
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}subscriptions/{http://jabber.org/protocol/pubsub#owner}subscription')
|
results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}subscriptions/{http://jabber.org/protocol/pubsub#owner}subscription')
|
||||||
|
@ -156,7 +160,7 @@ class xep_0060(base.base_plugin):
|
||||||
id = iq['id']
|
id = iq['id']
|
||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is None or result == False or result['type'] == 'error':
|
if result is None or result == False or result['type'] == 'error':
|
||||||
logging.warning("got error instead of config")
|
log.warning("got error instead of config")
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}affiliations/{http://jabber.org/protocol/pubsub#owner}affiliation')
|
results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}affiliations/{http://jabber.org/protocol/pubsub#owner}affiliation')
|
||||||
|
@ -264,7 +268,7 @@ class xep_0060(base.base_plugin):
|
||||||
try:
|
try:
|
||||||
config.field['pubsub#collection'].setValue(parent)
|
config.field['pubsub#collection'].setValue(parent)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logging.warning("pubsub#collection doesn't exist in config, trying to add it")
|
log.warning("pubsub#collection doesn't exist in config, trying to add it")
|
||||||
config.addField('pubsub#collection', value=parent)
|
config.addField('pubsub#collection', value=parent)
|
||||||
if not self.setNodeConfig(jid, child, config):
|
if not self.setNodeConfig(jid, child, config):
|
||||||
return False
|
return False
|
||||||
|
@ -298,7 +302,7 @@ class xep_0060(base.base_plugin):
|
||||||
try:
|
try:
|
||||||
config.field['pubsub#collection'].setValue(parent)
|
config.field['pubsub#collection'].setValue(parent)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logging.warning("pubsub#collection doesn't exist in config, trying to add it")
|
log.warning("pubsub#collection doesn't exist in config, trying to add it")
|
||||||
config.addField('pubsub#collection', value=parent)
|
config.addField('pubsub#collection', value=parent)
|
||||||
if not self.setNodeConfig(jid, child, config):
|
if not self.setNodeConfig(jid, child, config):
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -12,6 +12,9 @@ import hashlib
|
||||||
from . import base
|
from . import base
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class xep_0078(base.base_plugin):
|
class xep_0078(base.base_plugin):
|
||||||
"""
|
"""
|
||||||
XEP-0078 NON-SASL Authentication
|
XEP-0078 NON-SASL Authentication
|
||||||
|
@ -30,7 +33,7 @@ class xep_0078(base.base_plugin):
|
||||||
self.auth()
|
self.auth()
|
||||||
|
|
||||||
def auth(self, xml=None):
|
def auth(self, xml=None):
|
||||||
logging.debug("Starting jabber:iq:auth Authentication")
|
log.debug("Starting jabber:iq:auth Authentication")
|
||||||
auth_request = self.xmpp.makeIqGet()
|
auth_request = self.xmpp.makeIqGet()
|
||||||
auth_request_query = ET.Element('{jabber:iq:auth}query')
|
auth_request_query = ET.Element('{jabber:iq:auth}query')
|
||||||
auth_request.attrib['to'] = self.xmpp.server
|
auth_request.attrib['to'] = self.xmpp.server
|
||||||
|
@ -47,12 +50,12 @@ class xep_0078(base.base_plugin):
|
||||||
query.append(username)
|
query.append(username)
|
||||||
query.append(resource)
|
query.append(resource)
|
||||||
if rquery.find('{jabber:iq:auth}digest') is None:
|
if rquery.find('{jabber:iq:auth}digest') is None:
|
||||||
logging.warning("Authenticating via jabber:iq:auth Plain.")
|
log.warning("Authenticating via jabber:iq:auth Plain.")
|
||||||
password = ET.Element('password')
|
password = ET.Element('password')
|
||||||
password.text = self.xmpp.password
|
password.text = self.xmpp.password
|
||||||
query.append(password)
|
query.append(password)
|
||||||
else:
|
else:
|
||||||
logging.debug("Authenticating via jabber:iq:auth Digest")
|
log.debug("Authenticating via jabber:iq:auth Digest")
|
||||||
digest = ET.Element('digest')
|
digest = ET.Element('digest')
|
||||||
digest.text = hashlib.sha1(b"%s%s" % (self.streamid, self.xmpp.password)).hexdigest()
|
digest.text = hashlib.sha1(b"%s%s" % (self.streamid, self.xmpp.password)).hexdigest()
|
||||||
query.append(digest)
|
query.append(digest)
|
||||||
|
@ -64,6 +67,6 @@ class xep_0078(base.base_plugin):
|
||||||
self.xmpp.sessionstarted = True
|
self.xmpp.sessionstarted = True
|
||||||
self.xmpp.event("session_start")
|
self.xmpp.event("session_start")
|
||||||
else:
|
else:
|
||||||
logging.info("Authentication failed")
|
log.info("Authentication failed")
|
||||||
self.xmpp.disconnect()
|
self.xmpp.disconnect()
|
||||||
self.xmpp.event("failed_auth")
|
self.xmpp.event("failed_auth")
|
||||||
|
|
|
@ -14,6 +14,9 @@ from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET, JID
|
||||||
from .. stanza.message import Message
|
from .. stanza.message import Message
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ChatState(ElementBase):
|
class ChatState(ElementBase):
|
||||||
namespace = 'http://jabber.org/protocol/chatstates'
|
namespace = 'http://jabber.org/protocol/chatstates'
|
||||||
plugin_attrib = 'chat_state'
|
plugin_attrib = 'chat_state'
|
||||||
|
@ -97,5 +100,5 @@ class xep_0085(base.base_plugin):
|
||||||
|
|
||||||
def _handleChatState(self, msg):
|
def _handleChatState(self, msg):
|
||||||
state = msg['chat_state'].name
|
state = msg['chat_state'].name
|
||||||
logging.debug("Chat State: %s, %s" % (state, msg['from'].jid))
|
log.debug("Chat State: %s, %s" % (state, msg['from'].jid))
|
||||||
self.xmpp.event('chatstate_%s' % state, msg)
|
self.xmpp.event('chatstate_%s' % state, msg)
|
||||||
|
|
|
@ -10,50 +10,54 @@ from . import base
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class xep_0199(base.base_plugin):
|
class xep_0199(base.base_plugin):
|
||||||
"""XEP-0199 XMPP Ping"""
|
"""XEP-0199 XMPP Ping"""
|
||||||
|
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.description = "XMPP Ping"
|
self.description = "XMPP Ping"
|
||||||
self.xep = "0199"
|
self.xep = "0199"
|
||||||
self.xmpp.add_handler("<iq type='get' xmlns='%s'><ping xmlns='http://www.xmpp.org/extensions/xep-0199.html#ns'/></iq>" % self.xmpp.default_ns, self.handler_ping, name='XMPP Ping')
|
self.xmpp.add_handler("<iq type='get' xmlns='%s'><ping xmlns='urn:xmpp:ping'/></iq>" % self.xmpp.default_ns, self.handler_ping, name='XMPP Ping')
|
||||||
self.running = False
|
if self.config.get('keepalive', True):
|
||||||
#if self.config.get('keepalive', True):
|
self.xmpp.add_event_handler('session_start', self.handler_pingserver, threaded=True)
|
||||||
#self.xmpp.add_event_handler('session_start', self.handler_pingserver, threaded=True)
|
|
||||||
|
|
||||||
def post_init(self):
|
def post_init(self):
|
||||||
base.base_plugin.post_init(self)
|
base.base_plugin.post_init(self)
|
||||||
self.xmpp.plugin['xep_0030'].add_feature('http://www.xmpp.org/extensions/xep-0199.html#ns')
|
self.xmpp.plugin['xep_0030'].add_feature('urn:xmpp:ping')
|
||||||
|
|
||||||
def handler_pingserver(self, xml):
|
def handler_pingserver(self, xml):
|
||||||
if not self.running:
|
self.xmpp.schedule("xep-0119 ping", float(self.config.get('frequency', 300)), self.scheduled_ping, repeat=True)
|
||||||
time.sleep(self.config.get('frequency', 300))
|
|
||||||
while self.sendPing(self.xmpp.server, self.config.get('timeout', 30)) is not False:
|
|
||||||
time.sleep(self.config.get('frequency', 300))
|
|
||||||
logging.debug("Did not recieve ping back in time. Requesting Reconnect.")
|
|
||||||
self.xmpp.disconnect(reconnect=True)
|
|
||||||
|
|
||||||
def handler_ping(self, xml):
|
def scheduled_ping(self):
|
||||||
iq = self.xmpp.makeIqResult(xml.get('id', 'unknown'))
|
log.debug("pinging...")
|
||||||
iq.attrib['to'] = xml.get('from', self.xmpp.server)
|
if self.sendPing(self.xmpp.server, self.config.get('timeout', 30)) is False:
|
||||||
self.xmpp.send(iq)
|
log.debug("Did not recieve ping back in time. Requesting Reconnect.")
|
||||||
|
self.xmpp.reconnect()
|
||||||
|
|
||||||
def sendPing(self, jid, timeout = 30):
|
def handler_ping(self, xml):
|
||||||
""" sendPing(jid, timeout)
|
iq = self.xmpp.makeIqResult(xml.get('id', 'unknown'))
|
||||||
Sends a ping to the specified jid, returning the time (in seconds)
|
iq.attrib['to'] = xml.get('from', self.xmpp.boundjid.domain)
|
||||||
to receive a reply, or None if no reply is received in timeout seconds.
|
self.xmpp.send(iq)
|
||||||
"""
|
|
||||||
id = self.xmpp.getNewId()
|
def sendPing(self, jid, timeout = 30):
|
||||||
iq = self.xmpp.makeIq(id)
|
""" sendPing(jid, timeout)
|
||||||
iq.attrib['type'] = 'get'
|
Sends a ping to the specified jid, returning the time (in seconds)
|
||||||
iq.attrib['to'] = jid
|
to receive a reply, or None if no reply is received in timeout seconds.
|
||||||
ping = ET.Element('{http://www.xmpp.org/extensions/xep-0199.html#ns}ping')
|
"""
|
||||||
iq.append(ping)
|
id = self.xmpp.getNewId()
|
||||||
startTime = time.clock()
|
iq = self.xmpp.makeIq(id)
|
||||||
#pingresult = self.xmpp.send(iq, self.xmpp.makeIq(id), timeout)
|
iq.attrib['type'] = 'get'
|
||||||
pingresult = iq.send()
|
iq.attrib['to'] = jid
|
||||||
endTime = time.clock()
|
ping = ET.Element('{urn:xmpp:ping}ping')
|
||||||
if pingresult == False:
|
iq.append(ping)
|
||||||
#self.xmpp.disconnect(reconnect=True)
|
startTime = time.clock()
|
||||||
return False
|
#pingresult = self.xmpp.send(iq, self.xmpp.makeIq(id), timeout)
|
||||||
return endTime - startTime
|
pingresult = iq.send()
|
||||||
|
endTime = time.clock()
|
||||||
|
if pingresult == False:
|
||||||
|
#self.xmpp.disconnect(reconnect=True)
|
||||||
|
return False
|
||||||
|
return endTime - startTime
|
||||||
|
|
|
@ -17,6 +17,9 @@ from .. xmlstream.matcher.xpath import MatchXPath
|
||||||
from .. xmlstream import ElementBase, ET, JID, register_stanza_plugin
|
from .. xmlstream import ElementBase, ET, JID, register_stanza_plugin
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EntityTime(ElementBase):
|
class EntityTime(ElementBase):
|
||||||
name = 'time'
|
name = 'time'
|
||||||
namespace = 'urn:xmpp:time'
|
namespace = 'urn:xmpp:time'
|
||||||
|
@ -84,10 +87,10 @@ class xep_0202(base.base_plugin):
|
||||||
|
|
||||||
def handle_entity_time_query(self, iq):
|
def handle_entity_time_query(self, iq):
|
||||||
if iq['type'] == 'get':
|
if iq['type'] == 'get':
|
||||||
logging.debug("Entity time requested by %s" % iq['from'])
|
log.debug("Entity time requested by %s" % iq['from'])
|
||||||
self.xmpp.event('entity_time_request', iq)
|
self.xmpp.event('entity_time_request', iq)
|
||||||
elif iq['type'] == 'result':
|
elif iq['type'] == 'result':
|
||||||
logging.debug("Entity time result from %s" % iq['from'])
|
log.debug("Entity time result from %s" % iq['from'])
|
||||||
self.xmpp.event('entity_time', iq)
|
self.xmpp.event('entity_time', iq)
|
||||||
|
|
||||||
def handle_entity_time(self, iq):
|
def handle_entity_time(self, iq):
|
||||||
|
|
|
@ -442,7 +442,6 @@ class RosterItem(object):
|
||||||
key -- The state field to modify.
|
key -- The state field to modify.
|
||||||
value -- The new value of the state field.
|
value -- The new value of the state field.
|
||||||
"""
|
"""
|
||||||
print "%s: %s" % (key, value)
|
|
||||||
if key in self._state:
|
if key in self._state:
|
||||||
if key in ['name', 'subscription', 'groups']:
|
if key in ['name', 'subscription', 'groups']:
|
||||||
self._state[key] = value
|
self._state[key] = value
|
||||||
|
|
|
@ -15,6 +15,9 @@ from sleekxmpp.stanza import Error
|
||||||
from sleekxmpp.xmlstream import ET, StanzaBase, register_stanza_plugin
|
from sleekxmpp.xmlstream import ET, StanzaBase, register_stanza_plugin
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RootStanza(StanzaBase):
|
class RootStanza(StanzaBase):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -58,7 +61,7 @@ class RootStanza(StanzaBase):
|
||||||
self['error']['text'] = "SleekXMPP got into trouble."
|
self['error']['text'] = "SleekXMPP got into trouble."
|
||||||
else:
|
else:
|
||||||
self['error']['text'] = traceback.format_tb(e.__traceback__)
|
self['error']['text'] = traceback.format_tb(e.__traceback__)
|
||||||
logging.exception('Error handling {%s}%s stanza' %
|
log.exception('Error handling {%s}%s stanza' %
|
||||||
(self.namespace, self.name))
|
(self.namespace, self.name))
|
||||||
self.send()
|
self.send()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
SleekXMPP: The Sleek XMPP Library
|
SleekXMPP: The Sleek XMPP Library
|
||||||
Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
|
Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
|
||||||
This file is part of SleekXMPP.
|
This file is part of SleekXMPP.
|
||||||
|
@ -27,27 +26,29 @@ class SleekTest(unittest.TestCase):
|
||||||
Message -- Create a Message stanza object.
|
Message -- Create a Message stanza object.
|
||||||
Iq -- Create an Iq stanza object.
|
Iq -- Create an Iq stanza object.
|
||||||
Presence -- Create a Presence stanza object.
|
Presence -- Create a Presence stanza object.
|
||||||
check_stanza -- Compare a generic stanza against an XML string.
|
check_jid -- Check a JID and its component parts.
|
||||||
check_message -- Compare a Message stanza against an XML string.
|
check -- Compare a stanza against an XML string.
|
||||||
check_iq -- Compare an Iq stanza against an XML string.
|
|
||||||
check_presence -- Compare a Presence stanza against an XML string.
|
|
||||||
stream_start -- Initialize a dummy XMPP client.
|
stream_start -- Initialize a dummy XMPP client.
|
||||||
stream_recv -- Queue data for XMPP client to receive.
|
|
||||||
stream_make_header -- Create a stream header.
|
|
||||||
stream_send_header -- Check that the given header has been sent.
|
|
||||||
stream_send_message -- Check that the XMPP client sent the given
|
|
||||||
Message stanza.
|
|
||||||
stream_send_iq -- Check that the XMPP client sent the given
|
|
||||||
Iq stanza.
|
|
||||||
stream_send_presence -- Check thatt the XMPP client sent the given
|
|
||||||
Presence stanza.
|
|
||||||
stream_send_stanza -- Check that the XMPP client sent the given
|
|
||||||
generic stanza.
|
|
||||||
stream_close -- Disconnect the XMPP client.
|
stream_close -- Disconnect the XMPP client.
|
||||||
|
make_header -- Create a stream header.
|
||||||
|
send_header -- Check that the given header has been sent.
|
||||||
|
send_feature -- Send a raw XML element.
|
||||||
|
send -- Check that the XMPP client sent the given
|
||||||
|
generic stanza.
|
||||||
|
recv -- Queue data for XMPP client to receive, or
|
||||||
|
verify the data that was received from a
|
||||||
|
live connection.
|
||||||
|
recv_header -- Check that a given stream header
|
||||||
|
was received.
|
||||||
|
recv_feature -- Check that a given, raw XML element
|
||||||
|
was recveived.
|
||||||
fix_namespaces -- Add top-level namespace to an XML object.
|
fix_namespaces -- Add top-level namespace to an XML object.
|
||||||
compare -- Compare XML objects against each other.
|
compare -- Compare XML objects against each other.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def parse_xml(self, xml_string):
|
def parse_xml(self, xml_string):
|
||||||
try:
|
try:
|
||||||
xml = ET.fromstring(xml_string)
|
xml = ET.fromstring(xml_string)
|
||||||
|
@ -103,10 +104,8 @@ class SleekTest(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
return Presence(None, *args, **kwargs)
|
return Presence(None, *args, **kwargs)
|
||||||
|
|
||||||
|
def check_jid(self, jid, user=None, domain=None, resource=None,
|
||||||
|
bare=None, full=None, string=None):
|
||||||
def check_JID(self, jid, user=None, domain=None, resource=None,
|
|
||||||
bare=None, full=None, string=None):
|
|
||||||
"""
|
"""
|
||||||
Verify the components of a JID.
|
Verify the components of a JID.
|
||||||
|
|
||||||
|
@ -142,7 +141,6 @@ class SleekTest(unittest.TestCase):
|
||||||
afrom=None, ato=None, pending_out=None, pending_in=None,
|
afrom=None, ato=None, pending_out=None, pending_in=None,
|
||||||
groups=None):
|
groups=None):
|
||||||
roster = self.xmpp.roster[owner][jid]
|
roster = self.xmpp.roster[owner][jid]
|
||||||
print roster._state
|
|
||||||
if name is not None:
|
if name is not None:
|
||||||
self.assertEqual(roster['name'], name,
|
self.assertEqual(roster['name'], name,
|
||||||
"Incorrect name value: %s" % roster['name'])
|
"Incorrect name value: %s" % roster['name'])
|
||||||
|
@ -168,8 +166,8 @@ class SleekTest(unittest.TestCase):
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Methods for comparing stanza objects to XML strings
|
# Methods for comparing stanza objects to XML strings
|
||||||
|
|
||||||
def check_stanza(self, stanza_class, stanza, xml_string,
|
def check(self, stanza, xml_string,
|
||||||
defaults=None, use_values=True):
|
defaults=None, use_values=True):
|
||||||
"""
|
"""
|
||||||
Create and compare several stanza objects to a correct XML string.
|
Create and compare several stanza objects to a correct XML string.
|
||||||
|
|
||||||
|
@ -188,7 +186,6 @@ class SleekTest(unittest.TestCase):
|
||||||
must take into account any extra elements that are included by default.
|
must take into account any extra elements that are included by default.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
stanza_class -- The class of the stanza being tested.
|
|
||||||
stanza -- The stanza object to test.
|
stanza -- The stanza object to test.
|
||||||
xml_string -- A string version of the correct XML expected.
|
xml_string -- A string version of the correct XML expected.
|
||||||
defaults -- A list of stanza interfaces that have default
|
defaults -- A list of stanza interfaces that have default
|
||||||
|
@ -199,6 +196,7 @@ class SleekTest(unittest.TestCase):
|
||||||
setStanzaValues() should be used. Defaults to
|
setStanzaValues() should be used. Defaults to
|
||||||
True.
|
True.
|
||||||
"""
|
"""
|
||||||
|
stanza_class = stanza.__class__
|
||||||
xml = self.parse_xml(xml_string)
|
xml = self.parse_xml(xml_string)
|
||||||
|
|
||||||
# Ensure that top level namespaces are used, even if they
|
# Ensure that top level namespaces are used, even if they
|
||||||
|
@ -215,7 +213,11 @@ class SleekTest(unittest.TestCase):
|
||||||
# so that they will compare correctly.
|
# so that they will compare correctly.
|
||||||
default_stanza = stanza_class()
|
default_stanza = stanza_class()
|
||||||
if defaults is None:
|
if defaults is None:
|
||||||
defaults = []
|
known_defaults = {
|
||||||
|
Message: ['type'],
|
||||||
|
Presence: ['priority']
|
||||||
|
}
|
||||||
|
defaults = known_defaults.get(stanza_class, [])
|
||||||
for interface in defaults:
|
for interface in defaults:
|
||||||
stanza[interface] = stanza[interface]
|
stanza[interface] = stanza[interface]
|
||||||
stanza2[interface] = stanza2[interface]
|
stanza2[interface] = stanza2[interface]
|
||||||
|
@ -246,62 +248,6 @@ class SleekTest(unittest.TestCase):
|
||||||
|
|
||||||
self.failUnless(result, debug)
|
self.failUnless(result, debug)
|
||||||
|
|
||||||
def check_message(self, msg, xml_string, use_values=True):
|
|
||||||
"""
|
|
||||||
Create and compare several message stanza objects to a
|
|
||||||
correct XML string.
|
|
||||||
|
|
||||||
If use_values is False, the test using getStanzaValues() and
|
|
||||||
setStanzaValues() will not be used.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
msg -- The Message stanza object to check.
|
|
||||||
xml_string -- The XML contents to compare against.
|
|
||||||
use_values -- Indicates if the test using getStanzaValues
|
|
||||||
and setStanzaValues should be used. Defaults
|
|
||||||
to True.
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.check_stanza(Message, msg, xml_string,
|
|
||||||
defaults=['type'],
|
|
||||||
use_values=use_values)
|
|
||||||
|
|
||||||
def check_iq(self, iq, xml_string, use_values=True):
|
|
||||||
"""
|
|
||||||
Create and compare several iq stanza objects to a
|
|
||||||
correct XML string.
|
|
||||||
|
|
||||||
If use_values is False, the test using getStanzaValues() and
|
|
||||||
setStanzaValues() will not be used.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
iq -- The Iq stanza object to check.
|
|
||||||
xml_string -- The XML contents to compare against.
|
|
||||||
use_values -- Indicates if the test using getStanzaValues
|
|
||||||
and setStanzaValues should be used. Defaults
|
|
||||||
to True.
|
|
||||||
"""
|
|
||||||
return self.check_stanza(Iq, iq, xml_string, use_values=use_values)
|
|
||||||
|
|
||||||
def check_presence(self, pres, xml_string, use_values=True):
|
|
||||||
"""
|
|
||||||
Create and compare several presence stanza objects to a
|
|
||||||
correct XML string.
|
|
||||||
|
|
||||||
If use_values is False, the test using getStanzaValues() and
|
|
||||||
setStanzaValues() will not be used.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
iq -- The Iq stanza object to check.
|
|
||||||
xml_string -- The XML contents to compare against.
|
|
||||||
use_values -- Indicates if the test using getStanzaValues
|
|
||||||
and setStanzaValues should be used. Defaults
|
|
||||||
to True.
|
|
||||||
"""
|
|
||||||
return self.check_stanza(Presence, pres, xml_string,
|
|
||||||
defaults=['priority'],
|
|
||||||
use_values=use_values)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Methods for simulating stanza streams.
|
# Methods for simulating stanza streams.
|
||||||
|
|
||||||
|
@ -329,7 +275,6 @@ class SleekTest(unittest.TestCase):
|
||||||
port -- The port to use when connecting to the server.
|
port -- The port to use when connecting to the server.
|
||||||
Defaults to 5222.
|
Defaults to 5222.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if mode == 'client':
|
if mode == 'client':
|
||||||
self.xmpp = ClientXMPP(jid, password)
|
self.xmpp = ClientXMPP(jid, password)
|
||||||
elif mode == 'component':
|
elif mode == 'component':
|
||||||
|
@ -364,13 +309,13 @@ class SleekTest(unittest.TestCase):
|
||||||
if mode == 'component':
|
if mode == 'component':
|
||||||
self.xmpp.socket.next_sent(timeout=1)
|
self.xmpp.socket.next_sent(timeout=1)
|
||||||
|
|
||||||
def stream_make_header(self, sto='',
|
def make_header(self, sto='',
|
||||||
sfrom='',
|
sfrom='',
|
||||||
sid='',
|
sid='',
|
||||||
stream_ns="http://etherx.jabber.org/streams",
|
stream_ns="http://etherx.jabber.org/streams",
|
||||||
default_ns="jabber:client",
|
default_ns="jabber:client",
|
||||||
version="1.0",
|
version="1.0",
|
||||||
xml_header=True):
|
xml_header=True):
|
||||||
"""
|
"""
|
||||||
Create a stream header to be received by the test XMPP agent.
|
Create a stream header to be received by the test XMPP agent.
|
||||||
|
|
||||||
|
@ -401,8 +346,8 @@ class SleekTest(unittest.TestCase):
|
||||||
parts.append('xmlns="%s"' % default_ns)
|
parts.append('xmlns="%s"' % default_ns)
|
||||||
return header % ' '.join(parts)
|
return header % ' '.join(parts)
|
||||||
|
|
||||||
def stream_recv(self, data, stanza_class=StanzaBase, defaults=[],
|
def recv(self, data, stanza_class=StanzaBase, defaults=[],
|
||||||
use_values=True, timeout=1):
|
use_values=True, timeout=1):
|
||||||
"""
|
"""
|
||||||
Pass data to the dummy XMPP client as if it came from an XMPP server.
|
Pass data to the dummy XMPP client as if it came from an XMPP server.
|
||||||
|
|
||||||
|
@ -429,7 +374,7 @@ class SleekTest(unittest.TestCase):
|
||||||
if recv_data is None:
|
if recv_data is None:
|
||||||
return False
|
return False
|
||||||
stanza = stanza_class(xml=self.parse_xml(recv_data))
|
stanza = stanza_class(xml=self.parse_xml(recv_data))
|
||||||
return self.check_stanza(stanza_class, stanza, data,
|
return self.check(stanza_class, stanza, data,
|
||||||
defaults=defaults,
|
defaults=defaults,
|
||||||
use_values=use_values)
|
use_values=use_values)
|
||||||
else:
|
else:
|
||||||
|
@ -437,14 +382,14 @@ class SleekTest(unittest.TestCase):
|
||||||
data = str(data)
|
data = str(data)
|
||||||
self.xmpp.socket.recv_data(data)
|
self.xmpp.socket.recv_data(data)
|
||||||
|
|
||||||
def stream_recv_header(self, sto='',
|
def recv_header(self, sto='',
|
||||||
sfrom='',
|
sfrom='',
|
||||||
sid='',
|
sid='',
|
||||||
stream_ns="http://etherx.jabber.org/streams",
|
stream_ns="http://etherx.jabber.org/streams",
|
||||||
default_ns="jabber:client",
|
default_ns="jabber:client",
|
||||||
version="1.0",
|
version="1.0",
|
||||||
xml_header=False,
|
xml_header=False,
|
||||||
timeout=1):
|
timeout=1):
|
||||||
"""
|
"""
|
||||||
Check that a given stream header was received.
|
Check that a given stream header was received.
|
||||||
|
|
||||||
|
@ -460,11 +405,11 @@ class SleekTest(unittest.TestCase):
|
||||||
timeout -- Length of time to wait in seconds for a
|
timeout -- Length of time to wait in seconds for a
|
||||||
response.
|
response.
|
||||||
"""
|
"""
|
||||||
header = self.stream_make_header(sto, sfrom, sid,
|
header = self.make_header(sto, sfrom, sid,
|
||||||
stream_ns=stream_ns,
|
stream_ns=stream_ns,
|
||||||
default_ns=default_ns,
|
default_ns=default_ns,
|
||||||
version=version,
|
version=version,
|
||||||
xml_header=xml_header)
|
xml_header=xml_header)
|
||||||
recv_header = self.xmpp.socket.next_recv(timeout)
|
recv_header = self.xmpp.socket.next_recv(timeout)
|
||||||
if recv_header is None:
|
if recv_header is None:
|
||||||
raise ValueError("Socket did not return data.")
|
raise ValueError("Socket did not return data.")
|
||||||
|
@ -504,9 +449,8 @@ class SleekTest(unittest.TestCase):
|
||||||
"Stream headers do not match:\nDesired:\n%s\nReceived:\n%s" % (
|
"Stream headers do not match:\nDesired:\n%s\nReceived:\n%s" % (
|
||||||
'%s %s' % (xml.tag, xml.attrib),
|
'%s %s' % (xml.tag, xml.attrib),
|
||||||
'%s %s' % (recv_xml.tag, recv_xml.attrib)))
|
'%s %s' % (recv_xml.tag, recv_xml.attrib)))
|
||||||
#tostring(xml), tostring(recv_xml)))#recv_header))
|
|
||||||
|
|
||||||
def stream_recv_feature(self, data, use_values=True, timeout=1):
|
def recv_feature(self, data, use_values=True, timeout=1):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
if self.xmpp.socket.is_live:
|
if self.xmpp.socket.is_live:
|
||||||
|
@ -526,39 +470,14 @@ class SleekTest(unittest.TestCase):
|
||||||
data = str(data)
|
data = str(data)
|
||||||
self.xmpp.socket.recv_data(data)
|
self.xmpp.socket.recv_data(data)
|
||||||
|
|
||||||
|
def send_header(self, sto='',
|
||||||
|
sfrom='',
|
||||||
def stream_recv_message(self, data, use_values=True, timeout=1):
|
sid='',
|
||||||
"""
|
stream_ns="http://etherx.jabber.org/streams",
|
||||||
"""
|
default_ns="jabber:client",
|
||||||
return self.stream_recv(data, stanza_class=Message,
|
version="1.0",
|
||||||
defaults=['type'],
|
xml_header=False,
|
||||||
use_values=use_values,
|
timeout=1):
|
||||||
timeout=timeout)
|
|
||||||
|
|
||||||
def stream_recv_iq(self, data, use_values=True, timeout=1):
|
|
||||||
"""
|
|
||||||
"""
|
|
||||||
return self.stream_recv(data, stanza_class=Iq,
|
|
||||||
use_values=use_values,
|
|
||||||
timeout=timeout)
|
|
||||||
|
|
||||||
def stream_recv_presence(self, data, use_values=True, timeout=1):
|
|
||||||
"""
|
|
||||||
"""
|
|
||||||
return self.stream_recv(data, stanza_class=Presence,
|
|
||||||
defaults=['priority'],
|
|
||||||
use_values=use_values,
|
|
||||||
timeout=timeout)
|
|
||||||
|
|
||||||
def stream_send_header(self, sto='',
|
|
||||||
sfrom='',
|
|
||||||
sid='',
|
|
||||||
stream_ns="http://etherx.jabber.org/streams",
|
|
||||||
default_ns="jabber:client",
|
|
||||||
version="1.0",
|
|
||||||
xml_header=False,
|
|
||||||
timeout=1):
|
|
||||||
"""
|
"""
|
||||||
Check that a given stream header was sent.
|
Check that a given stream header was sent.
|
||||||
|
|
||||||
|
@ -574,11 +493,11 @@ class SleekTest(unittest.TestCase):
|
||||||
timeout -- Length of time to wait in seconds for a
|
timeout -- Length of time to wait in seconds for a
|
||||||
response.
|
response.
|
||||||
"""
|
"""
|
||||||
header = self.stream_make_header(sto, sfrom, sid,
|
header = self.make_header(sto, sfrom, sid,
|
||||||
stream_ns=stream_ns,
|
stream_ns=stream_ns,
|
||||||
default_ns=default_ns,
|
default_ns=default_ns,
|
||||||
version=version,
|
version=version,
|
||||||
xml_header=xml_header)
|
xml_header=xml_header)
|
||||||
sent_header = self.xmpp.socket.next_sent(timeout)
|
sent_header = self.xmpp.socket.next_sent(timeout)
|
||||||
if sent_header is None:
|
if sent_header is None:
|
||||||
raise ValueError("Socket did not return data.")
|
raise ValueError("Socket did not return data.")
|
||||||
|
@ -596,7 +515,7 @@ class SleekTest(unittest.TestCase):
|
||||||
"Stream headers do not match:\nDesired:\n%s\nSent:\n%s" % (
|
"Stream headers do not match:\nDesired:\n%s\nSent:\n%s" % (
|
||||||
header, sent_header))
|
header, sent_header))
|
||||||
|
|
||||||
def stream_send_feature(self, data, use_values=True, timeout=1):
|
def send_feature(self, data, use_values=True, timeout=1):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
sent_data = self.xmpp.socket.next_sent(timeout)
|
sent_data = self.xmpp.socket.next_sent(timeout)
|
||||||
|
@ -608,13 +527,13 @@ class SleekTest(unittest.TestCase):
|
||||||
"Features do not match.\nDesired:\n%s\nSent:\n%s" % (
|
"Features do not match.\nDesired:\n%s\nSent:\n%s" % (
|
||||||
tostring(xml), tostring(sent_xml)))
|
tostring(xml), tostring(sent_xml)))
|
||||||
|
|
||||||
def stream_send_stanza(self, stanza_class, data, defaults=None,
|
def send(self, data, defaults=None,
|
||||||
use_values=True, timeout=.1):
|
use_values=True, timeout=.1):
|
||||||
"""
|
"""
|
||||||
Check that the XMPP client sent the given stanza XML.
|
Check that the XMPP client sent the given stanza XML.
|
||||||
|
|
||||||
Extracts the next sent stanza and compares it with the given
|
Extracts the next sent stanza and compares it with the given
|
||||||
XML using check_stanza.
|
XML using check.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
stanza_class -- The class of the sent stanza object.
|
stanza_class -- The class of the sent stanza object.
|
||||||
|
@ -626,70 +545,15 @@ class SleekTest(unittest.TestCase):
|
||||||
timeout -- Time in seconds to wait for a stanza before
|
timeout -- Time in seconds to wait for a stanza before
|
||||||
failing the check.
|
failing the check.
|
||||||
"""
|
"""
|
||||||
if isintance(data, str):
|
if isinstance(data, str):
|
||||||
data = stanza_class(xml=self.parse_xml(data))
|
xml = self.parse_xml(data)
|
||||||
|
self.fix_namespaces(xml, 'jabber:client')
|
||||||
|
data = self.xmpp._build_stanza(xml, 'jabber:client')
|
||||||
sent = self.xmpp.socket.next_sent(timeout)
|
sent = self.xmpp.socket.next_sent(timeout)
|
||||||
self.check_stanza(stanza_class, data, sent,
|
self.check(data, sent,
|
||||||
defaults=defaults,
|
defaults=defaults,
|
||||||
use_values=use_values)
|
use_values=use_values)
|
||||||
|
|
||||||
def stream_send_message(self, data, use_values=True, timeout=.1):
|
|
||||||
"""
|
|
||||||
Check that the XMPP client sent the given stanza XML.
|
|
||||||
|
|
||||||
Extracts the next sent stanza and compares it with the given
|
|
||||||
XML using check_message.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
data -- The XML string of the expected Message stanza,
|
|
||||||
or an equivalent stanza object.
|
|
||||||
use_values -- Modifies the type of tests used by check_message.
|
|
||||||
timeout -- Time in seconds to wait for a stanza before
|
|
||||||
failing the check.
|
|
||||||
"""
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = self.Message(xml=self.parse_xml(data))
|
|
||||||
sent = self.xmpp.socket.next_sent(timeout)
|
|
||||||
self.check_message(data, sent, use_values)
|
|
||||||
|
|
||||||
def stream_send_iq(self, data, use_values=True, timeout=.1):
|
|
||||||
"""
|
|
||||||
Check that the XMPP client sent the given stanza XML.
|
|
||||||
|
|
||||||
Extracts the next sent stanza and compares it with the given
|
|
||||||
XML using check_iq.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
data -- The XML string of the expected Iq stanza,
|
|
||||||
or an equivalent stanza object.
|
|
||||||
use_values -- Modifies the type of tests used by check_iq.
|
|
||||||
timeout -- Time in seconds to wait for a stanza before
|
|
||||||
failing the check.
|
|
||||||
"""
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = self.Iq(xml=self.parse_xml(data))
|
|
||||||
sent = self.xmpp.socket.next_sent(timeout)
|
|
||||||
self.check_iq(data, sent, use_values)
|
|
||||||
|
|
||||||
def stream_send_presence(self, data, use_values=True, timeout=.1):
|
|
||||||
"""
|
|
||||||
Check that the XMPP client sent the given stanza XML.
|
|
||||||
|
|
||||||
Extracts the next sent stanza and compares it with the given
|
|
||||||
XML using check_presence.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
data -- The XML string of the expected Presence stanza,
|
|
||||||
or an equivalent stanza object.
|
|
||||||
use_values -- Modifies the type of tests used by check_presence.
|
|
||||||
timeout -- Time in seconds to wait for a stanza before
|
|
||||||
failing the check.
|
|
||||||
"""
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = self.Presence(xml=self.parse_xml(data))
|
|
||||||
sent = self.xmpp.socket.next_sent(timeout)
|
|
||||||
self.check_presence(data, sent, use_values)
|
|
||||||
|
|
||||||
def stream_close(self):
|
def stream_close(self):
|
||||||
"""
|
"""
|
||||||
Disconnect the dummy XMPP client.
|
Disconnect the dummy XMPP client.
|
||||||
|
|
4
sleekxmpp/thirdparty/statemachine.py
vendored
4
sleekxmpp/thirdparty/statemachine.py
vendored
|
@ -86,7 +86,7 @@ class StateMachine(object):
|
||||||
while not self.lock.acquire(False):
|
while not self.lock.acquire(False):
|
||||||
time.sleep(.001)
|
time.sleep(.001)
|
||||||
if (start + wait - time.time()) <= 0.0:
|
if (start + wait - time.time()) <= 0.0:
|
||||||
logging.debug("Could not acquire lock")
|
log.debug("Could not acquire lock")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
while not self.__current_state in from_states:
|
while not self.__current_state in from_states:
|
||||||
|
@ -95,7 +95,7 @@ class StateMachine(object):
|
||||||
if remainder > 0:
|
if remainder > 0:
|
||||||
self.notifier.wait(remainder)
|
self.notifier.wait(remainder)
|
||||||
else:
|
else:
|
||||||
logging.debug("State was not ready")
|
log.debug("State was not ready")
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ from sleekxmpp.xmlstream import StanzaBase, RESPONSE_TIMEOUT
|
||||||
from sleekxmpp.xmlstream.handler.base import BaseHandler
|
from sleekxmpp.xmlstream.handler.base import BaseHandler
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Waiter(BaseHandler):
|
class Waiter(BaseHandler):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -85,7 +88,7 @@ class Waiter(BaseHandler):
|
||||||
stanza = self._payload.get(True, timeout)
|
stanza = self._payload.get(True, timeout)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
stanza = False
|
stanza = False
|
||||||
logging.warning("Timed out waiting for %s" % self.name)
|
log.warning("Timed out waiting for %s" % self.name)
|
||||||
self.stream.removeHandler(self.name)
|
self.stream.removeHandler(self.name)
|
||||||
return stanza
|
return stanza
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from xml.parsers.expat import ExpatError
|
from xml.parsers.expat import ExpatError
|
||||||
|
|
||||||
from sleekxmpp.xmlstream.stanzabase import ET
|
from sleekxmpp.xmlstream.stanzabase import ET
|
||||||
|
@ -18,6 +20,9 @@ from sleekxmpp.xmlstream.matcher.base import MatcherBase
|
||||||
IGNORE_NS = False
|
IGNORE_NS = False
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MatchXMLMask(MatcherBase):
|
class MatchXMLMask(MatcherBase):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -97,8 +102,7 @@ class MatchXMLMask(MatcherBase):
|
||||||
try:
|
try:
|
||||||
mask = ET.fromstring(mask)
|
mask = ET.fromstring(mask)
|
||||||
except ExpatError:
|
except ExpatError:
|
||||||
logging.log(logging.WARNING,
|
log.warning("Expat error: %s\nIn parsing: %s" % ('', mask))
|
||||||
"Expat error: %s\nIn parsing: %s" % ('', mask))
|
|
||||||
|
|
||||||
if not use_ns:
|
if not use_ns:
|
||||||
# Compare the element without using namespaces.
|
# Compare the element without using namespaces.
|
||||||
|
|
|
@ -15,6 +15,9 @@ except ImportError:
|
||||||
import Queue as queue
|
import Queue as queue
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Task(object):
|
class Task(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -146,6 +149,8 @@ class Scheduler(object):
|
||||||
if wait <= 0.0:
|
if wait <= 0.0:
|
||||||
newtask = self.addq.get(False)
|
newtask = self.addq.get(False)
|
||||||
else:
|
else:
|
||||||
|
if wait >= 3.0:
|
||||||
|
wait = 3.0
|
||||||
newtask = self.addq.get(True, wait)
|
newtask = self.addq.get(True, wait)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
cleanup = []
|
cleanup = []
|
||||||
|
@ -168,13 +173,13 @@ class Scheduler(object):
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
self.run = False
|
self.run = False
|
||||||
if self.parentstop is not None:
|
if self.parentstop is not None:
|
||||||
logging.debug("stopping parent")
|
log.debug("stopping parent")
|
||||||
self.parentstop.set()
|
self.parentstop.set()
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
self.run = False
|
self.run = False
|
||||||
if self.parentstop is not None:
|
if self.parentstop is not None:
|
||||||
self.parentstop.set()
|
self.parentstop.set()
|
||||||
logging.debug("Quitting Scheduler thread")
|
log.debug("Quitting Scheduler thread")
|
||||||
if self.parentqueue is not None:
|
if self.parentqueue is not None:
|
||||||
self.parentqueue.put(('quit', None, None))
|
self.parentqueue.put(('quit', None, None))
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ from sleekxmpp.xmlstream import JID
|
||||||
from sleekxmpp.xmlstream.tostring import tostring
|
from sleekxmpp.xmlstream.tostring import tostring
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# Used to check if an argument is an XML object.
|
# Used to check if an argument is an XML object.
|
||||||
XML_TYPE = type(ET.Element('xml'))
|
XML_TYPE = type(ET.Element('xml'))
|
||||||
|
|
||||||
|
@ -1140,7 +1143,7 @@ class StanzaBase(ElementBase):
|
||||||
|
|
||||||
Meant to be overridden.
|
Meant to be overridden.
|
||||||
"""
|
"""
|
||||||
logging.exception('Error handling {%s}%s stanza' % (self.namespace,
|
log.exception('Error handling {%s}%s stanza' % (self.namespace,
|
||||||
self.name))
|
self.name))
|
||||||
|
|
||||||
def send(self):
|
def send(self):
|
||||||
|
|
|
@ -44,6 +44,9 @@ HANDLER_THREADS = 1
|
||||||
SSL_SUPPORT = True
|
SSL_SUPPORT = True
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RestartStream(Exception):
|
class RestartStream(Exception):
|
||||||
"""
|
"""
|
||||||
Exception to restart stream processing, including
|
Exception to restart stream processing, including
|
||||||
|
@ -87,6 +90,8 @@ class XMLStream(object):
|
||||||
send_queue -- A queue of stanzas to be sent on the stream.
|
send_queue -- A queue of stanzas to be sent on the stream.
|
||||||
socket -- The connection to the server.
|
socket -- The connection to the server.
|
||||||
ssl_support -- Indicates if a SSL library is available for use.
|
ssl_support -- Indicates if a SSL library is available for use.
|
||||||
|
ssl_version -- The version of the SSL protocol to use.
|
||||||
|
Defaults to ssl.PROTOCOL_TLSv1.
|
||||||
state -- A state machine for managing the stream's
|
state -- A state machine for managing the stream's
|
||||||
connection state.
|
connection state.
|
||||||
stream_footer -- The start tag and any attributes for the stream's
|
stream_footer -- The start tag and any attributes for the stream's
|
||||||
|
@ -155,6 +160,7 @@ class XMLStream(object):
|
||||||
self.sendXML = self.send_xml
|
self.sendXML = self.send_xml
|
||||||
|
|
||||||
self.ssl_support = SSL_SUPPORT
|
self.ssl_support = SSL_SUPPORT
|
||||||
|
self.ssl_version = ssl.PROTOCOL_TLSv1
|
||||||
|
|
||||||
self.state = StateMachine(('disconnected', 'connected'))
|
self.state = StateMachine(('disconnected', 'connected'))
|
||||||
self.state._set_state('disconnected')
|
self.state._set_state('disconnected')
|
||||||
|
@ -196,8 +202,15 @@ class XMLStream(object):
|
||||||
self.auto_reconnect = True
|
self.auto_reconnect = True
|
||||||
self.is_client = False
|
self.is_client = False
|
||||||
|
|
||||||
signal.signal(signal.SIGHUP, self._handle_kill)
|
try:
|
||||||
signal.signal(signal.SIGTERM, self._handle_kill) # used in Windows
|
if hasattr(signal, 'SIGHUP'):
|
||||||
|
signal.signal(signal.SIGHUP, self._handle_kill)
|
||||||
|
if hasattr(signal, 'SIGTERM'):
|
||||||
|
# Used in Windows
|
||||||
|
signal.signal(signal.SIGTERM, self._handle_kill)
|
||||||
|
except:
|
||||||
|
log.debug("Can not set interrupt signal handlers. " + \
|
||||||
|
"SleekXMPP is not running from a main thread.")
|
||||||
|
|
||||||
def _handle_kill(self, signum, frame):
|
def _handle_kill(self, signum, frame):
|
||||||
"""
|
"""
|
||||||
|
@ -265,7 +278,7 @@ class XMLStream(object):
|
||||||
self.socket = self.socket_class(Socket.AF_INET, Socket.SOCK_STREAM)
|
self.socket = self.socket_class(Socket.AF_INET, Socket.SOCK_STREAM)
|
||||||
self.socket.settimeout(None)
|
self.socket.settimeout(None)
|
||||||
if self.use_ssl and self.ssl_support:
|
if self.use_ssl and self.ssl_support:
|
||||||
logging.debug("Socket Wrapped for SSL")
|
log.debug("Socket Wrapped for SSL")
|
||||||
ssl_socket = ssl.wrap_socket(self.socket)
|
ssl_socket = ssl.wrap_socket(self.socket)
|
||||||
if hasattr(self.socket, 'socket'):
|
if hasattr(self.socket, 'socket'):
|
||||||
# We are using a testing socket, so preserve the top
|
# We are using a testing socket, so preserve the top
|
||||||
|
@ -275,7 +288,7 @@ class XMLStream(object):
|
||||||
self.socket = ssl_socket
|
self.socket = ssl_socket
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logging.debug("Connecting to %s:%s" % self.address)
|
log.debug("Connecting to %s:%s" % self.address)
|
||||||
self.socket.connect(self.address)
|
self.socket.connect(self.address)
|
||||||
self.set_socket(self.socket, ignore=True)
|
self.set_socket(self.socket, ignore=True)
|
||||||
#this event is where you should set your application state
|
#this event is where you should set your application state
|
||||||
|
@ -283,7 +296,7 @@ class XMLStream(object):
|
||||||
return True
|
return True
|
||||||
except Socket.error as serr:
|
except Socket.error as serr:
|
||||||
error_msg = "Could not connect to %s:%s. Socket Error #%s: %s"
|
error_msg = "Could not connect to %s:%s. Socket Error #%s: %s"
|
||||||
logging.error(error_msg % (self.address[0], self.address[1],
|
log.error(error_msg % (self.address[0], self.address[1],
|
||||||
serr.errno, serr.strerror))
|
serr.errno, serr.strerror))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
return False
|
return False
|
||||||
|
@ -328,10 +341,10 @@ class XMLStream(object):
|
||||||
"""
|
"""
|
||||||
Reset the stream's state and reconnect to the server.
|
Reset the stream's state and reconnect to the server.
|
||||||
"""
|
"""
|
||||||
logging.debug("reconnecting...")
|
log.debug("reconnecting...")
|
||||||
self.state.transition('connected', 'disconnected', wait=2.0,
|
self.state.transition('connected', 'disconnected', wait=2.0,
|
||||||
func=self._disconnect, args=(True,))
|
func=self._disconnect, args=(True,))
|
||||||
logging.debug("connecting...")
|
log.debug("connecting...")
|
||||||
return self.state.transition('disconnected', 'connected',
|
return self.state.transition('disconnected', 'connected',
|
||||||
wait=2.0, func=self._connect)
|
wait=2.0, func=self._connect)
|
||||||
|
|
||||||
|
@ -368,9 +381,10 @@ class XMLStream(object):
|
||||||
to be restarted.
|
to be restarted.
|
||||||
"""
|
"""
|
||||||
if self.ssl_support:
|
if self.ssl_support:
|
||||||
logging.info("Negotiating TLS")
|
log.info("Negotiating TLS")
|
||||||
|
log.info("Using SSL version: %s" % str(self.ssl_version))
|
||||||
ssl_socket = ssl.wrap_socket(self.socket,
|
ssl_socket = ssl.wrap_socket(self.socket,
|
||||||
ssl_version=ssl.PROTOCOL_TLSv1,
|
ssl_version=self.ssl_version,
|
||||||
do_handshake_on_connect=False)
|
do_handshake_on_connect=False)
|
||||||
if hasattr(self.socket, 'socket'):
|
if hasattr(self.socket, 'socket'):
|
||||||
# We are using a testing socket, so preserve the top
|
# We are using a testing socket, so preserve the top
|
||||||
|
@ -382,7 +396,7 @@ class XMLStream(object):
|
||||||
self.set_socket(self.socket)
|
self.set_socket(self.socket)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logging.warning("Tried to enable TLS, but ssl module not found.")
|
log.warning("Tried to enable TLS, but ssl module not found.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def start_stream_handler(self, xml):
|
def start_stream_handler(self, xml):
|
||||||
|
@ -517,6 +531,17 @@ class XMLStream(object):
|
||||||
self.__event_handlers[name] = filter(filter_pointers,
|
self.__event_handlers[name] = filter(filter_pointers,
|
||||||
self.__event_handlers[name])
|
self.__event_handlers[name])
|
||||||
|
|
||||||
|
def event_handled(self, name):
|
||||||
|
"""
|
||||||
|
Indicates if an event has any associated handlers.
|
||||||
|
|
||||||
|
Returns the number of registered handlers.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name -- The name of the event to check.
|
||||||
|
"""
|
||||||
|
return len(self.__event_handlers.get(name, []))
|
||||||
|
|
||||||
def event(self, name, data={}, direct=False):
|
def event(self, name, data={}, direct=False):
|
||||||
"""
|
"""
|
||||||
Manually trigger a custom event.
|
Manually trigger a custom event.
|
||||||
|
@ -525,13 +550,22 @@ class XMLStream(object):
|
||||||
name -- The name of the event to trigger.
|
name -- The name of the event to trigger.
|
||||||
data -- Data that will be passed to each event handler.
|
data -- Data that will be passed to each event handler.
|
||||||
Defaults to an empty dictionary.
|
Defaults to an empty dictionary.
|
||||||
direct -- Runs the event directly if True.
|
direct -- Runs the event directly if True, skipping the
|
||||||
|
event queue. All event handlers will run in the
|
||||||
|
same thread.
|
||||||
"""
|
"""
|
||||||
for handler in self.__event_handlers.get(name, []):
|
for handler in self.__event_handlers.get(name, []):
|
||||||
if direct:
|
if direct:
|
||||||
handler[0](copy.copy(data))
|
try:
|
||||||
|
handler[0](copy.copy(data))
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = 'Error processing event handler: %s'
|
||||||
|
log.exception(error_msg % str(handler[0]))
|
||||||
|
if hasattr(data, 'exception'):
|
||||||
|
data.exception(e)
|
||||||
else:
|
else:
|
||||||
self.event_queue.put(('event', handler, copy.copy(data)))
|
self.event_queue.put(('event', handler, copy.copy(data)))
|
||||||
|
|
||||||
if handler[2]:
|
if handler[2]:
|
||||||
# If the handler is disposable, we will go ahead and
|
# If the handler is disposable, we will go ahead and
|
||||||
# remove it now instead of waiting for it to be
|
# remove it now instead of waiting for it to be
|
||||||
|
@ -591,7 +625,7 @@ class XMLStream(object):
|
||||||
mask = mask.xml
|
mask = mask.xml
|
||||||
data = str(data)
|
data = str(data)
|
||||||
if mask is not None:
|
if mask is not None:
|
||||||
logging.warning("Use of send mask waiters is deprecated.")
|
log.warning("Use of send mask waiters is deprecated.")
|
||||||
wait_for = Waiter("SendWait_%s" % self.new_id(),
|
wait_for = Waiter("SendWait_%s" % self.new_id(),
|
||||||
MatchXMLMask(mask))
|
MatchXMLMask(mask))
|
||||||
self.register_handler(wait_for)
|
self.register_handler(wait_for)
|
||||||
|
@ -648,7 +682,7 @@ class XMLStream(object):
|
||||||
self.__thread[name].start()
|
self.__thread[name].start()
|
||||||
|
|
||||||
for t in range(0, HANDLER_THREADS):
|
for t in range(0, HANDLER_THREADS):
|
||||||
logging.debug("Starting HANDLER THREAD")
|
log.debug("Starting HANDLER THREAD")
|
||||||
start_thread('stream_event_handler_%s' % t, self._event_runner)
|
start_thread('stream_event_handler_%s' % t, self._event_runner)
|
||||||
|
|
||||||
start_thread('send_thread', self._send_thread)
|
start_thread('send_thread', self._send_thread)
|
||||||
|
@ -686,16 +720,16 @@ class XMLStream(object):
|
||||||
if self.is_client:
|
if self.is_client:
|
||||||
self.send_raw(self.stream_header)
|
self.send_raw(self.stream_header)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.debug("Keyboard Escape Detected in _process")
|
log.debug("Keyboard Escape Detected in _process")
|
||||||
self.stop.set()
|
self.stop.set()
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
logging.debug("SystemExit in _process")
|
log.debug("SystemExit in _process")
|
||||||
self.stop.set()
|
self.stop.set()
|
||||||
except Socket.error:
|
except Socket.error:
|
||||||
logging.exception('Socket Error')
|
log.exception('Socket Error')
|
||||||
except:
|
except:
|
||||||
if not self.stop.isSet():
|
if not self.stop.isSet():
|
||||||
logging.exception('Connection error.')
|
log.exception('Connection error.')
|
||||||
if not self.stop.isSet() and self.auto_reconnect:
|
if not self.stop.isSet() and self.auto_reconnect:
|
||||||
self.reconnect()
|
self.reconnect()
|
||||||
else:
|
else:
|
||||||
|
@ -725,7 +759,7 @@ class XMLStream(object):
|
||||||
if depth == 0:
|
if depth == 0:
|
||||||
# The stream's root element has closed,
|
# The stream's root element has closed,
|
||||||
# terminating the stream.
|
# terminating the stream.
|
||||||
logging.debug("End of stream recieved")
|
log.debug("End of stream recieved")
|
||||||
self.stream_end_event.set()
|
self.stream_end_event.set()
|
||||||
return False
|
return False
|
||||||
elif depth == 1:
|
elif depth == 1:
|
||||||
|
@ -739,7 +773,29 @@ class XMLStream(object):
|
||||||
# Keep the root element empty of children to
|
# Keep the root element empty of children to
|
||||||
# save on memory use.
|
# save on memory use.
|
||||||
root.clear()
|
root.clear()
|
||||||
logging.debug("Ending read XML loop")
|
log.debug("Ending read XML loop")
|
||||||
|
|
||||||
|
def _build_stanza(self, xml, default_ns=None):
|
||||||
|
"""
|
||||||
|
Create a stanza object from a given XML object.
|
||||||
|
|
||||||
|
If a specialized stanza type is not found for the XML, then
|
||||||
|
a generic StanzaBase stanza will be returned.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
xml -- The XML object to convert into a stanza object.
|
||||||
|
default_ns -- Optional default namespace to use instead of the
|
||||||
|
stream's current default namespace.
|
||||||
|
"""
|
||||||
|
if default_ns is None:
|
||||||
|
default_ns = self.default_ns
|
||||||
|
stanza_type = StanzaBase
|
||||||
|
for stanza_class in self.__root_stanza:
|
||||||
|
if xml.tag == "{%s}%s" % (default_ns, stanza_class.name):
|
||||||
|
stanza_type = stanza_class
|
||||||
|
break
|
||||||
|
stanza = stanza_type(self, xml)
|
||||||
|
return stanza
|
||||||
|
|
||||||
def __spawn_event(self, xml):
|
def __spawn_event(self, xml):
|
||||||
"""
|
"""
|
||||||
|
@ -750,7 +806,7 @@ class XMLStream(object):
|
||||||
Arguments:
|
Arguments:
|
||||||
xml -- The XML stanza to analyze.
|
xml -- The XML stanza to analyze.
|
||||||
"""
|
"""
|
||||||
logging.debug("RECV: %s" % tostring(xml,
|
log.debug("RECV: %s" % tostring(xml,
|
||||||
xmlns=self.default_ns,
|
xmlns=self.default_ns,
|
||||||
stream=self))
|
stream=self))
|
||||||
# Apply any preprocessing filters.
|
# Apply any preprocessing filters.
|
||||||
|
@ -799,7 +855,7 @@ class XMLStream(object):
|
||||||
func(*args)
|
func(*args)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = 'Error processing event handler: %s'
|
error_msg = 'Error processing event handler: %s'
|
||||||
logging.exception(error_msg % str(func))
|
log.exception(error_msg % str(func))
|
||||||
if hasattr(args[0], 'exception'):
|
if hasattr(args[0], 'exception'):
|
||||||
args[0].exception(e)
|
args[0].exception(e)
|
||||||
|
|
||||||
|
@ -812,7 +868,7 @@ class XMLStream(object):
|
||||||
Stream event handlers will all execute in this thread. Custom event
|
Stream event handlers will all execute in this thread. Custom event
|
||||||
handlers may be spawned in individual threads.
|
handlers may be spawned in individual threads.
|
||||||
"""
|
"""
|
||||||
logging.debug("Loading event runner")
|
log.debug("Loading event runner")
|
||||||
try:
|
try:
|
||||||
while not self.stop.isSet():
|
while not self.stop.isSet():
|
||||||
try:
|
try:
|
||||||
|
@ -830,14 +886,14 @@ class XMLStream(object):
|
||||||
handler.run(args[0])
|
handler.run(args[0])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = 'Error processing stream handler: %s'
|
error_msg = 'Error processing stream handler: %s'
|
||||||
logging.exception(error_msg % handler.name)
|
log.exception(error_msg % handler.name)
|
||||||
args[0].exception(e)
|
args[0].exception(e)
|
||||||
elif etype == 'schedule':
|
elif etype == 'schedule':
|
||||||
try:
|
try:
|
||||||
logging.debug(args)
|
log.debug(args)
|
||||||
handler(*args[0])
|
handler(*args[0])
|
||||||
except:
|
except:
|
||||||
logging.exception('Error processing scheduled task')
|
log.exception('Error processing scheduled task')
|
||||||
elif etype == 'event':
|
elif etype == 'event':
|
||||||
func, threaded, disposable = handler
|
func, threaded, disposable = handler
|
||||||
try:
|
try:
|
||||||
|
@ -851,14 +907,14 @@ class XMLStream(object):
|
||||||
func(*args)
|
func(*args)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = 'Error processing event handler: %s'
|
error_msg = 'Error processing event handler: %s'
|
||||||
logging.exception(error_msg % str(func))
|
log.exception(error_msg % str(func))
|
||||||
if hasattr(args[0], 'exception'):
|
if hasattr(args[0], 'exception'):
|
||||||
args[0].exception(e)
|
args[0].exception(e)
|
||||||
elif etype == 'quit':
|
elif etype == 'quit':
|
||||||
logging.debug("Quitting event runner thread")
|
log.debug("Quitting event runner thread")
|
||||||
return False
|
return False
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.debug("Keyboard Escape Detected in _event_runner")
|
log.debug("Keyboard Escape Detected in _event_runner")
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
|
@ -876,14 +932,14 @@ class XMLStream(object):
|
||||||
data = self.send_queue.get(True, 1)
|
data = self.send_queue.get(True, 1)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
continue
|
continue
|
||||||
logging.debug("SEND: %s" % data)
|
log.debug("SEND: %s" % data)
|
||||||
try:
|
try:
|
||||||
self.socket.send(data.encode('utf-8'))
|
self.socket.send(data.encode('utf-8'))
|
||||||
except:
|
except:
|
||||||
logging.warning("Failed to send %s" % data)
|
log.warning("Failed to send %s" % data)
|
||||||
self.disconnect(self.auto_reconnect)
|
self.disconnect(self.auto_reconnect)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.debug("Keyboard Escape Detected in _send_thread")
|
log.debug("Keyboard Escape Detected in _send_thread")
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
|
|
BIN
tests/__init__$py.class
Normal file
BIN
tests/__init__$py.class
Normal file
Binary file not shown.
|
@ -20,9 +20,9 @@ class TestLiveStream(SleekTest):
|
||||||
|
|
||||||
# Use sid=None to ignore any id sent by the server since
|
# Use sid=None to ignore any id sent by the server since
|
||||||
# we can't know it in advance.
|
# we can't know it in advance.
|
||||||
self.stream_recv_header(sfrom='localhost', sid=None)
|
self.recv_header(sfrom='localhost', sid=None)
|
||||||
self.stream_send_header(sto='localhost')
|
self.send_header(sto='localhost')
|
||||||
self.stream_recv_feature("""
|
self.recv_feature("""
|
||||||
<stream:features>
|
<stream:features>
|
||||||
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
|
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
|
||||||
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
|
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
|
||||||
|
@ -35,15 +35,15 @@ class TestLiveStream(SleekTest):
|
||||||
<register xmlns="http://jabber.org/features/iq-register" />
|
<register xmlns="http://jabber.org/features/iq-register" />
|
||||||
</stream:features>
|
</stream:features>
|
||||||
""")
|
""")
|
||||||
self.stream_send_feature("""
|
self.send_feature("""
|
||||||
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
|
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
|
||||||
""")
|
""")
|
||||||
self.stream_recv_feature("""
|
self.recv_feature("""
|
||||||
<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
|
<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
|
||||||
""")
|
""")
|
||||||
self.stream_send_header(sto='localhost')
|
self.send_header(sto='localhost')
|
||||||
self.stream_recv_header(sfrom='localhost', sid=None)
|
self.recv_header(sfrom='localhost', sid=None)
|
||||||
self.stream_recv_feature("""
|
self.recv_feature("""
|
||||||
<stream:features>
|
<stream:features>
|
||||||
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
|
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
|
||||||
<mechanism>DIGEST-MD5</mechanism>
|
<mechanism>DIGEST-MD5</mechanism>
|
||||||
|
@ -56,16 +56,16 @@ class TestLiveStream(SleekTest):
|
||||||
<register xmlns="http://jabber.org/features/iq-register" />
|
<register xmlns="http://jabber.org/features/iq-register" />
|
||||||
</stream:features>
|
</stream:features>
|
||||||
""")
|
""")
|
||||||
self.stream_send_feature("""
|
self.send_feature("""
|
||||||
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl"
|
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl"
|
||||||
mechanism="PLAIN">AHVzZXIAdXNlcg==</auth>
|
mechanism="PLAIN">AHVzZXIAdXNlcg==</auth>
|
||||||
""")
|
""")
|
||||||
self.stream_recv_feature("""
|
self.recv_feature("""
|
||||||
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />
|
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />
|
||||||
""")
|
""")
|
||||||
self.stream_send_header(sto='localhost')
|
self.send_header(sto='localhost')
|
||||||
self.stream_recv_header(sfrom='localhost', sid=None)
|
self.recv_header(sfrom='localhost', sid=None)
|
||||||
self.stream_recv_feature("""
|
self.recv_feature("""
|
||||||
<stream:features>
|
<stream:features>
|
||||||
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind" />
|
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind" />
|
||||||
<session xmlns="urn:ietf:params:xml:ns:xmpp-session" />
|
<session xmlns="urn:ietf:params:xml:ns:xmpp-session" />
|
||||||
|
@ -77,16 +77,16 @@ class TestLiveStream(SleekTest):
|
||||||
</stream:features>
|
</stream:features>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Should really use stream_send_iq, but our Iq stanza objects
|
# Should really use send, but our Iq stanza objects
|
||||||
# can't handle bind element payloads yet.
|
# can't handle bind element payloads yet.
|
||||||
self.stream_send_feature("""
|
self.send_feature("""
|
||||||
<iq type="set" id="1">
|
<iq type="set" id="1">
|
||||||
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
||||||
<resource>test</resource>
|
<resource>test</resource>
|
||||||
</bind>
|
</bind>
|
||||||
</iq>
|
</iq>
|
||||||
""")
|
""")
|
||||||
self.stream_recv_feature("""
|
self.recv_feature("""
|
||||||
<iq type="result" id="1">
|
<iq type="result" id="1">
|
||||||
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
||||||
<jid>user@localhost/test</jid>
|
<jid>user@localhost/test</jid>
|
||||||
|
|
|
@ -8,7 +8,7 @@ class TestJIDClass(SleekTest):
|
||||||
|
|
||||||
def testJIDFromFull(self):
|
def testJIDFromFull(self):
|
||||||
"""Test using JID of the form 'user@server/resource/with/slashes'."""
|
"""Test using JID of the form 'user@server/resource/with/slashes'."""
|
||||||
self.check_JID(JID('user@someserver/some/resource'),
|
self.check_jid(JID('user@someserver/some/resource'),
|
||||||
'user',
|
'user',
|
||||||
'someserver',
|
'someserver',
|
||||||
'some/resource',
|
'some/resource',
|
||||||
|
@ -22,7 +22,7 @@ class TestJIDClass(SleekTest):
|
||||||
j.user = 'user'
|
j.user = 'user'
|
||||||
j.domain = 'someserver'
|
j.domain = 'someserver'
|
||||||
j.resource = 'some/resource'
|
j.resource = 'some/resource'
|
||||||
self.check_JID(j,
|
self.check_jid(j,
|
||||||
'user',
|
'user',
|
||||||
'someserver',
|
'someserver',
|
||||||
'some/resource',
|
'some/resource',
|
||||||
|
@ -34,15 +34,15 @@ class TestJIDClass(SleekTest):
|
||||||
"""Test changing JID using aliases for domain."""
|
"""Test changing JID using aliases for domain."""
|
||||||
j = JID('user@someserver/resource')
|
j = JID('user@someserver/resource')
|
||||||
j.server = 'anotherserver'
|
j.server = 'anotherserver'
|
||||||
self.check_JID(j, domain='anotherserver')
|
self.check_jid(j, domain='anotherserver')
|
||||||
j.host = 'yetanother'
|
j.host = 'yetanother'
|
||||||
self.check_JID(j, domain='yetanother')
|
self.check_jid(j, domain='yetanother')
|
||||||
|
|
||||||
def testJIDSetFullWithUser(self):
|
def testJIDSetFullWithUser(self):
|
||||||
"""Test setting the full JID with a user portion."""
|
"""Test setting the full JID with a user portion."""
|
||||||
j = JID('user@domain/resource')
|
j = JID('user@domain/resource')
|
||||||
j.full = 'otheruser@otherdomain/otherresource'
|
j.full = 'otheruser@otherdomain/otherresource'
|
||||||
self.check_JID(j,
|
self.check_jid(j,
|
||||||
'otheruser',
|
'otheruser',
|
||||||
'otherdomain',
|
'otherdomain',
|
||||||
'otherresource',
|
'otherresource',
|
||||||
|
@ -57,7 +57,7 @@ class TestJIDClass(SleekTest):
|
||||||
"""
|
"""
|
||||||
j = JID('user@domain/resource')
|
j = JID('user@domain/resource')
|
||||||
j.full = 'otherdomain/otherresource'
|
j.full = 'otherdomain/otherresource'
|
||||||
self.check_JID(j,
|
self.check_jid(j,
|
||||||
'',
|
'',
|
||||||
'otherdomain',
|
'otherdomain',
|
||||||
'otherresource',
|
'otherresource',
|
||||||
|
@ -72,7 +72,7 @@ class TestJIDClass(SleekTest):
|
||||||
"""
|
"""
|
||||||
j = JID('user@domain/resource')
|
j = JID('user@domain/resource')
|
||||||
j.full = 'otherdomain'
|
j.full = 'otherdomain'
|
||||||
self.check_JID(j,
|
self.check_jid(j,
|
||||||
'',
|
'',
|
||||||
'otherdomain',
|
'otherdomain',
|
||||||
'',
|
'',
|
||||||
|
@ -84,7 +84,7 @@ class TestJIDClass(SleekTest):
|
||||||
"""Test setting the bare JID with a user."""
|
"""Test setting the bare JID with a user."""
|
||||||
j = JID('user@domain/resource')
|
j = JID('user@domain/resource')
|
||||||
j.bare = 'otheruser@otherdomain'
|
j.bare = 'otheruser@otherdomain'
|
||||||
self.check_JID(j,
|
self.check_jid(j,
|
||||||
'otheruser',
|
'otheruser',
|
||||||
'otherdomain',
|
'otherdomain',
|
||||||
'resource',
|
'resource',
|
||||||
|
@ -96,7 +96,7 @@ class TestJIDClass(SleekTest):
|
||||||
"""Test setting the bare JID without a user."""
|
"""Test setting the bare JID without a user."""
|
||||||
j = JID('user@domain/resource')
|
j = JID('user@domain/resource')
|
||||||
j.bare = 'otherdomain'
|
j.bare = 'otherdomain'
|
||||||
self.check_JID(j,
|
self.check_jid(j,
|
||||||
'',
|
'',
|
||||||
'otherdomain',
|
'otherdomain',
|
||||||
'resource',
|
'resource',
|
||||||
|
@ -106,7 +106,7 @@ class TestJIDClass(SleekTest):
|
||||||
|
|
||||||
def testJIDNoResource(self):
|
def testJIDNoResource(self):
|
||||||
"""Test using JID of the form 'user@domain'."""
|
"""Test using JID of the form 'user@domain'."""
|
||||||
self.check_JID(JID('user@someserver'),
|
self.check_jid(JID('user@someserver'),
|
||||||
'user',
|
'user',
|
||||||
'someserver',
|
'someserver',
|
||||||
'',
|
'',
|
||||||
|
@ -116,7 +116,7 @@ class TestJIDClass(SleekTest):
|
||||||
|
|
||||||
def testJIDNoUser(self):
|
def testJIDNoUser(self):
|
||||||
"""Test JID of the form 'component.domain.tld'."""
|
"""Test JID of the form 'component.domain.tld'."""
|
||||||
self.check_JID(JID('component.someserver'),
|
self.check_jid(JID('component.someserver'),
|
||||||
'',
|
'',
|
||||||
'component.someserver',
|
'component.someserver',
|
||||||
'',
|
'',
|
||||||
|
|
|
@ -27,7 +27,7 @@ class TestElementBase(SleekTest):
|
||||||
namespace = "test"
|
namespace = "test"
|
||||||
|
|
||||||
stanza = TestStanza()
|
stanza = TestStanza()
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="test">
|
<foo xmlns="test">
|
||||||
<bar>
|
<bar>
|
||||||
<baz />
|
<baz />
|
||||||
|
@ -117,7 +117,7 @@ class TestElementBase(SleekTest):
|
||||||
'baz': ''}]}
|
'baz': ''}]}
|
||||||
stanza.setStanzaValues(values)
|
stanza.setStanzaValues(values)
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo" bar="a">
|
<foo xmlns="foo" bar="a">
|
||||||
<pluginfoo baz="b" />
|
<pluginfoo baz="b" />
|
||||||
<pluginfoo2 bar="d" baz="e" />
|
<pluginfoo2 bar="d" baz="e" />
|
||||||
|
@ -198,7 +198,7 @@ class TestElementBase(SleekTest):
|
||||||
stanza['qux'] = 'overridden'
|
stanza['qux'] = 'overridden'
|
||||||
stanza['foobar'] = 'plugin'
|
stanza['foobar'] = 'plugin'
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo" bar="attribute!">
|
<foo xmlns="foo" bar="attribute!">
|
||||||
<baz>element!</baz>
|
<baz>element!</baz>
|
||||||
<foobar foobar="plugin" />
|
<foobar foobar="plugin" />
|
||||||
|
@ -231,7 +231,7 @@ class TestElementBase(SleekTest):
|
||||||
stanza['qux'] = 'c'
|
stanza['qux'] = 'c'
|
||||||
stanza['foobar']['foobar'] = 'd'
|
stanza['foobar']['foobar'] = 'd'
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo" baz="b" qux="c">
|
<foo xmlns="foo" baz="b" qux="c">
|
||||||
<bar>a</bar>
|
<bar>a</bar>
|
||||||
<foobar foobar="d" />
|
<foobar foobar="d" />
|
||||||
|
@ -243,7 +243,7 @@ class TestElementBase(SleekTest):
|
||||||
del stanza['qux']
|
del stanza['qux']
|
||||||
del stanza['foobar']
|
del stanza['foobar']
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo" qux="c" />
|
<foo xmlns="foo" qux="c" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ class TestElementBase(SleekTest):
|
||||||
|
|
||||||
stanza = TestStanza()
|
stanza = TestStanza()
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo" />
|
<foo xmlns="foo" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ class TestElementBase(SleekTest):
|
||||||
stanza._set_attr('bar', 'a')
|
stanza._set_attr('bar', 'a')
|
||||||
stanza._set_attr('baz', 'b')
|
stanza._set_attr('baz', 'b')
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo" bar="a" baz="b" />
|
<foo xmlns="foo" bar="a" baz="b" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ class TestElementBase(SleekTest):
|
||||||
stanza._set_attr('bar', None)
|
stanza._set_attr('bar', None)
|
||||||
stanza._del_attr('baz')
|
stanza._del_attr('baz')
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo" />
|
<foo xmlns="foo" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ class TestElementBase(SleekTest):
|
||||||
"Default _get_sub_text value incorrect.")
|
"Default _get_sub_text value incorrect.")
|
||||||
|
|
||||||
stanza['bar'] = 'found'
|
stanza['bar'] = 'found'
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<wrapper>
|
<wrapper>
|
||||||
<bar>found</bar>
|
<bar>found</bar>
|
||||||
|
@ -340,7 +340,7 @@ class TestElementBase(SleekTest):
|
||||||
stanza = TestStanza()
|
stanza = TestStanza()
|
||||||
stanza['bar'] = 'a'
|
stanza['bar'] = 'a'
|
||||||
stanza['baz'] = 'b'
|
stanza['baz'] = 'b'
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<wrapper>
|
<wrapper>
|
||||||
<bar>a</bar>
|
<bar>a</bar>
|
||||||
|
@ -349,7 +349,7 @@ class TestElementBase(SleekTest):
|
||||||
</foo>
|
</foo>
|
||||||
""")
|
""")
|
||||||
stanza._set_sub_text('wrapper/bar', text='', keep=True)
|
stanza._set_sub_text('wrapper/bar', text='', keep=True)
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<wrapper>
|
<wrapper>
|
||||||
<bar />
|
<bar />
|
||||||
|
@ -360,7 +360,7 @@ class TestElementBase(SleekTest):
|
||||||
|
|
||||||
stanza['bar'] = 'a'
|
stanza['bar'] = 'a'
|
||||||
stanza._set_sub_text('wrapper/bar', text='')
|
stanza._set_sub_text('wrapper/bar', text='')
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<wrapper>
|
<wrapper>
|
||||||
<baz>b</baz>
|
<baz>b</baz>
|
||||||
|
@ -398,7 +398,7 @@ class TestElementBase(SleekTest):
|
||||||
stanza['bar'] = 'a'
|
stanza['bar'] = 'a'
|
||||||
stanza['baz'] = 'b'
|
stanza['baz'] = 'b'
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<path>
|
<path>
|
||||||
<to>
|
<to>
|
||||||
|
@ -416,7 +416,7 @@ class TestElementBase(SleekTest):
|
||||||
del stanza['bar']
|
del stanza['bar']
|
||||||
del stanza['baz']
|
del stanza['baz']
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<path>
|
<path>
|
||||||
<to>
|
<to>
|
||||||
|
@ -432,7 +432,7 @@ class TestElementBase(SleekTest):
|
||||||
|
|
||||||
stanza._del_sub('path/to/only/bar', all=True)
|
stanza._del_sub('path/to/only/bar', all=True)
|
||||||
|
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<path>
|
<path>
|
||||||
<to>
|
<to>
|
||||||
|
@ -603,7 +603,7 @@ class TestElementBase(SleekTest):
|
||||||
"Incorrect empty stanza size.")
|
"Incorrect empty stanza size.")
|
||||||
|
|
||||||
stanza.append(substanza1)
|
stanza.append(substanza1)
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<foobar qux="a" />
|
<foobar qux="a" />
|
||||||
</foo>
|
</foo>
|
||||||
|
@ -612,7 +612,7 @@ class TestElementBase(SleekTest):
|
||||||
"Incorrect stanza size with 1 substanza.")
|
"Incorrect stanza size with 1 substanza.")
|
||||||
|
|
||||||
stanza.append(substanza2)
|
stanza.append(substanza2)
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<foobar qux="a" />
|
<foobar qux="a" />
|
||||||
<foobar qux="b" />
|
<foobar qux="b" />
|
||||||
|
@ -623,7 +623,7 @@ class TestElementBase(SleekTest):
|
||||||
|
|
||||||
# Test popping substanzas
|
# Test popping substanzas
|
||||||
stanza.pop(0)
|
stanza.pop(0)
|
||||||
self.check_stanza(TestStanza, stanza, """
|
self.check(stanza, """
|
||||||
<foo xmlns="foo">
|
<foo xmlns="foo">
|
||||||
<foobar qux="b" />
|
<foobar qux="b" />
|
||||||
</foo>
|
</foo>
|
||||||
|
|
|
@ -7,7 +7,7 @@ class TestErrorStanzas(SleekTest):
|
||||||
"""Test setting initial values in error stanza."""
|
"""Test setting initial values in error stanza."""
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg.enable('error')
|
msg.enable('error')
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
||||||
|
@ -20,7 +20,7 @@ class TestErrorStanzas(SleekTest):
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['error']['condition'] = 'item-not-found'
|
msg['error']['condition'] = 'item-not-found'
|
||||||
|
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
<item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
||||||
|
@ -32,7 +32,7 @@ class TestErrorStanzas(SleekTest):
|
||||||
|
|
||||||
msg['error']['condition'] = 'resource-constraint'
|
msg['error']['condition'] = 'resource-constraint'
|
||||||
|
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<resource-constraint xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
<resource-constraint xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
||||||
|
@ -48,7 +48,7 @@ class TestErrorStanzas(SleekTest):
|
||||||
|
|
||||||
del msg['error']['condition']
|
del msg['error']['condition']
|
||||||
|
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Error!</text>
|
<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Error!</text>
|
||||||
|
@ -64,7 +64,7 @@ class TestErrorStanzas(SleekTest):
|
||||||
|
|
||||||
del msg['error']['text']
|
del msg['error']['text']
|
||||||
|
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<internal-server-error xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
<internal-server-error xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
||||||
|
|
BIN
tests/test_stanza_gmail$py.class
Normal file
BIN
tests/test_stanza_gmail$py.class
Normal file
Binary file not shown.
|
@ -18,7 +18,7 @@ class TestGmail(SleekTest):
|
||||||
iq['gmail']['newer-than-time'] = '1140638252542'
|
iq['gmail']['newer-than-time'] = '1140638252542'
|
||||||
iq['gmail']['newer-than-tid'] = '11134623426430234'
|
iq['gmail']['newer-than-tid'] = '11134623426430234'
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq type="get">
|
<iq type="get">
|
||||||
<query xmlns="google:mail:notify"
|
<query xmlns="google:mail:notify"
|
||||||
newer-than-time="1140638252542"
|
newer-than-time="1140638252542"
|
||||||
|
|
|
@ -11,7 +11,7 @@ class TestIqStanzas(SleekTest):
|
||||||
def testSetup(self):
|
def testSetup(self):
|
||||||
"""Test initializing default Iq values."""
|
"""Test initializing default Iq values."""
|
||||||
iq = self.Iq()
|
iq = self.Iq()
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0" />
|
<iq id="0" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class TestIqStanzas(SleekTest):
|
||||||
"""Test setting Iq stanza payload."""
|
"""Test setting Iq stanza payload."""
|
||||||
iq = self.Iq()
|
iq = self.Iq()
|
||||||
iq.setPayload(ET.Element('{test}tester'))
|
iq.setPayload(ET.Element('{test}tester'))
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<tester xmlns="test" />
|
<tester xmlns="test" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -29,7 +29,7 @@ class TestIqStanzas(SleekTest):
|
||||||
def testUnhandled(self):
|
def testUnhandled(self):
|
||||||
"""Test behavior for Iq.unhandled."""
|
"""Test behavior for Iq.unhandled."""
|
||||||
self.stream_start()
|
self.stream_start()
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<iq id="test" type="get">
|
<iq id="test" type="get">
|
||||||
<query xmlns="test" />
|
<query xmlns="test" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -40,7 +40,7 @@ class TestIqStanzas(SleekTest):
|
||||||
iq['error']['condition'] = 'feature-not-implemented'
|
iq['error']['condition'] = 'feature-not-implemented'
|
||||||
iq['error']['text'] = 'No handlers registered for this request.'
|
iq['error']['text'] = 'No handlers registered for this request.'
|
||||||
|
|
||||||
self.stream_send_iq(iq, """
|
self.send(iq, """
|
||||||
<iq id="test" type="error">
|
<iq id="test" type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
|
||||||
|
@ -56,14 +56,14 @@ class TestIqStanzas(SleekTest):
|
||||||
iq = self.Iq()
|
iq = self.Iq()
|
||||||
|
|
||||||
iq['query'] = 'query_ns'
|
iq['query'] = 'query_ns'
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="query_ns" />
|
<query xmlns="query_ns" />
|
||||||
</iq>
|
</iq>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
iq['query'] = 'query_ns2'
|
iq['query'] = 'query_ns2'
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="query_ns2" />
|
<query xmlns="query_ns2" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -72,7 +72,7 @@ class TestIqStanzas(SleekTest):
|
||||||
self.failUnless(iq['query'] == 'query_ns2', "Query namespace doesn't match")
|
self.failUnless(iq['query'] == 'query_ns2', "Query namespace doesn't match")
|
||||||
|
|
||||||
del iq['query']
|
del iq['query']
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0" />
|
<iq id="0" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class TestIqStanzas(SleekTest):
|
||||||
iq['type'] = 'get'
|
iq['type'] = 'get'
|
||||||
iq.reply()
|
iq.reply()
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0" type="result" />
|
<iq id="0" type="result" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class TestMessageStanzas(SleekTest):
|
||||||
p = ET.Element('{http://www.w3.org/1999/xhtml}p')
|
p = ET.Element('{http://www.w3.org/1999/xhtml}p')
|
||||||
p.text = "This is the htmlim message"
|
p.text = "This is the htmlim message"
|
||||||
msg['html']['body'] = p
|
msg['html']['body'] = p
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message to="fritzy@netflint.net/sleekxmpp" type="chat">
|
<message to="fritzy@netflint.net/sleekxmpp" type="chat">
|
||||||
<body>this is the plaintext message</body>
|
<body>this is the plaintext message</body>
|
||||||
<html xmlns="http://jabber.org/protocol/xhtml-im">
|
<html xmlns="http://jabber.org/protocol/xhtml-im">
|
||||||
|
@ -47,7 +47,7 @@ class TestMessageStanzas(SleekTest):
|
||||||
"Test message/nick/nick stanza."
|
"Test message/nick/nick stanza."
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['nick']['nick'] = 'A nickname!'
|
msg['nick']['nick'] = 'A nickname!'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<nick xmlns="http://jabber.org/nick/nick">A nickname!</nick>
|
<nick xmlns="http://jabber.org/nick/nick">A nickname!</nick>
|
||||||
</message>
|
</message>
|
||||||
|
|
|
@ -8,26 +8,26 @@ class TestPresenceStanzas(SleekTest):
|
||||||
"""Regression check presence['type'] = 'dnd' show value working"""
|
"""Regression check presence['type'] = 'dnd' show value working"""
|
||||||
p = self.Presence()
|
p = self.Presence()
|
||||||
p['type'] = 'dnd'
|
p['type'] = 'dnd'
|
||||||
self.check_presence(p, "<presence><show>dnd</show></presence>")
|
self.check(p, "<presence><show>dnd</show></presence>")
|
||||||
|
|
||||||
def testPresenceType(self):
|
def testPresenceType(self):
|
||||||
"""Test manipulating presence['type']"""
|
"""Test manipulating presence['type']"""
|
||||||
p = self.Presence()
|
p = self.Presence()
|
||||||
p['type'] = 'available'
|
p['type'] = 'available'
|
||||||
self.check_presence(p, "<presence />")
|
self.check(p, "<presence />")
|
||||||
self.failUnless(p['type'] == 'available',
|
self.failUnless(p['type'] == 'available',
|
||||||
"Incorrect presence['type'] for type 'available': %s" % p['type'])
|
"Incorrect presence['type'] for type 'available': %s" % p['type'])
|
||||||
|
|
||||||
for showtype in ['away', 'chat', 'dnd', 'xa']:
|
for showtype in ['away', 'chat', 'dnd', 'xa']:
|
||||||
p['type'] = showtype
|
p['type'] = showtype
|
||||||
self.check_presence(p, """
|
self.check(p, """
|
||||||
<presence><show>%s</show></presence>
|
<presence><show>%s</show></presence>
|
||||||
""" % showtype)
|
""" % showtype)
|
||||||
self.failUnless(p['type'] == showtype,
|
self.failUnless(p['type'] == showtype,
|
||||||
"Incorrect presence['type'] for type '%s'" % showtype)
|
"Incorrect presence['type'] for type '%s'" % showtype)
|
||||||
|
|
||||||
p['type'] = None
|
p['type'] = None
|
||||||
self.check_presence(p, "<presence />")
|
self.check(p, "<presence />")
|
||||||
|
|
||||||
def testPresenceUnsolicitedOffline(self):
|
def testPresenceUnsolicitedOffline(self):
|
||||||
"""
|
"""
|
||||||
|
@ -57,7 +57,7 @@ class TestPresenceStanzas(SleekTest):
|
||||||
"""Test presence/nick/nick stanza."""
|
"""Test presence/nick/nick stanza."""
|
||||||
p = self.Presence()
|
p = self.Presence()
|
||||||
p['nick']['nick'] = 'A nickname!'
|
p['nick']['nick'] = 'A nickname!'
|
||||||
self.check_presence(p, """
|
self.check(p, """
|
||||||
<presence>
|
<presence>
|
||||||
<nick xmlns="http://jabber.org/nick/nick">A nickname!</nick>
|
<nick xmlns="http://jabber.org/nick/nick">A nickname!</nick>
|
||||||
</presence>
|
</presence>
|
||||||
|
|
|
@ -16,7 +16,7 @@ class TestRosterStanzas(SleekTest):
|
||||||
'name': 'Other User',
|
'name': 'Other User',
|
||||||
'subscription': 'both',
|
'subscription': 'both',
|
||||||
'groups': []}})
|
'groups': []}})
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq>
|
<iq>
|
||||||
<query xmlns="jabber:iq:roster">
|
<query xmlns="jabber:iq:roster">
|
||||||
<item jid="user@example.com" name="User" subscription="both">
|
<item jid="user@example.com" name="User" subscription="both">
|
||||||
|
@ -78,7 +78,7 @@ class TestRosterStanzas(SleekTest):
|
||||||
"""
|
"""
|
||||||
iq = self.Iq(ET.fromstring(xml_string))
|
iq = self.Iq(ET.fromstring(xml_string))
|
||||||
del iq['roster']['items']
|
del iq['roster']['items']
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq>
|
<iq>
|
||||||
<query xmlns="jabber:iq:roster" />
|
<query xmlns="jabber:iq:roster" />
|
||||||
</iq>
|
</iq>
|
||||||
|
|
|
@ -14,7 +14,7 @@ class TestDataForms(SleekTest):
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['form']['instructions'] = "Instructions\nSecond batch"
|
msg['form']['instructions'] = "Instructions\nSecond batch"
|
||||||
|
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<x xmlns="jabber:x:data" type="form">
|
<x xmlns="jabber:x:data" type="form">
|
||||||
<instructions>Instructions</instructions>
|
<instructions>Instructions</instructions>
|
||||||
|
@ -35,7 +35,7 @@ class TestDataForms(SleekTest):
|
||||||
required=True,
|
required=True,
|
||||||
value='Some text!')
|
value='Some text!')
|
||||||
|
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<x xmlns="jabber:x:data" type="form">
|
<x xmlns="jabber:x:data" type="form">
|
||||||
<field var="f1" type="text-single" label="Text">
|
<field var="f1" type="text-single" label="Text">
|
||||||
|
@ -62,7 +62,7 @@ class TestDataForms(SleekTest):
|
||||||
'value': 'cool'},
|
'value': 'cool'},
|
||||||
{'label': 'Urgh!',
|
{'label': 'Urgh!',
|
||||||
'value': 'urgh'}]})]
|
'value': 'urgh'}]})]
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<x xmlns="jabber:x:data" type="form">
|
<x xmlns="jabber:x:data" type="form">
|
||||||
<field var="f1" type="text-single" label="Username">
|
<field var="f1" type="text-single" label="Username">
|
||||||
|
@ -99,7 +99,7 @@ class TestDataForms(SleekTest):
|
||||||
form.setValues({'foo': 'Foo!',
|
form.setValues({'foo': 'Foo!',
|
||||||
'bar': ['a', 'b']})
|
'bar': ['a', 'b']})
|
||||||
|
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<x xmlns="jabber:x:data" type="form">
|
<x xmlns="jabber:x:data" type="form">
|
||||||
<field var="foo" type="text-single">
|
<field var="foo" type="text-single">
|
||||||
|
|
|
@ -14,7 +14,7 @@ class TestDisco(SleekTest):
|
||||||
iq['id'] = "0"
|
iq['id'] = "0"
|
||||||
iq['disco_info']['node'] = ''
|
iq['disco_info']['node'] = ''
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="http://jabber.org/protocol/disco#info" />
|
<query xmlns="http://jabber.org/protocol/disco#info" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -26,7 +26,7 @@ class TestDisco(SleekTest):
|
||||||
iq['id'] = "0"
|
iq['id'] = "0"
|
||||||
iq['disco_info']['node'] = 'foo'
|
iq['disco_info']['node'] = 'foo'
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="http://jabber.org/protocol/disco#info" node="foo" />
|
<query xmlns="http://jabber.org/protocol/disco#info" node="foo" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -38,7 +38,7 @@ class TestDisco(SleekTest):
|
||||||
iq['id'] = "0"
|
iq['id'] = "0"
|
||||||
iq['disco_items']['node'] = ''
|
iq['disco_items']['node'] = ''
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="http://jabber.org/protocol/disco#items" />
|
<query xmlns="http://jabber.org/protocol/disco#items" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -50,7 +50,7 @@ class TestDisco(SleekTest):
|
||||||
iq['id'] = "0"
|
iq['id'] = "0"
|
||||||
iq['disco_items']['node'] = 'foo'
|
iq['disco_items']['node'] = 'foo'
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="http://jabber.org/protocol/disco#items" node="foo" />
|
<query xmlns="http://jabber.org/protocol/disco#items" node="foo" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -63,7 +63,7 @@ class TestDisco(SleekTest):
|
||||||
iq['disco_info']['node'] = 'foo'
|
iq['disco_info']['node'] = 'foo'
|
||||||
iq['disco_info'].addIdentity('conference', 'text', 'Chatroom')
|
iq['disco_info'].addIdentity('conference', 'text', 'Chatroom')
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="http://jabber.org/protocol/disco#info" node="foo">
|
<query xmlns="http://jabber.org/protocol/disco#info" node="foo">
|
||||||
<identity category="conference" type="text" name="Chatroom" />
|
<identity category="conference" type="text" name="Chatroom" />
|
||||||
|
@ -79,7 +79,7 @@ class TestDisco(SleekTest):
|
||||||
iq['disco_info'].addFeature('foo')
|
iq['disco_info'].addFeature('foo')
|
||||||
iq['disco_info'].addFeature('bar')
|
iq['disco_info'].addFeature('bar')
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="http://jabber.org/protocol/disco#info" node="foo">
|
<query xmlns="http://jabber.org/protocol/disco#info" node="foo">
|
||||||
<feature var="foo" />
|
<feature var="foo" />
|
||||||
|
@ -97,7 +97,7 @@ class TestDisco(SleekTest):
|
||||||
iq['disco_items'].addItem('user@localhost', 'foo')
|
iq['disco_items'].addItem('user@localhost', 'foo')
|
||||||
iq['disco_items'].addItem('user@localhost', 'bar', 'Testing')
|
iq['disco_items'].addItem('user@localhost', 'bar', 'Testing')
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<query xmlns="http://jabber.org/protocol/disco#items" node="foo">
|
<query xmlns="http://jabber.org/protocol/disco#items" node="foo">
|
||||||
<item jid="user@localhost" />
|
<item jid="user@localhost" />
|
||||||
|
|
|
@ -11,7 +11,7 @@ class TestAddresses(SleekTest):
|
||||||
"""Testing adding extended stanza address."""
|
"""Testing adding extended stanza address."""
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['addresses'].addAddress(atype='to', jid='to@header1.org')
|
msg['addresses'].addAddress(atype='to', jid='to@header1.org')
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<addresses xmlns="http://jabber.org/protocol/address">
|
<addresses xmlns="http://jabber.org/protocol/address">
|
||||||
<address jid="to@header1.org" type="to" />
|
<address jid="to@header1.org" type="to" />
|
||||||
|
@ -23,7 +23,7 @@ class TestAddresses(SleekTest):
|
||||||
msg['addresses'].addAddress(atype='replyto',
|
msg['addresses'].addAddress(atype='replyto',
|
||||||
jid='replyto@header1.org',
|
jid='replyto@header1.org',
|
||||||
desc='Reply address')
|
desc='Reply address')
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<addresses xmlns="http://jabber.org/protocol/address">
|
<addresses xmlns="http://jabber.org/protocol/address">
|
||||||
<address jid="replyto@header1.org" type="replyto" desc="Reply address" />
|
<address jid="replyto@header1.org" type="replyto" desc="Reply address" />
|
||||||
|
@ -53,14 +53,14 @@ class TestAddresses(SleekTest):
|
||||||
'jid':'cc@header2.org'},
|
'jid':'cc@header2.org'},
|
||||||
{'type':'bcc',
|
{'type':'bcc',
|
||||||
'jid':'bcc@header2.org'}])
|
'jid':'bcc@header2.org'}])
|
||||||
self.check_message(msg, xmlstring)
|
self.check(msg, xmlstring)
|
||||||
|
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['addresses']['replyto'] = [{'jid':'replyto@header1.org',
|
msg['addresses']['replyto'] = [{'jid':'replyto@header1.org',
|
||||||
'desc':'Reply address'}]
|
'desc':'Reply address'}]
|
||||||
msg['addresses']['cc'] = [{'jid':'cc@header2.org'}]
|
msg['addresses']['cc'] = [{'jid':'cc@header2.org'}]
|
||||||
msg['addresses']['bcc'] = [{'jid':'bcc@header2.org'}]
|
msg['addresses']['bcc'] = [{'jid':'bcc@header2.org'}]
|
||||||
self.check_message(msg, xmlstring)
|
self.check(msg, xmlstring)
|
||||||
|
|
||||||
def testAddURI(self):
|
def testAddURI(self):
|
||||||
"""Testing adding URI attribute to extended stanza address."""
|
"""Testing adding URI attribute to extended stanza address."""
|
||||||
|
@ -69,7 +69,7 @@ class TestAddresses(SleekTest):
|
||||||
addr = msg['addresses'].addAddress(atype='to',
|
addr = msg['addresses'].addAddress(atype='to',
|
||||||
jid='to@header1.org',
|
jid='to@header1.org',
|
||||||
node='foo')
|
node='foo')
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<addresses xmlns="http://jabber.org/protocol/address">
|
<addresses xmlns="http://jabber.org/protocol/address">
|
||||||
<address node="foo" jid="to@header1.org" type="to" />
|
<address node="foo" jid="to@header1.org" type="to" />
|
||||||
|
@ -78,7 +78,7 @@ class TestAddresses(SleekTest):
|
||||||
""")
|
""")
|
||||||
|
|
||||||
addr['uri'] = 'mailto:to@header2.org'
|
addr['uri'] = 'mailto:to@header2.org'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message>
|
<message>
|
||||||
<addresses xmlns="http://jabber.org/protocol/address">
|
<addresses xmlns="http://jabber.org/protocol/address">
|
||||||
<address type="to" uri="mailto:to@header2.org" />
|
<address type="to" uri="mailto:to@header2.org" />
|
||||||
|
@ -99,13 +99,13 @@ class TestAddresses(SleekTest):
|
||||||
|
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
addr = msg['addresses'].addAddress(jid='to@header1.org', atype='to')
|
addr = msg['addresses'].addAddress(jid='to@header1.org', atype='to')
|
||||||
self.check_message(msg, xmlstring % '')
|
self.check(msg, xmlstring % '')
|
||||||
|
|
||||||
addr['delivered'] = True
|
addr['delivered'] = True
|
||||||
self.check_message(msg, xmlstring % 'delivered="true"')
|
self.check(msg, xmlstring % 'delivered="true"')
|
||||||
|
|
||||||
addr['delivered'] = False
|
addr['delivered'] = False
|
||||||
self.check_message(msg, xmlstring % '')
|
self.check(msg, xmlstring % '')
|
||||||
|
|
||||||
|
|
||||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestAddresses)
|
suite = unittest.TestLoader().loadTestsFromTestCase(TestAddresses)
|
||||||
|
|
|
@ -16,7 +16,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
aff2['affiliation'] = 'publisher'
|
aff2['affiliation'] = 'publisher'
|
||||||
iq['pubsub']['affiliations'].append(aff1)
|
iq['pubsub']['affiliations'].append(aff1)
|
||||||
iq['pubsub']['affiliations'].append(aff2)
|
iq['pubsub']['affiliations'].append(aff2)
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<affiliations>
|
<affiliations>
|
||||||
|
@ -38,7 +38,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
sub2['subscription'] = 'subscribed'
|
sub2['subscription'] = 'subscribed'
|
||||||
iq['pubsub']['subscriptions'].append(sub1)
|
iq['pubsub']['subscriptions'].append(sub1)
|
||||||
iq['pubsub']['subscriptions'].append(sub2)
|
iq['pubsub']['subscriptions'].append(sub2)
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<subscriptions>
|
<subscriptions>
|
||||||
|
@ -55,7 +55,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
iq['pubsub']['subscription']['node'] = 'testnode alsdkjfas'
|
iq['pubsub']['subscription']['node'] = 'testnode alsdkjfas'
|
||||||
iq['pubsub']['subscription']['jid'] = "fritzy@netflint.net/sleekxmpp"
|
iq['pubsub']['subscription']['jid'] = "fritzy@netflint.net/sleekxmpp"
|
||||||
iq['pubsub']['subscription']['subscription'] = 'unconfigured'
|
iq['pubsub']['subscription']['subscription'] = 'unconfigured'
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<subscription node="testnode alsdkjfas" jid="fritzy@netflint.net/sleekxmpp" subscription="unconfigured">
|
<subscription node="testnode alsdkjfas" jid="fritzy@netflint.net/sleekxmpp" subscription="unconfigured">
|
||||||
|
@ -88,7 +88,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
item2['payload'] = payload2
|
item2['payload'] = payload2
|
||||||
iq['pubsub']['items'].append(item)
|
iq['pubsub']['items'].append(item)
|
||||||
iq['pubsub']['items'].append(item2)
|
iq['pubsub']['items'].append(item2)
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<items node="crap">
|
<items node="crap">
|
||||||
|
@ -115,7 +115,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
iq['pubsub']['configure']['form'].addField('pubsub#title',
|
iq['pubsub']['configure']['form'].addField('pubsub#title',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value='This thing is awesome')
|
value='This thing is awesome')
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<create node="mynode" />
|
<create node="mynode" />
|
||||||
|
@ -136,7 +136,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
iq['psstate']['item']= 'myitem'
|
iq['psstate']['item']= 'myitem'
|
||||||
pl = ET.Element('{http://andyet.net/protocol/pubsubqueue}claimed')
|
pl = ET.Element('{http://andyet.net/protocol/pubsubqueue}claimed')
|
||||||
iq['psstate']['payload'] = pl
|
iq['psstate']['payload'] = pl
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<state xmlns="http://jabber.org/protocol/psstate" node="mynode" item="myitem">
|
<state xmlns="http://jabber.org/protocol/psstate" node="mynode" item="myitem">
|
||||||
<claimed xmlns="http://andyet.net/protocol/pubsubqueue" />
|
<claimed xmlns="http://andyet.net/protocol/pubsubqueue" />
|
||||||
|
@ -152,7 +152,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
iq['pubsub_owner']['default']['form'].addField('pubsub#title',
|
iq['pubsub_owner']['default']['form'].addField('pubsub#title',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value='This thing is awesome')
|
value='This thing is awesome')
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
|
||||||
<default node="mynode" type="leaf">
|
<default node="mynode" type="leaf">
|
||||||
|
@ -176,7 +176,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
form = xep_0004.Form()
|
form = xep_0004.Form()
|
||||||
form.addField('pubsub#title', ftype='text-single', value='this thing is awesome')
|
form.addField('pubsub#title', ftype='text-single', value='this thing is awesome')
|
||||||
iq['pubsub']['subscribe']['options']['options'] = form
|
iq['pubsub']['subscribe']['options']['options'] = form
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<subscribe node="cheese" jid="fritzy@netflint.net/sleekxmpp">
|
<subscribe node="cheese" jid="fritzy@netflint.net/sleekxmpp">
|
||||||
|
@ -214,7 +214,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
iq['pubsub']['publish'].append(item)
|
iq['pubsub']['publish'].append(item)
|
||||||
iq['pubsub']['publish'].append(item2)
|
iq['pubsub']['publish'].append(item2)
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<publish node="thingers">
|
<publish node="thingers">
|
||||||
|
@ -238,7 +238,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
"Testing iq/pubsub_owner/delete stanzas"
|
"Testing iq/pubsub_owner/delete stanzas"
|
||||||
iq = self.Iq()
|
iq = self.Iq()
|
||||||
iq['pubsub_owner']['delete']['node'] = 'thingers'
|
iq['pubsub_owner']['delete']['node'] = 'thingers'
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq id="0">
|
<iq id="0">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
|
||||||
<delete node="thingers" />
|
<delete node="thingers" />
|
||||||
|
@ -300,7 +300,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
'label': 'Deliver notification only to available users'}),
|
'label': 'Deliver notification only to available users'}),
|
||||||
])
|
])
|
||||||
|
|
||||||
self.check_iq(iq, """
|
self.check(iq, """
|
||||||
<iq to="pubsub.asdf" type="set" id="E" from="fritzy@asdf/87292ede-524d-4117-9076-d934ed3db8e7">
|
<iq to="pubsub.asdf" type="set" id="E" from="fritzy@asdf/87292ede-524d-4117-9076-d934ed3db8e7">
|
||||||
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
<pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
<create node="testnode2" />
|
<create node="testnode2" />
|
||||||
|
@ -357,7 +357,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
msg['pubsub_event']['items'].append(item)
|
msg['pubsub_event']['items'].append(item)
|
||||||
msg['pubsub_event']['items']['node'] = 'cheese'
|
msg['pubsub_event']['items']['node'] = 'cheese'
|
||||||
msg['type'] = 'normal'
|
msg['type'] = 'normal'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="normal">
|
<message type="normal">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<items node="cheese">
|
<items node="cheese">
|
||||||
|
@ -383,7 +383,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
msg['pubsub_event']['items'].append(item2)
|
msg['pubsub_event']['items'].append(item2)
|
||||||
msg['pubsub_event']['items']['node'] = 'cheese'
|
msg['pubsub_event']['items']['node'] = 'cheese'
|
||||||
msg['type'] = 'normal'
|
msg['type'] = 'normal'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="normal">
|
<message type="normal">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<items node="cheese">
|
<items node="cheese">
|
||||||
|
@ -415,7 +415,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
msg['pubsub_event']['items'].append(item2)
|
msg['pubsub_event']['items'].append(item2)
|
||||||
msg['pubsub_event']['items']['node'] = 'cheese'
|
msg['pubsub_event']['items']['node'] = 'cheese'
|
||||||
msg['type'] = 'normal'
|
msg['type'] = 'normal'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="normal">
|
<message type="normal">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<items node="cheese">
|
<items node="cheese">
|
||||||
|
@ -435,7 +435,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
msg['pubsub_event']['collection']['associate']['node'] = 'cheese'
|
msg['pubsub_event']['collection']['associate']['node'] = 'cheese'
|
||||||
msg['pubsub_event']['collection']['node'] = 'cheeseburger'
|
msg['pubsub_event']['collection']['node'] = 'cheeseburger'
|
||||||
msg['type'] = 'headline'
|
msg['type'] = 'headline'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="headline">
|
<message type="headline">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<collection node="cheeseburger">
|
<collection node="cheeseburger">
|
||||||
|
@ -450,7 +450,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
msg['pubsub_event']['collection']['disassociate']['node'] = 'cheese'
|
msg['pubsub_event']['collection']['disassociate']['node'] = 'cheese'
|
||||||
msg['pubsub_event']['collection']['node'] = 'cheeseburger'
|
msg['pubsub_event']['collection']['node'] = 'cheeseburger'
|
||||||
msg['type'] = 'headline'
|
msg['type'] = 'headline'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="headline">
|
<message type="headline">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<collection node="cheeseburger">
|
<collection node="cheeseburger">
|
||||||
|
@ -467,7 +467,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value='This thing is awesome')
|
value='This thing is awesome')
|
||||||
msg['type'] = 'headline'
|
msg['type'] = 'headline'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="headline">
|
<message type="headline">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<configuration node="cheese">
|
<configuration node="cheese">
|
||||||
|
@ -485,7 +485,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['pubsub_event']['purge']['node'] = 'pickles'
|
msg['pubsub_event']['purge']['node'] = 'pickles'
|
||||||
msg['type'] = 'headline'
|
msg['type'] = 'headline'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="headline">
|
<message type="headline">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<purge node="pickles" />
|
<purge node="pickles" />
|
||||||
|
@ -501,7 +501,7 @@ class TestPubsubStanzas(SleekTest):
|
||||||
msg['pubsub_event']['subscription']['subscription'] = 'subscribed'
|
msg['pubsub_event']['subscription']['subscription'] = 'subscribed'
|
||||||
msg['pubsub_event']['subscription']['expiry'] = 'presence'
|
msg['pubsub_event']['subscription']['expiry'] = 'presence'
|
||||||
msg['type'] = 'headline'
|
msg['type'] = 'headline'
|
||||||
self.check_message(msg, """
|
self.check(msg, """
|
||||||
<message type="headline">
|
<message type="headline">
|
||||||
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
||||||
<subscription node="pickles" subid="aabb1122" jid="fritzy@netflint.net/test" subscription="subscribed" expiry="presence" />
|
<subscription node="pickles" subid="aabb1122" jid="fritzy@netflint.net/test" subscription="subscribed" expiry="presence" />
|
||||||
|
|
|
@ -21,24 +21,24 @@ class TestChatStates(SleekTest):
|
||||||
|
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['chat_state'].active()
|
msg['chat_state'].active()
|
||||||
self.check_message(msg, xmlstring % 'active',
|
self.check(msg, xmlstring % 'active',
|
||||||
use_values=False)
|
use_values=False)
|
||||||
|
|
||||||
msg['chat_state'].composing()
|
msg['chat_state'].composing()
|
||||||
self.check_message(msg, xmlstring % 'composing',
|
self.check(msg, xmlstring % 'composing',
|
||||||
use_values=False)
|
use_values=False)
|
||||||
|
|
||||||
|
|
||||||
msg['chat_state'].gone()
|
msg['chat_state'].gone()
|
||||||
self.check_message(msg, xmlstring % 'gone',
|
self.check(msg, xmlstring % 'gone',
|
||||||
use_values=False)
|
use_values=False)
|
||||||
|
|
||||||
msg['chat_state'].inactive()
|
msg['chat_state'].inactive()
|
||||||
self.check_message(msg, xmlstring % 'inactive',
|
self.check(msg, xmlstring % 'inactive',
|
||||||
use_values=False)
|
use_values=False)
|
||||||
|
|
||||||
msg['chat_state'].paused()
|
msg['chat_state'].paused()
|
||||||
self.check_message(msg, xmlstring % 'paused',
|
self.check(msg, xmlstring % 'paused',
|
||||||
use_values=False)
|
use_values=False)
|
||||||
|
|
||||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestChatStates)
|
suite = unittest.TestLoader().loadTestsFromTestCase(TestChatStates)
|
||||||
|
|
|
@ -19,13 +19,13 @@ class TestStreamTester(SleekTest):
|
||||||
|
|
||||||
self.xmpp.add_event_handler('message', echo)
|
self.xmpp.add_event_handler('message', echo)
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<message to="tester@localhost" from="user@localhost">
|
<message to="tester@localhost" from="user@localhost">
|
||||||
<body>Hi!</body>
|
<body>Hi!</body>
|
||||||
</message>
|
</message>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_message("""
|
self.send("""
|
||||||
<message to="user@localhost">
|
<message to="user@localhost">
|
||||||
<body>Thanks for sending: Hi!</body>
|
<body>Thanks for sending: Hi!</body>
|
||||||
</message>
|
</message>
|
||||||
|
@ -40,13 +40,13 @@ class TestStreamTester(SleekTest):
|
||||||
|
|
||||||
self.xmpp.add_event_handler('message', echo)
|
self.xmpp.add_event_handler('message', echo)
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<message to="tester.localhost" from="user@localhost">
|
<message to="tester.localhost" from="user@localhost">
|
||||||
<body>Hi!</body>
|
<body>Hi!</body>
|
||||||
</message>
|
</message>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_message("""
|
self.send("""
|
||||||
<message to="user@localhost" from="tester.localhost">
|
<message to="user@localhost" from="tester.localhost">
|
||||||
<body>Thanks for sending: Hi!</body>
|
<body>Thanks for sending: Hi!</body>
|
||||||
</message>
|
</message>
|
||||||
|
@ -55,6 +55,6 @@ class TestStreamTester(SleekTest):
|
||||||
def testSendStreamHeader(self):
|
def testSendStreamHeader(self):
|
||||||
"""Test that we can check a sent stream header."""
|
"""Test that we can check a sent stream header."""
|
||||||
self.stream_start(mode='client', skip=False)
|
self.stream_start(mode='client', skip=False)
|
||||||
self.stream_send_header(sto='localhost')
|
self.send_header(sto='localhost')
|
||||||
|
|
||||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamTester)
|
suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamTester)
|
||||||
|
|
|
@ -26,13 +26,13 @@ class TestStreamExceptions(SleekTest):
|
||||||
self.stream_start()
|
self.stream_start()
|
||||||
self.xmpp.add_event_handler('message', message)
|
self.xmpp.add_event_handler('message', message)
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<message>
|
<message>
|
||||||
<body>This is going to cause an error.</body>
|
<body>This is going to cause an error.</body>
|
||||||
</message>
|
</message>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_message("""
|
self.send("""
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<feature-not-implemented
|
<feature-not-implemented
|
||||||
|
@ -57,13 +57,13 @@ class TestStreamExceptions(SleekTest):
|
||||||
self.xmpp.add_event_handler('message', message,
|
self.xmpp.add_event_handler('message', message,
|
||||||
threaded=True)
|
threaded=True)
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<message>
|
<message>
|
||||||
<body>This is going to cause an error.</body>
|
<body>This is going to cause an error.</body>
|
||||||
</message>
|
</message>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_message("""
|
self.send("""
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<feature-not-implemented
|
<feature-not-implemented
|
||||||
|
@ -84,14 +84,14 @@ class TestStreamExceptions(SleekTest):
|
||||||
self.stream_start()
|
self.stream_start()
|
||||||
self.xmpp.add_event_handler('message', message)
|
self.xmpp.add_event_handler('message', message)
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<message>
|
<message>
|
||||||
<body>This is going to cause an error.</body>
|
<body>This is going to cause an error.</body>
|
||||||
</message>
|
</message>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
if sys.version_info < (3, 0):
|
if sys.version_info < (3, 0):
|
||||||
self.stream_send_message("""
|
self.send("""
|
||||||
<message type="error">
|
<message type="error">
|
||||||
<error type="cancel">
|
<error type="cancel">
|
||||||
<undefined-condition
|
<undefined-condition
|
||||||
|
|
|
@ -30,11 +30,11 @@ class TestHandlers(SleekTest):
|
||||||
|
|
||||||
self.xmpp.registerHandler(callback)
|
self.xmpp.registerHandler(callback)
|
||||||
|
|
||||||
self.stream_recv("""<tester xmlns="test" />""")
|
self.recv("""<tester xmlns="test" />""")
|
||||||
|
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['body'] = 'Success!'
|
msg['body'] = 'Success!'
|
||||||
self.stream_send_message(msg)
|
self.send(msg)
|
||||||
|
|
||||||
def testWaiter(self):
|
def testWaiter(self):
|
||||||
"""Test using stream waiter handler."""
|
"""Test using stream waiter handler."""
|
||||||
|
@ -55,7 +55,7 @@ class TestHandlers(SleekTest):
|
||||||
self.xmpp.add_event_handler('message', waiter_handler, threaded=True)
|
self.xmpp.add_event_handler('message', waiter_handler, threaded=True)
|
||||||
|
|
||||||
# Send message to trigger waiter_handler
|
# Send message to trigger waiter_handler
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<message>
|
<message>
|
||||||
<body>Testing</body>
|
<body>Testing</body>
|
||||||
</message>
|
</message>
|
||||||
|
@ -66,10 +66,10 @@ class TestHandlers(SleekTest):
|
||||||
iq['id'] = 'test'
|
iq['id'] = 'test'
|
||||||
iq['type'] = 'set'
|
iq['type'] = 'set'
|
||||||
iq['query'] = 'test'
|
iq['query'] = 'test'
|
||||||
self.stream_send_iq(iq)
|
self.send(iq)
|
||||||
|
|
||||||
# Send the reply Iq
|
# Send the reply Iq
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<iq id="test" type="result">
|
<iq id="test" type="result">
|
||||||
<query xmlns="test" />
|
<query xmlns="test" />
|
||||||
</iq>
|
</iq>
|
||||||
|
@ -78,7 +78,7 @@ class TestHandlers(SleekTest):
|
||||||
# Check that waiter_handler received the reply
|
# Check that waiter_handler received the reply
|
||||||
msg = self.Message()
|
msg = self.Message()
|
||||||
msg['body'] = 'Successful: test'
|
msg['body'] = 'Successful: test'
|
||||||
self.stream_send_message(msg)
|
self.send(msg)
|
||||||
|
|
||||||
def testWaiterTimeout(self):
|
def testWaiterTimeout(self):
|
||||||
"""Test that waiter handler is removed after timeout."""
|
"""Test that waiter handler is removed after timeout."""
|
||||||
|
@ -93,14 +93,14 @@ class TestHandlers(SleekTest):
|
||||||
self.xmpp.add_event_handler('message', waiter_handler, threaded=True)
|
self.xmpp.add_event_handler('message', waiter_handler, threaded=True)
|
||||||
|
|
||||||
# Start test by triggerig waiter_handler
|
# Start test by triggerig waiter_handler
|
||||||
self.stream_recv("""<message><body>Start Test</body></message>""")
|
self.recv("""<message><body>Start Test</body></message>""")
|
||||||
|
|
||||||
# Check that Iq was sent to trigger start of timeout period
|
# Check that Iq was sent to trigger start of timeout period
|
||||||
iq = self.Iq()
|
iq = self.Iq()
|
||||||
iq['id'] = 'test2'
|
iq['id'] = 'test2'
|
||||||
iq['type'] = 'set'
|
iq['type'] = 'set'
|
||||||
iq['query'] = 'test2'
|
iq['query'] = 'test2'
|
||||||
self.stream_send_iq(iq)
|
self.send(iq)
|
||||||
|
|
||||||
# Check that the waiter is no longer registered
|
# Check that the waiter is no longer registered
|
||||||
waiter_exists = self.xmpp.removeHandler('IqWait_test2')
|
waiter_exists = self.xmpp.removeHandler('IqWait_test2')
|
||||||
|
|
|
@ -29,10 +29,10 @@ class TestStreamPresence(SleekTest):
|
||||||
self.xmpp.add_event_handler('got_offline', got_offline)
|
self.xmpp.add_event_handler('got_offline', got_offline)
|
||||||
self.xmpp.add_event_handler('presence_unavailable', unavailable)
|
self.xmpp.add_event_handler('presence_unavailable', unavailable)
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<presence from="otheruser@localhost"
|
<presence type="unavailable"
|
||||||
to="tester@localhost"
|
from="otheruser@localhost"
|
||||||
type="unavailable" />
|
to="tester@localhost"/>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Give event queue time to process.
|
# Give event queue time to process.
|
||||||
|
@ -56,7 +56,7 @@ class TestStreamPresence(SleekTest):
|
||||||
#
|
#
|
||||||
# We use the stream to initialize the roster to make
|
# We use the stream to initialize the roster to make
|
||||||
# the test independent of the roster implementation.
|
# the test independent of the roster implementation.
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<iq type="set">
|
<iq type="set">
|
||||||
<query xmlns="jabber:iq:roster">
|
<query xmlns="jabber:iq:roster">
|
||||||
<item jid="otheruser@localhost"
|
<item jid="otheruser@localhost"
|
||||||
|
@ -69,13 +69,13 @@ class TestStreamPresence(SleekTest):
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Contact comes online.
|
# Contact comes online.
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<presence from="otheruser@localhost/foobar"
|
<presence from="otheruser@localhost/foobar"
|
||||||
to="tester@localhost" />
|
to="tester@localhost" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Contact goes offline, should trigger got_offline.
|
# Contact goes offline, should trigger got_offline.
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<presence from="otheruser@localhost/foobar"
|
<presence from="otheruser@localhost/foobar"
|
||||||
to="tester@localhost"
|
to="tester@localhost"
|
||||||
type="unavailable" />
|
type="unavailable" />
|
||||||
|
@ -102,7 +102,7 @@ class TestStreamPresence(SleekTest):
|
||||||
self.xmpp.add_event_handler('presence_available', presence_available)
|
self.xmpp.add_event_handler('presence_available', presence_available)
|
||||||
self.xmpp.add_event_handler('got_online', got_online)
|
self.xmpp.add_event_handler('got_online', got_online)
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<presence from="user@localhost"
|
<presence from="user@localhost"
|
||||||
to="tester@localhost" />
|
to="tester@localhost" />
|
||||||
""")
|
""")
|
||||||
|
@ -140,22 +140,22 @@ class TestStreamPresence(SleekTest):
|
||||||
self.xmpp.auto_authorize = True
|
self.xmpp.auto_authorize = True
|
||||||
self.xmpp.auto_subscribe = True
|
self.xmpp.auto_subscribe = True
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<presence from="user@localhost"
|
<presence from="user@localhost"
|
||||||
to="tester@localhost"
|
to="tester@localhost"
|
||||||
type="subscribe" />
|
type="subscribe" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_presence("""
|
self.send("""
|
||||||
<presence to="user@localhost"
|
<presence to="user@localhost"
|
||||||
type="subscribed" />
|
type="subscribed" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_presence("""
|
self.send("""
|
||||||
<presence to="user@localhost" />
|
<presence to="user@localhost" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_presence("""
|
self.send("""
|
||||||
<presence to="user@localhost"
|
<presence to="user@localhost"
|
||||||
type="subscribe" />
|
type="subscribe" />
|
||||||
""")
|
""")
|
||||||
|
@ -185,13 +185,13 @@ class TestStreamPresence(SleekTest):
|
||||||
# With this setting we should reject all subscriptions.
|
# With this setting we should reject all subscriptions.
|
||||||
self.xmpp.roster['tester@localhost'].auto_authorize = False
|
self.xmpp.roster['tester@localhost'].auto_authorize = False
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<presence from="user@localhost"
|
<presence from="user@localhost"
|
||||||
to="tester@localhost"
|
to="tester@localhost"
|
||||||
type="subscribe" />
|
type="subscribe" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.stream_send_presence("""
|
self.send("""
|
||||||
<presence to="user@localhost"
|
<presence to="user@localhost"
|
||||||
type="unsubscribed" />
|
type="unsubscribed" />
|
||||||
""")
|
""")
|
||||||
|
|
|
@ -19,12 +19,12 @@ class TestStreamRoster(SleekTest):
|
||||||
t = threading.Thread(name='get_roster', target=self.xmpp.get_roster)
|
t = threading.Thread(name='get_roster', target=self.xmpp.get_roster)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
self.stream_send_iq("""
|
self.send("""
|
||||||
<iq type="get" id="1">
|
<iq type="get" id="1">
|
||||||
<query xmlns="jabber:iq:roster" />
|
<query xmlns="jabber:iq:roster" />
|
||||||
</iq>
|
</iq>
|
||||||
""")
|
""")
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<iq to='tester@localhost' type="result" id="1">
|
<iq to='tester@localhost' type="result" id="1">
|
||||||
<query xmlns="jabber:iq:roster">
|
<query xmlns="jabber:iq:roster">
|
||||||
<item jid="user@localhost"
|
<item jid="user@localhost"
|
||||||
|
@ -41,7 +41,6 @@ class TestStreamRoster(SleekTest):
|
||||||
# Wait for get_roster to return.
|
# Wait for get_roster to return.
|
||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
print self.xmpp.roster['tester@localhost']['user@localhost']._state
|
|
||||||
self.check_roster('tester@localhost', 'user@localhost',
|
self.check_roster('tester@localhost', 'user@localhost',
|
||||||
name='User',
|
name='User',
|
||||||
subscription='from',
|
subscription='from',
|
||||||
|
@ -53,7 +52,7 @@ class TestStreamRoster(SleekTest):
|
||||||
"""Test handling pushed roster updates."""
|
"""Test handling pushed roster updates."""
|
||||||
self.stream_start(mode='client', jid='tester@localhost')
|
self.stream_start(mode='client', jid='tester@localhost')
|
||||||
|
|
||||||
self.stream_recv("""
|
self.recv("""
|
||||||
<iq to='tester@localhost' type="set" id="1">
|
<iq to='tester@localhost' type="set" id="1">
|
||||||
<query xmlns="jabber:iq:roster">
|
<query xmlns="jabber:iq:roster">
|
||||||
<item jid="user@localhost"
|
<item jid="user@localhost"
|
||||||
|
@ -65,7 +64,7 @@ class TestStreamRoster(SleekTest):
|
||||||
</query>
|
</query>
|
||||||
</iq>
|
</iq>
|
||||||
""")
|
""")
|
||||||
self.stream_send_iq("""
|
self.send("""
|
||||||
<iq type="result" id="1">
|
<iq type="result" id="1">
|
||||||
<query xmlns="jabber:iq:roster" />
|
<query xmlns="jabber:iq:roster" />
|
||||||
</iq>
|
</iq>
|
||||||
|
|
Loading…
Reference in a new issue