Logging no longer uses root logger.
Each module should now log into its own logger.
This commit is contained in:
parent
d0c506f930
commit
4fb77ac878
@ -26,6 +26,9 @@ from sleekxmpp.xmlstream.matcher import *
|
|||||||
from sleekxmpp.xmlstream.handler import *
|
from sleekxmpp.xmlstream.handler import *
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# Flag indicating if DNS SRV records are available for use.
|
# Flag indicating if DNS SRV records are available for use.
|
||||||
SRV_SUPPORT = True
|
SRV_SUPPORT = True
|
||||||
try:
|
try:
|
||||||
@ -192,9 +195,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):
|
||||||
"""
|
"""
|
||||||
@ -228,7 +231,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):
|
||||||
@ -446,12 +449,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
|
||||||
@ -459,12 +462,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
|
||||||
@ -472,12 +475,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
|
||||||
@ -485,12 +488,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
|
||||||
@ -498,17 +501,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):
|
||||||
@ -588,7 +591,7 @@ class BaseXMPP(XMLStream):
|
|||||||
# disconnects. Determine if this was the last connection
|
# disconnects. Determine if this was the last connection
|
||||||
# for the JID.
|
# for the JID.
|
||||||
if show == 'unavailable':
|
if show == 'unavailable':
|
||||||
logging.debug("%s %s got offline" % (jid, resource))
|
log.debug("%s %s got offline" % (jid, resource))
|
||||||
del connections[resource]
|
del connections[resource]
|
||||||
|
|
||||||
if not connections and not self.roster[jid]['in_roster']:
|
if not connections and not self.roster[jid]['in_roster']:
|
||||||
@ -604,7 +607,7 @@ class BaseXMPP(XMLStream):
|
|||||||
self.event("changed_status", presence)
|
self.event("changed_status", presence)
|
||||||
if got_online:
|
if got_online:
|
||||||
self.event("got_online", presence)
|
self.event("got_online", presence)
|
||||||
logging.debug("STATUS: %s%s/%s[%s]: %s" % (name, jid, resource,
|
log.debug("STATUS: %s%s/%s[%s]: %s" % (name, jid, resource,
|
||||||
show, status))
|
show, status))
|
||||||
|
|
||||||
def _handle_subscribe(self, presence):
|
def _handle_subscribe(self, presence):
|
||||||
|
@ -32,6 +32,9 @@ except:
|
|||||||
SRV_SUPPORT = False
|
SRV_SUPPORT = False
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ClientXMPP(BaseXMPP):
|
class ClientXMPP(BaseXMPP):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -133,7 +136,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()):
|
||||||
@ -150,19 +153,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:
|
||||||
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.
|
||||||
@ -276,7 +279,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
|
||||||
|
|
||||||
@ -286,7 +289,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()
|
||||||
|
|
||||||
@ -300,7 +303,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,
|
||||||
@ -334,7 +337,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
|
||||||
|
|
||||||
@ -356,7 +359,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()
|
||||||
|
|
||||||
@ -367,7 +370,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:
|
||||||
@ -381,10 +384,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")
|
||||||
@ -399,7 +402,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")
|
||||||
|
@ -22,6 +22,9 @@ 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)
|
||||||
|
@ -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'
|
||||||
@ -34,12 +37,12 @@ class MailBox(ElementBase):
|
|||||||
namespace = 'google:mail:notify'
|
namespace = 'google:mail:notify'
|
||||||
name = 'mailbox'
|
name = 'mailbox'
|
||||||
plugin_attrib = 'mailbox'
|
plugin_attrib = 'mailbox'
|
||||||
interfaces = set(('result-time', 'total-matched', 'total-estimate',
|
interfaces = set(('result-time', 'total-matched', 'total-estimate',
|
||||||
'url', 'threads', 'matched', 'estimate'))
|
'url', 'threads', 'matched', 'estimate'))
|
||||||
|
|
||||||
def getThreads(self):
|
def getThreads(self):
|
||||||
threads = []
|
threads = []
|
||||||
for threadXML in self.xml.findall('{%s}%s' % (MailThread.namespace,
|
for threadXML in self.xml.findall('{%s}%s' % (MailThread.namespace,
|
||||||
MailThread.name)):
|
MailThread.name)):
|
||||||
threads.append(MailThread(xml=threadXML, parent=None))
|
threads.append(MailThread(xml=threadXML, parent=None))
|
||||||
return threads
|
return threads
|
||||||
@ -55,10 +58,10 @@ class MailThread(ElementBase):
|
|||||||
namespace = 'google:mail:notify'
|
namespace = 'google:mail:notify'
|
||||||
name = 'mail-thread-info'
|
name = 'mail-thread-info'
|
||||||
plugin_attrib = 'thread'
|
plugin_attrib = 'thread'
|
||||||
interfaces = set(('tid', 'participation', 'messages', 'date',
|
interfaces = set(('tid', 'participation', 'messages', 'date',
|
||||||
'senders', 'url', 'labels', 'subject', 'snippet'))
|
'senders', 'url', 'labels', 'subject', 'snippet'))
|
||||||
sub_interfaces = set(('labels', 'subject', 'snippet'))
|
sub_interfaces = set(('labels', 'subject', 'snippet'))
|
||||||
|
|
||||||
def getSenders(self):
|
def getSenders(self):
|
||||||
senders = []
|
senders = []
|
||||||
sendersXML = self.xml.find('{%s}senders' % self.namespace)
|
sendersXML = self.xml.find('{%s}senders' % self.namespace)
|
||||||
@ -91,13 +94,13 @@ class gmail_notify(base.base_plugin):
|
|||||||
"""
|
"""
|
||||||
Google Talk: Gmail Notifications
|
Google Talk: Gmail Notifications
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.description = 'Google Talk: Gmail Notifications'
|
self.description = 'Google Talk: Gmail Notifications'
|
||||||
|
|
||||||
self.xmpp.registerHandler(
|
self.xmpp.registerHandler(
|
||||||
Callback('Gmail Result',
|
Callback('Gmail Result',
|
||||||
MatchXPath('{%s}iq/{%s}%s' % (self.xmpp.default_ns,
|
MatchXPath('{%s}iq/{%s}%s' % (self.xmpp.default_ns,
|
||||||
MailBox.namespace,
|
MailBox.namespace,
|
||||||
MailBox.name)),
|
MailBox.name)),
|
||||||
self.handle_gmail))
|
self.handle_gmail))
|
||||||
@ -108,7 +111,7 @@ class gmail_notify(base.base_plugin):
|
|||||||
NewMail.namespace,
|
NewMail.namespace,
|
||||||
NewMail.name)),
|
NewMail.name)),
|
||||||
self.handle_new_mail))
|
self.handle_new_mail))
|
||||||
|
|
||||||
registerStanzaPlugin(Iq, GmailQuery)
|
registerStanzaPlugin(Iq, GmailQuery)
|
||||||
registerStanzaPlugin(Iq, MailBox)
|
registerStanzaPlugin(Iq, MailBox)
|
||||||
registerStanzaPlugin(Iq, NewMail)
|
registerStanzaPlugin(Iq, NewMail)
|
||||||
@ -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,15 +3,19 @@ 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'
|
||||||
self.description = "Job distribution over Pubsub"
|
self.description = "Job distribution over Pubsub"
|
||||||
|
|
||||||
def post_init(self):
|
def post_init(self):
|
||||||
pass
|
pass
|
||||||
#TODO add event
|
#TODO add event
|
||||||
|
|
||||||
def createJobNode(self, host, jid, node, config=None):
|
def createJobNode(self, host, jid, node, config=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
|
@ -2,42 +2,46 @@
|
|||||||
SleekXMPP: The Sleek XMPP Library
|
SleekXMPP: The Sleek XMPP Library
|
||||||
Copyright (C) 2010 Nathanael C. Fritz
|
Copyright (C) 2010 Nathanael C. Fritz
|
||||||
This file is part of SleekXMPP.
|
This file is part of SleekXMPP.
|
||||||
|
|
||||||
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):
|
||||||
self.xep = '0004'
|
self.xep = '0004'
|
||||||
self.description = '*Deprecated Data Forms'
|
self.description = '*Deprecated Data Forms'
|
||||||
self.xmpp.add_handler("<message><x xmlns='jabber:x:data' /></message>", self.handler_message_xform, name='Old Message Form')
|
self.xmpp.add_handler("<message><x xmlns='jabber:x:data' /></message>", self.handler_message_xform, name='Old Message Form')
|
||||||
|
|
||||||
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)
|
||||||
self.xmpp.event("message_form", object)
|
self.xmpp.event("message_form", object)
|
||||||
|
|
||||||
def handler_presence_xform(self, xml):
|
def handler_presence_xform(self, xml):
|
||||||
object = self.handle_form(xml)
|
object = self.handle_form(xml)
|
||||||
self.xmpp.event("presence_form", object)
|
self.xmpp.event("presence_form", object)
|
||||||
|
|
||||||
def handle_form(self, xml):
|
def handle_form(self, xml):
|
||||||
xmlform = xml.find('{jabber:x:data}x')
|
xmlform = xml.find('{jabber:x:data}x')
|
||||||
object = self.buildForm(xmlform)
|
object = self.buildForm(xmlform)
|
||||||
self.xmpp.event("message_xform", object)
|
self.xmpp.event("message_xform", object)
|
||||||
return object
|
return object
|
||||||
|
|
||||||
def buildForm(self, xml):
|
def buildForm(self, xml):
|
||||||
form = Form(ftype=xml.attrib['type'])
|
form = Form(ftype=xml.attrib['type'])
|
||||||
form.fromXML(xml)
|
form.fromXML(xml)
|
||||||
@ -51,12 +55,12 @@ class FieldContainer(object):
|
|||||||
self.fields = []
|
self.fields = []
|
||||||
self.field = {}
|
self.field = {}
|
||||||
self.stanza = stanza
|
self.stanza = stanza
|
||||||
|
|
||||||
def addField(self, var, ftype='text-single', label='', desc='', required=False, value=None):
|
def addField(self, var, ftype='text-single', label='', desc='', required=False, value=None):
|
||||||
self.field[var] = FormField(var, ftype, label, desc, required, value)
|
self.field[var] = FormField(var, ftype, label, desc, required, value)
|
||||||
self.fields.append(self.field[var])
|
self.fields.append(self.field[var])
|
||||||
return self.field[var]
|
return self.field[var]
|
||||||
|
|
||||||
def buildField(self, xml):
|
def buildField(self, xml):
|
||||||
self.field[xml.get('var', '__unnamed__')] = FormField(xml.get('var', '__unnamed__'), xml.get('type', 'text-single'))
|
self.field[xml.get('var', '__unnamed__')] = FormField(xml.get('var', '__unnamed__'), xml.get('type', 'text-single'))
|
||||||
self.fields.append(self.field[xml.get('var', '__unnamed__')])
|
self.fields.append(self.field[xml.get('var', '__unnamed__')])
|
||||||
@ -66,13 +70,13 @@ class FieldContainer(object):
|
|||||||
self.stanza = xml.tag
|
self.stanza = xml.tag
|
||||||
for field in xml.findall('{jabber:x:data}field'):
|
for field in xml.findall('{jabber:x:data}field'):
|
||||||
self.buildField(field)
|
self.buildField(field)
|
||||||
|
|
||||||
def getXML(self, ftype):
|
def getXML(self, ftype):
|
||||||
container = ET.Element(self.stanza)
|
container = ET.Element(self.stanza)
|
||||||
for field in self.fields:
|
for field in self.fields:
|
||||||
container.append(field.getXML(ftype))
|
container.append(field.getXML(ftype))
|
||||||
return container
|
return container
|
||||||
|
|
||||||
class Form(FieldContainer):
|
class Form(FieldContainer):
|
||||||
types = ('form', 'submit', 'cancel', 'result')
|
types = ('form', 'submit', 'cancel', 'result')
|
||||||
def __init__(self, xmpp=None, ftype='form', title='', instructions=''):
|
def __init__(self, xmpp=None, ftype='form', title='', instructions=''):
|
||||||
@ -85,7 +89,7 @@ class Form(FieldContainer):
|
|||||||
self.instructions = instructions
|
self.instructions = instructions
|
||||||
self.reported = []
|
self.reported = []
|
||||||
self.items = []
|
self.items = []
|
||||||
|
|
||||||
def merge(self, form2):
|
def merge(self, form2):
|
||||||
form1 = Form(ftype=self.type)
|
form1 = Form(ftype=self.type)
|
||||||
form1.fromXML(self.getXML(self.type))
|
form1.fromXML(self.getXML(self.type))
|
||||||
@ -98,18 +102,18 @@ class Form(FieldContainer):
|
|||||||
if (option, label) not in form1.field[field.var].options:
|
if (option, label) not in form1.field[field.var].options:
|
||||||
form1.fields[field.var].addOption(option, label)
|
form1.fields[field.var].addOption(option, label)
|
||||||
return form1
|
return form1
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
newform = Form(ftype=self.type)
|
newform = Form(ftype=self.type)
|
||||||
newform.fromXML(self.getXML(self.type))
|
newform.fromXML(self.getXML(self.type))
|
||||||
return newform
|
return newform
|
||||||
|
|
||||||
def update(self, form):
|
def update(self, form):
|
||||||
values = form.getValues()
|
values = form.getValues()
|
||||||
for var in values:
|
for var in values:
|
||||||
if var in self.fields:
|
if var in self.fields:
|
||||||
self.fields[var].setValue(self.fields[var])
|
self.fields[var].setValue(self.fields[var])
|
||||||
|
|
||||||
def getValues(self):
|
def getValues(self):
|
||||||
result = {}
|
result = {}
|
||||||
for field in self.fields:
|
for field in self.fields:
|
||||||
@ -118,7 +122,7 @@ class Form(FieldContainer):
|
|||||||
value = value[0]
|
value = value[0]
|
||||||
result[field.var] = value
|
result[field.var] = value
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def setValues(self, values={}):
|
def setValues(self, values={}):
|
||||||
for field in values:
|
for field in values:
|
||||||
if field in self.field:
|
if field in self.field:
|
||||||
@ -127,10 +131,10 @@ class Form(FieldContainer):
|
|||||||
self.field[field].setValue(value)
|
self.field[field].setValue(value)
|
||||||
else:
|
else:
|
||||||
self.field[field].setValue(values[field])
|
self.field[field].setValue(values[field])
|
||||||
|
|
||||||
def fromXML(self, xml):
|
def fromXML(self, xml):
|
||||||
self.buildForm(xml)
|
self.buildForm(xml)
|
||||||
|
|
||||||
def addItem(self):
|
def addItem(self):
|
||||||
newitem = FieldContainer('item')
|
newitem = FieldContainer('item')
|
||||||
self.items.append(newitem)
|
self.items.append(newitem)
|
||||||
@ -148,21 +152,21 @@ class Form(FieldContainer):
|
|||||||
def buildReported(self, xml):
|
def buildReported(self, xml):
|
||||||
reported = self.addReported()
|
reported = self.addReported()
|
||||||
reported.buildContainer(xml)
|
reported.buildContainer(xml)
|
||||||
|
|
||||||
def setTitle(self, title):
|
def setTitle(self, title):
|
||||||
self.title = title
|
self.title = title
|
||||||
|
|
||||||
def setInstructions(self, instructions):
|
def setInstructions(self, instructions):
|
||||||
self.instructions = instructions
|
self.instructions = instructions
|
||||||
|
|
||||||
def setType(self, ftype):
|
def setType(self, ftype):
|
||||||
self.type = ftype
|
self.type = ftype
|
||||||
|
|
||||||
def getXMLMessage(self, to):
|
def getXMLMessage(self, to):
|
||||||
msg = self.xmpp.makeMessage(to)
|
msg = self.xmpp.makeMessage(to)
|
||||||
msg.append(self.getXML())
|
msg.append(self.getXML())
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def buildForm(self, xml):
|
def buildForm(self, xml):
|
||||||
self.type = xml.get('type', 'form')
|
self.type = xml.get('type', 'form')
|
||||||
if xml.find('{jabber:x:data}title') is not None:
|
if xml.find('{jabber:x:data}title') is not None:
|
||||||
@ -175,7 +179,7 @@ class Form(FieldContainer):
|
|||||||
self.buildReported(reported)
|
self.buildReported(reported)
|
||||||
for item in xml.findall('{jabber:x:data}item'):
|
for item in xml.findall('{jabber:x:data}item'):
|
||||||
self.buildItem(item)
|
self.buildItem(item)
|
||||||
|
|
||||||
#def getXML(self, tostring = False):
|
#def getXML(self, tostring = False):
|
||||||
def getXML(self, ftype=None):
|
def getXML(self, ftype=None):
|
||||||
if ftype:
|
if ftype:
|
||||||
@ -199,7 +203,7 @@ class Form(FieldContainer):
|
|||||||
#if tostring:
|
#if tostring:
|
||||||
# form = self.xmpp.tostring(form)
|
# form = self.xmpp.tostring(form)
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def getXHTML(self):
|
def getXHTML(self):
|
||||||
form = ET.Element('{http://www.w3.org/1999/xhtml}form')
|
form = ET.Element('{http://www.w3.org/1999/xhtml}form')
|
||||||
if self.title:
|
if self.title:
|
||||||
@ -217,8 +221,8 @@ class Form(FieldContainer):
|
|||||||
for field in self.items:
|
for field in self.items:
|
||||||
form.append(field.getXHTML())
|
form.append(field.getXHTML())
|
||||||
return form
|
return form
|
||||||
|
|
||||||
|
|
||||||
def makeSubmit(self):
|
def makeSubmit(self):
|
||||||
self.setType('submit')
|
self.setType('submit')
|
||||||
|
|
||||||
@ -246,13 +250,13 @@ class FormField(object):
|
|||||||
self.islinebreak = False
|
self.islinebreak = False
|
||||||
if value:
|
if value:
|
||||||
self.setValue(value)
|
self.setValue(value)
|
||||||
|
|
||||||
def addOption(self, value, label):
|
def addOption(self, value, label):
|
||||||
if self.islist:
|
if self.islist:
|
||||||
self.options.append((value, label))
|
self.options.append((value, label))
|
||||||
else:
|
else:
|
||||||
raise ValueError("Cannot add options to non-list type field.")
|
raise ValueError("Cannot add options to non-list type field.")
|
||||||
|
|
||||||
def setTrue(self):
|
def setTrue(self):
|
||||||
if self.type == 'boolean':
|
if self.type == 'boolean':
|
||||||
self.value = [True]
|
self.value = [True]
|
||||||
@ -263,10 +267,10 @@ class FormField(object):
|
|||||||
|
|
||||||
def require(self):
|
def require(self):
|
||||||
self.required = True
|
self.required = True
|
||||||
|
|
||||||
def setDescription(self, desc):
|
def setDescription(self, desc):
|
||||||
self.desc = desc
|
self.desc = desc
|
||||||
|
|
||||||
def setValue(self, value):
|
def setValue(self, value):
|
||||||
if self.type == 'boolean':
|
if self.type == 'boolean':
|
||||||
if value in ('1', 1, True, 'true', 'True', 'yes'):
|
if value in ('1', 1, True, 'true', 'True', 'yes'):
|
||||||
@ -291,10 +295,10 @@ class FormField(object):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.value = ''
|
self.value = ''
|
||||||
|
|
||||||
def setAnswer(self, value):
|
def setAnswer(self, value):
|
||||||
self.setValue(value)
|
self.setValue(value)
|
||||||
|
|
||||||
def buildField(self, xml):
|
def buildField(self, xml):
|
||||||
self.type = xml.get('type', 'text-single')
|
self.type = xml.get('type', 'text-single')
|
||||||
self.label = xml.get('label', '')
|
self.label = xml.get('label', '')
|
||||||
@ -306,7 +310,7 @@ class FormField(object):
|
|||||||
self.require()
|
self.require()
|
||||||
if xml.find('{jabber:x:data}desc') is not None:
|
if xml.find('{jabber:x:data}desc') is not None:
|
||||||
self.setDescription(xml.find('{jabber:x:data}desc').text)
|
self.setDescription(xml.find('{jabber:x:data}desc').text)
|
||||||
|
|
||||||
def getXML(self, ftype):
|
def getXML(self, ftype):
|
||||||
field = ET.Element('{jabber:x:data}field')
|
field = ET.Element('{jabber:x:data}field')
|
||||||
if ftype != 'result':
|
if ftype != 'result':
|
||||||
@ -342,7 +346,7 @@ class FormField(object):
|
|||||||
valuexml.text = value
|
valuexml.text = value
|
||||||
field.append(valuexml)
|
field.append(valuexml)
|
||||||
return field
|
return field
|
||||||
|
|
||||||
def getXHTML(self):
|
def getXHTML(self):
|
||||||
field = ET.Element('div', {'class': 'xmpp-xforms-%s' % self.type})
|
field = ET.Element('div', {'class': 'xmpp-xforms-%s' % self.type})
|
||||||
if self.label:
|
if self.label:
|
||||||
@ -414,4 +418,4 @@ class FormField(object):
|
|||||||
pass
|
pass
|
||||||
label.append(formf)
|
label.append(formf)
|
||||||
return field
|
return field
|
||||||
|
|
||||||
|
@ -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'
|
||||||
@ -33,7 +36,7 @@ class Form(ElementBase):
|
|||||||
if title is not None:
|
if title is not None:
|
||||||
self['title'] = title
|
self['title'] = title
|
||||||
self.field = FieldAccessor(self)
|
self.field = FieldAccessor(self)
|
||||||
|
|
||||||
def setup(self, xml=None):
|
def setup(self, xml=None):
|
||||||
if ElementBase.setup(self, xml): #if we had to generate xml
|
if ElementBase.setup(self, xml): #if we had to generate xml
|
||||||
self['type'] = 'form'
|
self['type'] = 'form'
|
||||||
@ -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
|
||||||
|
|
||||||
@ -113,10 +116,10 @@ class Form(ElementBase):
|
|||||||
reportedXML = self.xml.find('{%s}reported' % self.namespace)
|
reportedXML = self.xml.find('{%s}reported' % self.namespace)
|
||||||
if reportedXML is not None:
|
if reportedXML is not None:
|
||||||
self.xml.remove(reportedXML)
|
self.xml.remove(reportedXML)
|
||||||
|
|
||||||
def getFields(self, use_dict=False):
|
def getFields(self, use_dict=False):
|
||||||
fields = {} if use_dict else []
|
fields = {} if use_dict else []
|
||||||
fieldsXML = self.xml.findall('{%s}field' % FormField.namespace)
|
fieldsXML = self.xml.findall('{%s}field' % FormField.namespace)
|
||||||
for fieldXML in fieldsXML:
|
for fieldXML in fieldsXML:
|
||||||
field = FormField(xml=fieldXML)
|
field = FormField(xml=fieldXML)
|
||||||
if use_dict:
|
if use_dict:
|
||||||
@ -144,7 +147,7 @@ class Form(ElementBase):
|
|||||||
|
|
||||||
def getReported(self):
|
def getReported(self):
|
||||||
fields = {}
|
fields = {}
|
||||||
fieldsXML = self.xml.findall('{%s}reported/{%s}field' % (self.namespace,
|
fieldsXML = self.xml.findall('{%s}reported/{%s}field' % (self.namespace,
|
||||||
FormField.namespace))
|
FormField.namespace))
|
||||||
for fieldXML in fieldsXML:
|
for fieldXML in fieldsXML:
|
||||||
field = FormField(xml=fieldXML)
|
field = FormField(xml=fieldXML)
|
||||||
@ -197,7 +200,7 @@ class Form(ElementBase):
|
|||||||
fields = self.getFields(use_dict=True)
|
fields = self.getFields(use_dict=True)
|
||||||
for field in values:
|
for field in values:
|
||||||
fields[field]['value'] = values[field]
|
fields[field]['value'] = values[field]
|
||||||
|
|
||||||
def merge(self, other):
|
def merge(self, other):
|
||||||
new = copy.copy(self)
|
new = copy.copy(self)
|
||||||
if type(other) == types.DictType:
|
if type(other) == types.DictType:
|
||||||
@ -212,7 +215,7 @@ class Form(ElementBase):
|
|||||||
class FieldAccessor(object):
|
class FieldAccessor(object):
|
||||||
def __init__(self, form):
|
def __init__(self, form):
|
||||||
self.form = form
|
self.form = form
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self.form.getFields(use_dict=True)[key]
|
return self.form.getFields(use_dict=True)[key]
|
||||||
|
|
||||||
@ -366,21 +369,21 @@ class xep_0004(base.base_plugin):
|
|||||||
|
|
||||||
self.xmpp.registerHandler(
|
self.xmpp.registerHandler(
|
||||||
Callback('Data Form',
|
Callback('Data Form',
|
||||||
MatchXPath('{%s}message/{%s}x' % (self.xmpp.default_ns,
|
MatchXPath('{%s}message/{%s}x' % (self.xmpp.default_ns,
|
||||||
Form.namespace)),
|
Form.namespace)),
|
||||||
self.handle_form))
|
self.handle_form))
|
||||||
|
|
||||||
registerStanzaPlugin(FormField, FieldOption)
|
registerStanzaPlugin(FormField, FieldOption)
|
||||||
registerStanzaPlugin(Form, FormField)
|
registerStanzaPlugin(Form, FormField)
|
||||||
registerStanzaPlugin(Message, Form)
|
registerStanzaPlugin(Message, Form)
|
||||||
|
|
||||||
def makeForm(self, ftype='form', title='', instructions=''):
|
def makeForm(self, ftype='form', title='', instructions=''):
|
||||||
f = Form()
|
f = Form()
|
||||||
f['type'] = ftype
|
f['type'] = ftype
|
||||||
f['title'] = title
|
f['title'] = title
|
||||||
f['instructions'] = instructions
|
f['instructions'] = instructions
|
||||||
return f
|
return f
|
||||||
|
|
||||||
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')
|
||||||
|
@ -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,6 +13,10 @@ 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'
|
||||||
@ -222,18 +226,18 @@ class xep_0030(base.base_plugin):
|
|||||||
|
|
||||||
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):
|
||||||
@ -248,13 +252,13 @@ class xep_0030(base.base_plugin):
|
|||||||
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'
|
||||||
@ -276,13 +280,13 @@ class xep_0030(base.base_plugin):
|
|||||||
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'
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
SleekXMPP: The Sleek XMPP Library
|
SleekXMPP: The Sleek XMPP Library
|
||||||
Copyright (C) 2010 Nathanael C. Fritz
|
Copyright (C) 2010 Nathanael C. Fritz
|
||||||
This file is part of SleekXMPP.
|
This file is part of SleekXMPP.
|
||||||
|
|
||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
@ -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'
|
||||||
@ -34,79 +38,79 @@ class MUCPresence(ElementBase):
|
|||||||
#TODO if no affilation, set it to the default and return default
|
#TODO if no affilation, set it to the default and return default
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
return item.get('affiliation', '')
|
return item.get('affiliation', '')
|
||||||
|
|
||||||
def setAffiliation(self, value):
|
def setAffiliation(self, value):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
#TODO check for valid affiliation
|
#TODO check for valid affiliation
|
||||||
item.attrib['affiliation'] = value
|
item.attrib['affiliation'] = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delAffiliation(self):
|
def delAffiliation(self):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
#TODO set default affiliation
|
#TODO set default affiliation
|
||||||
if 'affiliation' in item.attrib: del item.attrib['affiliation']
|
if 'affiliation' in item.attrib: del item.attrib['affiliation']
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getJid(self):
|
def getJid(self):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
return JID(item.get('jid', ''))
|
return JID(item.get('jid', ''))
|
||||||
|
|
||||||
def setJid(self, value):
|
def setJid(self, value):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
value = str(value)
|
value = str(value)
|
||||||
item.attrib['jid'] = value
|
item.attrib['jid'] = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delJid(self):
|
def delJid(self):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
if 'jid' in item.attrib: del item.attrib['jid']
|
if 'jid' in item.attrib: del item.attrib['jid']
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getRole(self):
|
def getRole(self):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
#TODO get default role, set default role if none
|
#TODO get default role, set default role if none
|
||||||
return item.get('role', '')
|
return item.get('role', '')
|
||||||
|
|
||||||
def setRole(self, value):
|
def setRole(self, value):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
#TODO check for valid role
|
#TODO check for valid role
|
||||||
item.attrib['role'] = value
|
item.attrib['role'] = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delRole(self):
|
def delRole(self):
|
||||||
item = self.getXMLItem()
|
item = self.getXMLItem()
|
||||||
#TODO set default role
|
#TODO set default role
|
||||||
if 'role' in item.attrib: del item.attrib['role']
|
if 'role' in item.attrib: del item.attrib['role']
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getNick(self):
|
def getNick(self):
|
||||||
return self.parent()['from'].resource
|
return self.parent()['from'].resource
|
||||||
|
|
||||||
def getRoom(self):
|
def getRoom(self):
|
||||||
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):
|
||||||
"""
|
"""
|
||||||
Impliments XEP-0045 Multi User Chat
|
Impliments XEP-0045 Multi User Chat
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.rooms = {}
|
self.rooms = {}
|
||||||
self.ourNicks = {}
|
self.ourNicks = {}
|
||||||
@ -116,7 +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))
|
||||||
|
|
||||||
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,27 +139,27 @@ 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:
|
||||||
self.xmpp.event("muc::%s::got_offline" % entry['room'], pr)
|
self.xmpp.event("muc::%s::got_offline" % entry['room'], pr)
|
||||||
if got_online:
|
if got_online:
|
||||||
self.xmpp.event("muc::%s::got_online" % entry['room'], pr)
|
self.xmpp.event("muc::%s::got_online" % entry['room'], pr)
|
||||||
|
|
||||||
def handle_groupchat_message(self, msg):
|
def handle_groupchat_message(self, msg):
|
||||||
""" Handle a message event in a muc.
|
""" Handle a message event in a muc.
|
||||||
"""
|
"""
|
||||||
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 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]
|
||||||
if entry is not None and entry['jid'].full == jid:
|
if entry is not None and entry['jid'].full == jid:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getNick(self, room, jid):
|
def getNick(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]
|
||||||
@ -176,12 +180,12 @@ class xep_0045(base.base_plugin):
|
|||||||
if xform is None: return False
|
if xform is None: return False
|
||||||
form = self.xmpp.plugin['old_0004'].buildForm(xform)
|
form = self.xmpp.plugin['old_0004'].buildForm(xform)
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def configureRoom(self, room, form=None, ifrom=None):
|
def configureRoom(self, room, form=None, ifrom=None):
|
||||||
if form is None:
|
if form is None:
|
||||||
form = self.getRoomForm(room, ifrom=ifrom)
|
form = self.getRoomForm(room, ifrom=ifrom)
|
||||||
#form = self.xmpp.plugin['old_0004'].makeForm(ftype='submit')
|
#form = self.xmpp.plugin['old_0004'].makeForm(ftype='submit')
|
||||||
#form.addField('FORM_TYPE', value='http://jabber.org/protocol/muc#roomconfig')
|
#form.addField('FORM_TYPE', value='http://jabber.org/protocol/muc#roomconfig')
|
||||||
iq = self.xmpp.makeIqSet()
|
iq = self.xmpp.makeIqSet()
|
||||||
iq['to'] = room
|
iq['to'] = room
|
||||||
if ifrom is not None:
|
if ifrom is not None:
|
||||||
@ -194,7 +198,7 @@ class xep_0045(base.base_plugin):
|
|||||||
if result['type'] == 'error':
|
if result['type'] == 'error':
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def joinMUC(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None):
|
def joinMUC(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None):
|
||||||
""" Join the specified room, requesting 'maxhistory' lines of history.
|
""" Join the specified room, requesting 'maxhistory' lines of history.
|
||||||
"""
|
"""
|
||||||
@ -220,7 +224,7 @@ class xep_0045(base.base_plugin):
|
|||||||
self.xmpp.send(stanza, expect)
|
self.xmpp.send(stanza, expect)
|
||||||
self.rooms[room] = {}
|
self.rooms[room] = {}
|
||||||
self.ourNicks[room] = nick
|
self.ourNicks[room] = nick
|
||||||
|
|
||||||
def destroy(self, room, reason='', altroom = '', ifrom=None):
|
def destroy(self, room, reason='', altroom = '', ifrom=None):
|
||||||
iq = self.xmpp.makeIqSet()
|
iq = self.xmpp.makeIqSet()
|
||||||
if ifrom is not None:
|
if ifrom is not None:
|
||||||
@ -246,9 +250,9 @@ class xep_0045(base.base_plugin):
|
|||||||
raise TypeError
|
raise TypeError
|
||||||
query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
|
query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
|
||||||
if nick is not None:
|
if nick is not None:
|
||||||
item = ET.Element('item', {'affiliation':affiliation, 'nick':nick})
|
item = ET.Element('item', {'affiliation':affiliation, 'nick':nick})
|
||||||
else:
|
else:
|
||||||
item = ET.Element('item', {'affiliation':affiliation, 'jid':jid})
|
item = ET.Element('item', {'affiliation':affiliation, 'jid':jid})
|
||||||
query.append(item)
|
query.append(item)
|
||||||
iq = self.xmpp.makeIqSet(query)
|
iq = self.xmpp.makeIqSet(query)
|
||||||
iq['to'] = room
|
iq['to'] = room
|
||||||
@ -256,7 +260,7 @@ class xep_0045(base.base_plugin):
|
|||||||
if result is False or result['type'] != 'result':
|
if result is False or result['type'] != 'result':
|
||||||
raise ValueError
|
raise ValueError
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def invite(self, room, jid, reason=''):
|
def invite(self, room, jid, reason=''):
|
||||||
""" Invite a jid to a room."""
|
""" Invite a jid to a room."""
|
||||||
msg = self.xmpp.makeMessage(room)
|
msg = self.xmpp.makeMessage(room)
|
||||||
@ -279,7 +283,7 @@ class xep_0045(base.base_plugin):
|
|||||||
else:
|
else:
|
||||||
self.xmpp.sendPresence(pshow='unavailable', pto="%s/%s" % (room, nick))
|
self.xmpp.sendPresence(pshow='unavailable', pto="%s/%s" % (room, nick))
|
||||||
del self.rooms[room]
|
del self.rooms[room]
|
||||||
|
|
||||||
def getRoomConfig(self, room):
|
def getRoomConfig(self, room):
|
||||||
iq = self.xmpp.makeIqGet('http://jabber.org/protocol/muc#owner')
|
iq = self.xmpp.makeIqGet('http://jabber.org/protocol/muc#owner')
|
||||||
iq['to'] = room
|
iq['to'] = room
|
||||||
@ -291,14 +295,14 @@ class xep_0045(base.base_plugin):
|
|||||||
if form is None:
|
if form is None:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
return self.xmpp.plugin['xep_0004'].buildForm(form)
|
return self.xmpp.plugin['xep_0004'].buildForm(form)
|
||||||
|
|
||||||
def cancelConfig(self, room):
|
def cancelConfig(self, room):
|
||||||
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
||||||
x = ET.Element('{jabber:x:data}x', type='cancel')
|
x = ET.Element('{jabber:x:data}x', type='cancel')
|
||||||
query.append(x)
|
query.append(x)
|
||||||
iq = self.xmpp.makeIqSet(query)
|
iq = self.xmpp.makeIqSet(query)
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def setRoomConfig(self, room, config):
|
def setRoomConfig(self, room, config):
|
||||||
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
|
||||||
x = config.getXML('submit')
|
x = config.getXML('submit')
|
||||||
@ -307,15 +311,15 @@ class xep_0045(base.base_plugin):
|
|||||||
iq['to'] = room
|
iq['to'] = room
|
||||||
iq['from'] = self.xmpp.jid
|
iq['from'] = self.xmpp.jid
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def getJoinedRooms(self):
|
def getJoinedRooms(self):
|
||||||
return self.rooms.keys()
|
return self.rooms.keys()
|
||||||
|
|
||||||
def getOurJidInRoom(self, roomJid):
|
def getOurJidInRoom(self, roomJid):
|
||||||
""" Return the jid we're using in a room.
|
""" Return the jid we're using in a room.
|
||||||
"""
|
"""
|
||||||
return "%s/%s" % (roomJid, self.ourNicks[roomJid])
|
return "%s/%s" % (roomJid, self.ourNicks[roomJid])
|
||||||
|
|
||||||
def getJidProperty(self, room, nick, jidProperty):
|
def getJidProperty(self, room, nick, jidProperty):
|
||||||
""" Get the property of a nick in a room, such as its 'jid' or 'affiliation'
|
""" Get the property of a nick in a room, such as its 'jid' or 'affiliation'
|
||||||
If not found, return None.
|
If not found, return None.
|
||||||
@ -324,7 +328,7 @@ class xep_0045(base.base_plugin):
|
|||||||
return self.rooms[room][nick][jidProperty]
|
return self.rooms[room][nick][jidProperty]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getRoster(self, room):
|
def getRoster(self, room):
|
||||||
""" Get the list of nicks in a room.
|
""" Get the list of nicks in a room.
|
||||||
"""
|
"""
|
||||||
|
@ -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
|
||||||
@ -14,7 +18,7 @@ class xep_0060(base.base_plugin):
|
|||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.xep = '0060'
|
self.xep = '0060'
|
||||||
self.description = 'Publish-Subscribe'
|
self.description = 'Publish-Subscribe'
|
||||||
|
|
||||||
def create_node(self, jid, node, config=None, collection=False, ntype=None):
|
def create_node(self, jid, node, config=None, collection=False, ntype=None):
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
||||||
create = ET.Element('create')
|
create = ET.Element('create')
|
||||||
@ -52,7 +56,7 @@ class xep_0060(base.base_plugin):
|
|||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is False or result is None or result['type'] == 'error': return False
|
if result is False or result is None or result['type'] == 'error': return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def subscribe(self, jid, node, bare=True, subscribee=None):
|
def subscribe(self, jid, node, bare=True, subscribee=None):
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
||||||
subscribe = ET.Element('subscribe')
|
subscribe = ET.Element('subscribe')
|
||||||
@ -72,7 +76,7 @@ class xep_0060(base.base_plugin):
|
|||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is False or result is None or result['type'] == 'error': return False
|
if result is False or result is None or result['type'] == 'error': return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unsubscribe(self, jid, node, bare=True, subscribee=None):
|
def unsubscribe(self, jid, node, bare=True, subscribee=None):
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
||||||
unsubscribe = ET.Element('unsubscribe')
|
unsubscribe = ET.Element('unsubscribe')
|
||||||
@ -92,7 +96,7 @@ class xep_0060(base.base_plugin):
|
|||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is False or result is None or result['type'] == 'error': return False
|
if result is False or result is None or result['type'] == 'error': return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getNodeConfig(self, jid, node=None): # if no node, then grab default
|
def getNodeConfig(self, jid, node=None): # if no node, then grab default
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
|
||||||
if node is not None:
|
if node is not None:
|
||||||
@ -110,17 +114,17 @@ 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)
|
||||||
|
|
||||||
def getNodeSubscriptions(self, jid, node):
|
def getNodeSubscriptions(self, jid, node):
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
|
||||||
subscriptions = ET.Element('subscriptions')
|
subscriptions = ET.Element('subscriptions')
|
||||||
@ -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')
|
||||||
@ -181,8 +185,8 @@ class xep_0060(base.base_plugin):
|
|||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def setNodeConfig(self, jid, node, config):
|
def setNodeConfig(self, jid, node, config):
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
|
||||||
configure = ET.Element('configure')
|
configure = ET.Element('configure')
|
||||||
@ -195,10 +199,10 @@ class xep_0060(base.base_plugin):
|
|||||||
iq.attrib['from'] = self.xmpp.fulljid
|
iq.attrib['from'] = self.xmpp.fulljid
|
||||||
id = iq['id']
|
id = iq['id']
|
||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is None or result['type'] == 'error':
|
if result is None or result['type'] == 'error':
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setItem(self, jid, node, items=[]):
|
def setItem(self, jid, node, items=[]):
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
||||||
publish = ET.Element('publish')
|
publish = ET.Element('publish')
|
||||||
@ -218,7 +222,7 @@ class xep_0060(base.base_plugin):
|
|||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is None or result is False or result['type'] == 'error': return False
|
if result is None or result is False or result['type'] == 'error': return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def addItem(self, jid, node, items=[]):
|
def addItem(self, jid, node, items=[]):
|
||||||
return self.setItem(jid, node, items)
|
return self.setItem(jid, node, items)
|
||||||
|
|
||||||
@ -237,7 +241,7 @@ class xep_0060(base.base_plugin):
|
|||||||
result = iq.send()
|
result = iq.send()
|
||||||
if result is None or result is False or result['type'] == 'error': return False
|
if result is None or result is False or result['type'] == 'error': return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getNodes(self, jid):
|
def getNodes(self, jid):
|
||||||
response = self.xmpp.plugin['xep_0030'].getItems(jid)
|
response = self.xmpp.plugin['xep_0030'].getItems(jid)
|
||||||
items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
|
items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
|
||||||
@ -246,7 +250,7 @@ class xep_0060(base.base_plugin):
|
|||||||
for item in items:
|
for item in items:
|
||||||
nodes[item.get('node')] = item.get('name')
|
nodes[item.get('node')] = item.get('name')
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def getItems(self, jid, node):
|
def getItems(self, jid, node):
|
||||||
response = self.xmpp.plugin['xep_0030'].getItems(jid, node)
|
response = self.xmpp.plugin['xep_0030'].getItems(jid, node)
|
||||||
items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
|
items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
|
||||||
@ -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
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
SleekXMPP: The Sleek XMPP Library
|
SleekXMPP: The Sleek XMPP Library
|
||||||
Copyright (C) 2010 Nathanael C. Fritz
|
Copyright (C) 2010 Nathanael C. Fritz
|
||||||
This file is part of SleekXMPP.
|
This file is part of SleekXMPP.
|
||||||
|
|
||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
@ -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
|
||||||
@ -23,14 +26,14 @@ class xep_0078(base.base_plugin):
|
|||||||
#disabling until I fix conflict with PLAIN
|
#disabling until I fix conflict with PLAIN
|
||||||
#self.xmpp.registerFeature("<auth xmlns='http://jabber.org/features/iq-auth'/>", self.auth)
|
#self.xmpp.registerFeature("<auth xmlns='http://jabber.org/features/iq-auth'/>", self.auth)
|
||||||
self.streamid = ''
|
self.streamid = ''
|
||||||
|
|
||||||
def check_stream(self, xml):
|
def check_stream(self, xml):
|
||||||
self.streamid = xml.attrib['id']
|
self.streamid = xml.attrib['id']
|
||||||
if xml.get('version', '0') != '1.0':
|
if xml.get('version', '0') != '1.0':
|
||||||
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,15 +14,18 @@ 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'
|
||||||
interface = set(('state',))
|
interface = set(('state',))
|
||||||
states = set(('active', 'composing', 'gone', 'inactive', 'paused'))
|
states = set(('active', 'composing', 'gone', 'inactive', 'paused'))
|
||||||
|
|
||||||
def active(self):
|
def active(self):
|
||||||
self.setState('active')
|
self.setState('active')
|
||||||
|
|
||||||
def composing(self):
|
def composing(self):
|
||||||
self.setState('composing')
|
self.setState('composing')
|
||||||
|
|
||||||
@ -67,11 +70,11 @@ class xep_0085(base.base_plugin):
|
|||||||
"""
|
"""
|
||||||
XEP-0085 Chat State Notifications
|
XEP-0085 Chat State Notifications
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def plugin_init(self):
|
def plugin_init(self):
|
||||||
self.xep = '0085'
|
self.xep = '0085'
|
||||||
self.description = 'Chat State Notifications'
|
self.description = 'Chat State Notifications'
|
||||||
|
|
||||||
handlers = [('Active Chat State', 'active'),
|
handlers = [('Active Chat State', 'active'),
|
||||||
('Composing Chat State', 'composing'),
|
('Composing Chat State', 'composing'),
|
||||||
('Gone Chat State', 'gone'),
|
('Gone Chat State', 'gone'),
|
||||||
@ -79,10 +82,10 @@ class xep_0085(base.base_plugin):
|
|||||||
('Paused Chat State', 'paused')]
|
('Paused Chat State', 'paused')]
|
||||||
for handler in handlers:
|
for handler in handlers:
|
||||||
self.xmpp.registerHandler(
|
self.xmpp.registerHandler(
|
||||||
Callback(handler[0],
|
Callback(handler[0],
|
||||||
MatchXPath("{%s}message/{%s}%s" % (self.xmpp.default_ns,
|
MatchXPath("{%s}message/{%s}%s" % (self.xmpp.default_ns,
|
||||||
ChatState.namespace,
|
ChatState.namespace,
|
||||||
handler[1])),
|
handler[1])),
|
||||||
self._handleChatState))
|
self._handleChatState))
|
||||||
|
|
||||||
registerStanzaPlugin(Message, Active)
|
registerStanzaPlugin(Message, Active)
|
||||||
@ -90,12 +93,12 @@ class xep_0085(base.base_plugin):
|
|||||||
registerStanzaPlugin(Message, Gone)
|
registerStanzaPlugin(Message, Gone)
|
||||||
registerStanzaPlugin(Message, Inactive)
|
registerStanzaPlugin(Message, Inactive)
|
||||||
registerStanzaPlugin(Message, Paused)
|
registerStanzaPlugin(Message, Paused)
|
||||||
|
|
||||||
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://jabber.org/protocol/chatstates')
|
self.xmpp.plugin['xep_0030'].add_feature('http://jabber.org/protocol/chatstates')
|
||||||
|
|
||||||
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)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
SleekXMPP: The Sleek XMPP Library
|
SleekXMPP: The Sleek XMPP Library
|
||||||
Copyright (C) 2010 Nathanael C. Fritz
|
Copyright (C) 2010 Nathanael C. Fritz
|
||||||
This file is part of SleekXMPP.
|
This file is part of SleekXMPP.
|
||||||
|
|
||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
from xml.etree import cElementTree as ET
|
from xml.etree import cElementTree as ET
|
||||||
@ -10,6 +10,10 @@ 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"""
|
||||||
|
|
||||||
@ -20,19 +24,19 @@ class xep_0199(base.base_plugin):
|
|||||||
self.running = False
|
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('urn:xmpp:ping')
|
self.xmpp.plugin['xep_0030'].add_feature('urn:xmpp:ping')
|
||||||
|
|
||||||
def handler_pingserver(self, xml):
|
def handler_pingserver(self, xml):
|
||||||
if not self.running:
|
if not self.running:
|
||||||
time.sleep(self.config.get('frequency', 300))
|
time.sleep(self.config.get('frequency', 300))
|
||||||
while self.sendPing(self.xmpp.server, self.config.get('timeout', 30)) is not False:
|
while self.sendPing(self.xmpp.server, self.config.get('timeout', 30)) is not False:
|
||||||
time.sleep(self.config.get('frequency', 300))
|
time.sleep(self.config.get('frequency', 300))
|
||||||
logging.debug("Did not recieve ping back in time. Requesting Reconnect.")
|
log.debug("Did not recieve ping back in time. Requesting Reconnect.")
|
||||||
self.xmpp.disconnect(reconnect=True)
|
self.xmpp.disconnect(reconnect=True)
|
||||||
|
|
||||||
def handler_ping(self, xml):
|
def handler_ping(self, xml):
|
||||||
iq = self.xmpp.makeIqResult(xml.get('id', 'unknown'))
|
iq = self.xmpp.makeIqResult(xml.get('id', 'unknown'))
|
||||||
iq.attrib['to'] = xml.get('from', self.xmpp.boundjid.domain)
|
iq.attrib['to'] = xml.get('from', self.xmpp.boundjid.domain)
|
||||||
|
@ -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):
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
96
sleekxmpp/thirdparty/statemachine.py
vendored
96
sleekxmpp/thirdparty/statemachine.py
vendored
@ -21,7 +21,7 @@ class StateMachine(object):
|
|||||||
self.addStates(states)
|
self.addStates(states)
|
||||||
self.__default_state = self.__states[0]
|
self.__default_state = self.__states[0]
|
||||||
self.__current_state = self.__default_state
|
self.__current_state = self.__default_state
|
||||||
|
|
||||||
def addStates(self, states):
|
def addStates(self, states):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
@ -30,19 +30,19 @@ class StateMachine(object):
|
|||||||
raise IndexError("The state '%s' is already in the StateMachine." % state)
|
raise IndexError("The state '%s' is already in the StateMachine." % state)
|
||||||
self.__states.append(state)
|
self.__states.append(state)
|
||||||
finally: self.lock.release()
|
finally: self.lock.release()
|
||||||
|
|
||||||
|
|
||||||
def transition(self, from_state, to_state, wait=0.0, func=None, args=[], kwargs={}):
|
def transition(self, from_state, to_state, wait=0.0, func=None, args=[], kwargs={}):
|
||||||
'''
|
'''
|
||||||
Transition from the given `from_state` to the given `to_state`.
|
Transition from the given `from_state` to the given `to_state`.
|
||||||
This method will return `True` if the state machine is now in `to_state`. It
|
This method will return `True` if the state machine is now in `to_state`. It
|
||||||
will return `False` if a timeout occurred the transition did not occur.
|
will return `False` if a timeout occurred the transition did not occur.
|
||||||
If `wait` is 0 (the default,) this method returns immediately if the state machine
|
If `wait` is 0 (the default,) this method returns immediately if the state machine
|
||||||
is not in `from_state`.
|
is not in `from_state`.
|
||||||
|
|
||||||
If you want the thread to block and transition once the state machine to enters
|
If you want the thread to block and transition once the state machine to enters
|
||||||
`from_state`, set `wait` to a non-negative value. Note there is no 'block
|
`from_state`, set `wait` to a non-negative value. Note there is no 'block
|
||||||
indefinitely' flag since this leads to deadlock. If you want to wait indefinitely,
|
indefinitely' flag since this leads to deadlock. If you want to wait indefinitely,
|
||||||
choose a reasonable value for `wait` (e.g. 20 seconds) and do so in a while loop like so:
|
choose a reasonable value for `wait` (e.g. 20 seconds) and do so in a while loop like so:
|
||||||
|
|
||||||
::
|
::
|
||||||
@ -60,42 +60,42 @@ class StateMachine(object):
|
|||||||
True value or if an exception is thrown, the transition will not occur. Any thrown
|
True value or if an exception is thrown, the transition will not occur. Any thrown
|
||||||
exception is not caught by the state machine and is the caller's responsibility to handle.
|
exception is not caught by the state machine and is the caller's responsibility to handle.
|
||||||
If `func` completes normally, this method will return the value returned by `func.` If
|
If `func` completes normally, this method will return the value returned by `func.` If
|
||||||
values for `args` and `kwargs` are provided, they are expanded and passed like so:
|
values for `args` and `kwargs` are provided, they are expanded and passed like so:
|
||||||
`func( *args, **kwargs )`.
|
`func( *args, **kwargs )`.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
return self.transition_any((from_state,), to_state, wait=wait,
|
return self.transition_any((from_state,), to_state, wait=wait,
|
||||||
func=func, args=args, kwargs=kwargs)
|
func=func, args=args, kwargs=kwargs)
|
||||||
|
|
||||||
|
|
||||||
def transition_any(self, from_states, to_state, wait=0.0, func=None, args=[], kwargs={}):
|
def transition_any(self, from_states, to_state, wait=0.0, func=None, args=[], kwargs={}):
|
||||||
'''
|
'''
|
||||||
Transition from any of the given `from_states` to the given `to_state`.
|
Transition from any of the given `from_states` to the given `to_state`.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if not (isinstance(from_states,tuple) or isinstance(from_states,list)):
|
if not (isinstance(from_states,tuple) or isinstance(from_states,list)):
|
||||||
raise ValueError("from_states should be a list or tuple")
|
raise ValueError("from_states should be a list or tuple")
|
||||||
|
|
||||||
for state in from_states:
|
for state in from_states:
|
||||||
if not state in self.__states:
|
if not state in self.__states:
|
||||||
raise ValueError("StateMachine does not contain from_state %s." % state)
|
raise ValueError("StateMachine does not contain from_state %s." % state)
|
||||||
if not to_state in self.__states:
|
if not to_state in self.__states:
|
||||||
raise ValueError("StateMachine does not contain to_state %s." % to_state)
|
raise ValueError("StateMachine does not contain to_state %s." % to_state)
|
||||||
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
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:
|
||||||
# detect timeout:
|
# detect timeout:
|
||||||
remainder = start + wait - time.time()
|
remainder = start + wait - time.time()
|
||||||
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
|
||||||
|
|
||||||
@ -105,9 +105,9 @@ class StateMachine(object):
|
|||||||
# Note that func might throw an exception, but that's OK, it aborts the transition
|
# Note that func might throw an exception, but that's OK, it aborts the transition
|
||||||
return_val = func(*args,**kwargs) if func is not None else True
|
return_val = func(*args,**kwargs) if func is not None else True
|
||||||
|
|
||||||
# some 'false' value returned from func,
|
# some 'false' value returned from func,
|
||||||
# indicating that transition should not occur:
|
# indicating that transition should not occur:
|
||||||
if not return_val: return return_val
|
if not return_val: return return_val
|
||||||
|
|
||||||
log.debug(' ==== TRANSITION %s -> %s', self.__current_state, to_state)
|
log.debug(' ==== TRANSITION %s -> %s', self.__current_state, to_state)
|
||||||
self._set_state(to_state)
|
self._set_state(to_state)
|
||||||
@ -115,7 +115,7 @@ class StateMachine(object):
|
|||||||
else:
|
else:
|
||||||
log.error("StateMachine bug!! The lock should ensure this doesn't happen!")
|
log.error("StateMachine bug!! The lock should ensure this doesn't happen!")
|
||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
self.notifier.set() # notify any waiting threads that the state has changed.
|
self.notifier.set() # notify any waiting threads that the state has changed.
|
||||||
self.notifier.clear()
|
self.notifier.clear()
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
@ -125,13 +125,13 @@ class StateMachine(object):
|
|||||||
'''
|
'''
|
||||||
Use the state machine as a context manager. The transition occurs on /exit/ from
|
Use the state machine as a context manager. The transition occurs on /exit/ from
|
||||||
the `with` context, so long as no exception is thrown. For example:
|
the `with` context, so long as no exception is thrown. For example:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
with state_machine.transition_ctx('one','two', wait=5) as locked:
|
with state_machine.transition_ctx('one','two', wait=5) as locked:
|
||||||
if locked:
|
if locked:
|
||||||
# the state machine is currently locked in state 'one', and will
|
# the state machine is currently locked in state 'one', and will
|
||||||
# transition to 'two' when the 'with' statement ends, so long as
|
# transition to 'two' when the 'with' statement ends, so long as
|
||||||
# no exception is thrown.
|
# no exception is thrown.
|
||||||
print 'Currently locked in state one: %s' % state_machine['one']
|
print 'Currently locked in state one: %s' % state_machine['one']
|
||||||
|
|
||||||
@ -142,20 +142,20 @@ class StateMachine(object):
|
|||||||
print 'Since no exception was thrown, we are now in state "two": %s' % state_machine['two']
|
print 'Since no exception was thrown, we are now in state "two": %s' % state_machine['two']
|
||||||
|
|
||||||
|
|
||||||
The other main difference between this method and `transition()` is that the
|
The other main difference between this method and `transition()` is that the
|
||||||
state machine is locked for the duration of the `with` statement. Normally,
|
state machine is locked for the duration of the `with` statement. Normally,
|
||||||
after a `transition()` occurs, the state machine is immediately unlocked and
|
after a `transition()` occurs, the state machine is immediately unlocked and
|
||||||
available to another thread to call `transition()` again.
|
available to another thread to call `transition()` again.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if not from_state in self.__states:
|
if not from_state in self.__states:
|
||||||
raise ValueError("StateMachine does not contain from_state %s." % from_state)
|
raise ValueError("StateMachine does not contain from_state %s." % from_state)
|
||||||
if not to_state in self.__states:
|
if not to_state in self.__states:
|
||||||
raise ValueError("StateMachine does not contain to_state %s." % to_state)
|
raise ValueError("StateMachine does not contain to_state %s." % to_state)
|
||||||
|
|
||||||
return _StateCtx(self, from_state, to_state, wait)
|
return _StateCtx(self, from_state, to_state, wait)
|
||||||
|
|
||||||
|
|
||||||
def ensure(self, state, wait=0.0, block_on_transition=False):
|
def ensure(self, state, wait=0.0, block_on_transition=False):
|
||||||
'''
|
'''
|
||||||
Ensure the state machine is currently in `state`, or wait until it enters `state`.
|
Ensure the state machine is currently in `state`, or wait until it enters `state`.
|
||||||
@ -168,24 +168,24 @@ class StateMachine(object):
|
|||||||
Ensure we are currently in one of the given `states` or wait until
|
Ensure we are currently in one of the given `states` or wait until
|
||||||
we enter one of those states.
|
we enter one of those states.
|
||||||
|
|
||||||
Note that due to the nature of the function, you cannot guarantee that
|
Note that due to the nature of the function, you cannot guarantee that
|
||||||
the entirety of some operation completes while you remain in a given
|
the entirety of some operation completes while you remain in a given
|
||||||
state. That would require acquiring and holding a lock, which
|
state. That would require acquiring and holding a lock, which
|
||||||
would mean no other threads could do the same. (You'd essentially
|
would mean no other threads could do the same. (You'd essentially
|
||||||
be serializing all of the threads that are 'ensuring' their tasks
|
be serializing all of the threads that are 'ensuring' their tasks
|
||||||
occurred in some state.
|
occurred in some state.
|
||||||
'''
|
'''
|
||||||
if not (isinstance(states,tuple) or isinstance(states,list)):
|
if not (isinstance(states,tuple) or isinstance(states,list)):
|
||||||
raise ValueError('states arg should be a tuple or list')
|
raise ValueError('states arg should be a tuple or list')
|
||||||
|
|
||||||
for state in states:
|
for state in states:
|
||||||
if not state in self.__states:
|
if not state in self.__states:
|
||||||
raise ValueError("StateMachine does not contain state '%s'" % state)
|
raise ValueError("StateMachine does not contain state '%s'" % state)
|
||||||
|
|
||||||
# if we're in the middle of a transition, determine whether we should
|
# if we're in the middle of a transition, determine whether we should
|
||||||
# 'fall back' to the 'current' state, or wait for the new state, in order to
|
# 'fall back' to the 'current' state, or wait for the new state, in order to
|
||||||
# avoid an operation occurring in the wrong state.
|
# avoid an operation occurring in the wrong state.
|
||||||
# TODO another option would be an ensure_ctx that uses a semaphore to allow
|
# TODO another option would be an ensure_ctx that uses a semaphore to allow
|
||||||
# threads to indicate they want to remain in a particular state.
|
# threads to indicate they want to remain in a particular state.
|
||||||
|
|
||||||
# will return immediately if no transition is in process.
|
# will return immediately if no transition is in process.
|
||||||
@ -196,16 +196,16 @@ class StateMachine(object):
|
|||||||
else: self.notifier.wait()
|
else: self.notifier.wait()
|
||||||
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
while not self.__current_state in states:
|
while not self.__current_state in states:
|
||||||
# detect timeout:
|
# detect timeout:
|
||||||
remainder = start + wait - time.time()
|
remainder = start + wait - time.time()
|
||||||
if remainder > 0: self.notifier.wait(remainder)
|
if remainder > 0: self.notifier.wait(remainder)
|
||||||
else: return False
|
else: return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
# TODO need to lock before calling this?
|
# TODO need to lock before calling this?
|
||||||
self.transition(self.__current_state, self.__default_state)
|
self.transition(self.__current_state, self.__default_state)
|
||||||
|
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ class StateMachine(object):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(("StateMachine(", ','.join(self.__states), "): ", self.__current_state))
|
return "".join(("StateMachine(", ','.join(self.__states), "): ", self.__current_state))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class _StateCtx:
|
class _StateCtx:
|
||||||
|
|
||||||
@ -244,28 +244,28 @@ class _StateCtx:
|
|||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
start = time.time()
|
start = time.time()
|
||||||
while not self.state_machine[self.from_state] or not self.state_machine.lock.acquire(False):
|
while not self.state_machine[self.from_state] or not self.state_machine.lock.acquire(False):
|
||||||
# detect timeout:
|
# detect timeout:
|
||||||
remainder = start + self.wait - time.time()
|
remainder = start + self.wait - time.time()
|
||||||
if remainder > 0: self.state_machine.notifier.wait(remainder)
|
if remainder > 0: self.state_machine.notifier.wait(remainder)
|
||||||
else:
|
else:
|
||||||
log.debug('StateMachine timeout while waiting for state: %s', self.from_state)
|
log.debug('StateMachine timeout while waiting for state: %s', self.from_state)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self._locked = True # lock has been acquired at this point
|
self._locked = True # lock has been acquired at this point
|
||||||
self.state_machine.notifier.clear()
|
self.state_machine.notifier.clear()
|
||||||
log.debug('StateMachine entered context in state: %s',
|
log.debug('StateMachine entered context in state: %s',
|
||||||
self.state_machine.current_state())
|
self.state_machine.current_state())
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
if exc_val is not None:
|
if exc_val is not None:
|
||||||
log.exception("StateMachine exception in context, remaining in state: %s\n%s:%s",
|
log.exception("StateMachine exception in context, remaining in state: %s\n%s:%s",
|
||||||
self.state_machine.current_state(), exc_type.__name__, exc_val)
|
self.state_machine.current_state(), exc_type.__name__, exc_val)
|
||||||
|
|
||||||
if self._locked:
|
if self._locked:
|
||||||
if exc_val is None:
|
if exc_val is None:
|
||||||
log.debug(' ==== TRANSITION %s -> %s',
|
log.debug(' ==== TRANSITION %s -> %s',
|
||||||
self.state_machine.current_state(), self.to_state)
|
self.state_machine.current_state(), self.to_state)
|
||||||
self.state_machine._set_state(self.to_state)
|
self.state_machine._set_state(self.to_state)
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -168,13 +171,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
|
||||||
@ -206,7 +209,7 @@ class XMLStream(object):
|
|||||||
# Used in Windows
|
# Used in Windows
|
||||||
signal.signal(signal.SIGTERM, self._handle_kill)
|
signal.signal(signal.SIGTERM, self._handle_kill)
|
||||||
except:
|
except:
|
||||||
logging.debug("Can not set interrupt signal handlers. " + \
|
log.debug("Can not set interrupt signal handlers. " + \
|
||||||
"SleekXMPP is not running from a main thread.")
|
"SleekXMPP is not running from a main thread.")
|
||||||
|
|
||||||
def _handle_kill(self, signum, frame):
|
def _handle_kill(self, signum, frame):
|
||||||
@ -275,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
|
||||||
@ -285,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
|
||||||
@ -293,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
|
||||||
@ -338,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)
|
||||||
|
|
||||||
@ -378,8 +381,8 @@ 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")
|
||||||
logging.info("Using SSL version: %s" % str(self.ssl_version))
|
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=self.ssl_version,
|
ssl_version=self.ssl_version,
|
||||||
do_handshake_on_connect=False)
|
do_handshake_on_connect=False)
|
||||||
@ -393,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):
|
||||||
@ -547,7 +550,7 @@ 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, skipping the
|
direct -- Runs the event directly if True, skipping the
|
||||||
event queue. All event handlers will run in the
|
event queue. All event handlers will run in the
|
||||||
same thread.
|
same thread.
|
||||||
"""
|
"""
|
||||||
@ -557,7 +560,7 @@ class XMLStream(object):
|
|||||||
handler[0](copy.copy(data))
|
handler[0](copy.copy(data))
|
||||||
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(handler[0]))
|
log.exception(error_msg % str(handler[0]))
|
||||||
if hasattr(data, 'exception'):
|
if hasattr(data, 'exception'):
|
||||||
data.exception(e)
|
data.exception(e)
|
||||||
else:
|
else:
|
||||||
@ -622,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)
|
||||||
@ -679,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)
|
||||||
@ -717,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:
|
||||||
@ -756,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:
|
||||||
@ -770,7 +773,7 @@ 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):
|
def _build_stanza(self, xml, default_ns=None):
|
||||||
"""
|
"""
|
||||||
@ -781,7 +784,7 @@ class XMLStream(object):
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
xml -- The XML object to convert into a stanza object.
|
xml -- The XML object to convert into a stanza object.
|
||||||
default_ns -- Optional default namespace to use instead of the
|
default_ns -- Optional default namespace to use instead of the
|
||||||
stream's current default namespace.
|
stream's current default namespace.
|
||||||
"""
|
"""
|
||||||
if default_ns is None:
|
if default_ns is None:
|
||||||
@ -803,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.
|
||||||
@ -852,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)
|
||||||
|
|
||||||
@ -865,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:
|
||||||
@ -883,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:
|
||||||
@ -904,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:
|
||||||
@ -929,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:
|
||||||
|
Loading…
Reference in New Issue
Block a user