* started converstion to stanza objects
This commit is contained in:
		@@ -75,6 +75,7 @@ class ClientXMPP(basexmpp, XMLStream):
 | 
			
		||||
		#self.map_namespace('http://etherx.jabber.org/streams', 'stream')
 | 
			
		||||
		#self.map_namespace('jabber:client', '')
 | 
			
		||||
		self.features = []
 | 
			
		||||
		#TODO: Use stream state here
 | 
			
		||||
		self.authenticated = False
 | 
			
		||||
		self.sessionstarted = False
 | 
			
		||||
		self.registerHandler(Callback('Stream Features', MatchXPath('{http://etherx.jabber.org/streams}features'), self._handleStreamFeatures, thread=True))
 | 
			
		||||
@@ -88,14 +89,6 @@ class ClientXMPP(basexmpp, XMLStream):
 | 
			
		||||
		#self.registerStanzaExtension('PresenceStanza', PresenceStanzaType)
 | 
			
		||||
		#self.register_plugins()
 | 
			
		||||
	
 | 
			
		||||
	def importStanzas(self):
 | 
			
		||||
		pass
 | 
			
		||||
		return 
 | 
			
		||||
		for modname in stanza.__all__:
 | 
			
		||||
			__import__("%s.%s" % (globals()['stanza'].__name__, modname))
 | 
			
		||||
			for register in getattr(stanza, modname).stanzas:
 | 
			
		||||
				self.registerStanza(**register)
 | 
			
		||||
 | 
			
		||||
	def __getitem__(self, key):
 | 
			
		||||
		if key in self.plugin:
 | 
			
		||||
			return self.plugin[key]
 | 
			
		||||
@@ -109,7 +102,6 @@ class ClientXMPP(basexmpp, XMLStream):
 | 
			
		||||
	def connect(self, address=tuple()):
 | 
			
		||||
		"""Connect to the Jabber Server.  Attempts SRV lookup, and if it fails, uses
 | 
			
		||||
		the JID server."""
 | 
			
		||||
		self.importStanzas()
 | 
			
		||||
		if not address or len(address) < 2:
 | 
			
		||||
			if not self.srvsupport:
 | 
			
		||||
				logging.debug("Did not supply (address, port) to connect to and no SRV support is installed (http://www.dnspython.org).  Continuing to attempt connection, using server hostname from JID.")
 | 
			
		||||
@@ -163,26 +155,15 @@ class ClientXMPP(basexmpp, XMLStream):
 | 
			
		||||
 | 
			
		||||
	def updateRoster(self, jid, name=None, subscription=None, groups=[]):
 | 
			
		||||
		"""Add or change a roster item."""
 | 
			
		||||
		iq = self.makeIqSet()
 | 
			
		||||
		iq.attrib['from'] = self.fulljid
 | 
			
		||||
		query = self.makeQueryRoster(iq)
 | 
			
		||||
		item = ET.Element('item')
 | 
			
		||||
		item.attrib['jid'] = jid
 | 
			
		||||
		if name:
 | 
			
		||||
			item.attrib['name'] = name
 | 
			
		||||
		if subscription in ['to', 'from', 'both']:
 | 
			
		||||
			item.attrib['subscription'] = subscription
 | 
			
		||||
		else:
 | 
			
		||||
			item.attrib['subscription'] = 'none'
 | 
			
		||||
		for group in groups:
 | 
			
		||||
			groupxml = ET.Element('group')
 | 
			
		||||
			groupxml.text = group
 | 
			
		||||
			item.append.groupxml
 | 
			
		||||
		return self.send(iq, self.makeIq(self.getId()))
 | 
			
		||||
		iq = self.Iq().setValues({'type': 'set'})
 | 
			
		||||
		iq['roster'] = {jid: {'name': name, 'subscription': subscription, 'groups': groups}}
 | 
			
		||||
		#self.send(iq, self.Iq().setValues({'id': iq['id']}))
 | 
			
		||||
		r = iq.send()
 | 
			
		||||
		return r['type'] == 'result'
 | 
			
		||||
	
 | 
			
		||||
	def getRoster(self):
 | 
			
		||||
		"""Request the roster be sent."""
 | 
			
		||||
		self.send(self.makeIqGet('jabber:iq:roster'))
 | 
			
		||||
		self.Iq().setValues({'type': 'get'}).enable('roster').send()
 | 
			
		||||
	
 | 
			
		||||
	def _handleStreamFeatures(self, features):
 | 
			
		||||
		self.features = []
 | 
			
		||||
@@ -198,7 +179,7 @@ class ClientXMPP(basexmpp, XMLStream):
 | 
			
		||||
	def handler_starttls(self, xml):
 | 
			
		||||
		if not self.authenticated and self.ssl_support:
 | 
			
		||||
			self.add_handler("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls' />", self.handler_tls_start, instream=True)
 | 
			
		||||
			self.send(xml)
 | 
			
		||||
			self.sendXML(xml)
 | 
			
		||||
			return True
 | 
			
		||||
		else:
 | 
			
		||||
			logging.warning("The module tlslite is required in to some servers, and has not been found.")
 | 
			
		||||
@@ -240,14 +221,14 @@ class ClientXMPP(basexmpp, XMLStream):
 | 
			
		||||
	
 | 
			
		||||
	def handler_bind_resource(self, xml):
 | 
			
		||||
		logging.debug("Requesting resource: %s" % self.resource)
 | 
			
		||||
		out = self.makeIqSet()
 | 
			
		||||
		iq = self.Iq(stype='set')
 | 
			
		||||
		res = ET.Element('resource')
 | 
			
		||||
		res.text = self.resource
 | 
			
		||||
		xml.append(res)
 | 
			
		||||
		out.append(xml)
 | 
			
		||||
		id = out.get('id')
 | 
			
		||||
		response = self.send(out, self.makeIqResult(id))
 | 
			
		||||
		self.set_jid(response.find('{urn:ietf:params:xml:ns:xmpp-bind}bind/{urn:ietf:params:xml:ns:xmpp-bind}jid').text)
 | 
			
		||||
		iq.append(xml)
 | 
			
		||||
		response = iq.send()
 | 
			
		||||
		#response = self.send(iq, self.Iq(sid=iq['id']))
 | 
			
		||||
		self.set_jid(response.xml.find('{urn:ietf:params:xml:ns:xmpp-bind}bind/{urn:ietf:params:xml:ns:xmpp-bind}jid').text)
 | 
			
		||||
		logging.info("Node set to: %s" % self.fulljid)
 | 
			
		||||
		if "{urn:ietf:params:xml:ns:xmpp-session}session" not in self.features:
 | 
			
		||||
			logging.debug("Established Session")
 | 
			
		||||
@@ -261,21 +242,11 @@ class ClientXMPP(basexmpp, XMLStream):
 | 
			
		||||
			self.sessionstarted = True
 | 
			
		||||
			self.event("session_start")
 | 
			
		||||
	
 | 
			
		||||
	def _handleRoster(self, roster):
 | 
			
		||||
		xml = roster.xml
 | 
			
		||||
		xml = roster.xml
 | 
			
		||||
		roster_update = {}
 | 
			
		||||
		for item in xml.findall('{jabber:iq:roster}query/{jabber:iq:roster}item'):
 | 
			
		||||
			if not item.attrib['jid'] in self.roster:
 | 
			
		||||
				self.roster[item.attrib['jid']] = {'groups': [], 'name': '', 'subscription': 'none', 'presence': {}, 'in_roster': False}
 | 
			
		||||
			self.roster[item.attrib['jid']]['name'] = item.get('name', '')
 | 
			
		||||
			self.roster[item.attrib['jid']]['subscription'] = item.get('subscription', 'none')
 | 
			
		||||
			self.roster[item.attrib['jid']]['in_roster'] = 'True'
 | 
			
		||||
			for group in item.findall('{jabber:iq:roster}group'):
 | 
			
		||||
				self.roster[item.attrib['jid']]['groups'].append(group.text)
 | 
			
		||||
			if self.roster[item.attrib['jid']]['groups'] == []:
 | 
			
		||||
				self.roster[item.attrib['jid']]['groups'].append('Default')
 | 
			
		||||
			roster_update[item.attrib['jid']] = self.roster[item.attrib['jid']]
 | 
			
		||||
		if xml.get('type', 'result') == 'set':
 | 
			
		||||
			self.send(self.makeIqResult(xml.get('id', '0')))
 | 
			
		||||
		self.event("roster_update", roster_update)
 | 
			
		||||
	def _handleRoster(self, iq):
 | 
			
		||||
		for jid in iq['roster']['items']:
 | 
			
		||||
			if not jid.bare in self.roster:
 | 
			
		||||
				self.roster[jid.bare] = {'groups': [], 'name': '', 'subscription': 'none', 'presence': {}, 'in_roster': True}
 | 
			
		||||
			self.roster[jid.bare].update(iq['roster']['jid'])
 | 
			
		||||
		if iq['type'] == 'set':
 | 
			
		||||
			self.send(self.Iq().setValues({'type': 'result', 'id': iq['id']}).enable('roster'))
 | 
			
		||||
		self.event("roster_update", iq)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,61 +28,22 @@ from . xmlstream.handler.callback import Callback
 | 
			
		||||
from . import plugins
 | 
			
		||||
from . stanza.message import Message
 | 
			
		||||
from . stanza.iq import Iq
 | 
			
		||||
from . stanza.presence import Presence
 | 
			
		||||
from . stanza.roster import Roster
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
import threading
 | 
			
		||||
 | 
			
		||||
def stanzaPlugin(stanza, plugin):
 | 
			
		||||
	stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin
 | 
			
		||||
	stanza.plugin_tag_map["{%s}%s" % (plugin.namespace, plugin.name)] = plugin
 | 
			
		||||
 | 
			
		||||
stanzaPlugin(Iq, Roster)
 | 
			
		||||
 | 
			
		||||
class basexmpp(object):
 | 
			
		||||
	def __init__(self):
 | 
			
		||||
		self.id = 0
 | 
			
		||||
		self.id_lock = threading.Lock()
 | 
			
		||||
		self.stanza_errors = {
 | 
			
		||||
			'bad-request':False,
 | 
			
		||||
			'conflict':False,
 | 
			
		||||
			'feature-not-implemented':False,
 | 
			
		||||
			'forbidden':False,
 | 
			
		||||
			'gone':True,
 | 
			
		||||
			'internal-server-error':False,
 | 
			
		||||
			'item-not-found':False,
 | 
			
		||||
			'jid-malformed':False,
 | 
			
		||||
			'not-acceptable':False,
 | 
			
		||||
			'not-allowed':False,
 | 
			
		||||
			'payment-required':False,
 | 
			
		||||
			'recipient-unavailable':False,
 | 
			
		||||
			'redirect':True,
 | 
			
		||||
			'registration-required':False,
 | 
			
		||||
			'remote-server-not-found':False,
 | 
			
		||||
			'remote-server-timeout':False,
 | 
			
		||||
			'resource-constraint':False,
 | 
			
		||||
			'service-unavailable':False,
 | 
			
		||||
			'subscription-required':False,
 | 
			
		||||
			'undefined-condition':False,
 | 
			
		||||
			'unexpected-request':False}
 | 
			
		||||
		self.stream_errors = {
 | 
			
		||||
			'bad-format':False,
 | 
			
		||||
			'bad-namespace-prefix':False,
 | 
			
		||||
			'conflict':False,
 | 
			
		||||
			'connection-timeout':False,
 | 
			
		||||
			'host-gone':False,
 | 
			
		||||
			'host-unknown':False,
 | 
			
		||||
			'improper-addressing':False,
 | 
			
		||||
			'internal-server-error':False,
 | 
			
		||||
			'invalid-from':False,
 | 
			
		||||
			'invalid-id':False,
 | 
			
		||||
			'invalid-namespace':False,
 | 
			
		||||
			'invalid-xml':False,
 | 
			
		||||
			'not-authorized':False,
 | 
			
		||||
			'policy-violation':False,
 | 
			
		||||
			'remote-connection-failed':False,
 | 
			
		||||
			'resource-constraint':False,
 | 
			
		||||
			'restricted-xml':False,
 | 
			
		||||
			'see-other-host':True,
 | 
			
		||||
			'system-shutdown':False,
 | 
			
		||||
			'undefined-condition':False,
 | 
			
		||||
			'unsupported-encoding':False,
 | 
			
		||||
			'unsupported-stanza-type':False,
 | 
			
		||||
			'unsupported-version':False,
 | 
			
		||||
			'xml-not-well-formed':False}
 | 
			
		||||
		self.sentpresence = False
 | 
			
		||||
		self.fulljid = ''
 | 
			
		||||
		self.resource = ''
 | 
			
		||||
@@ -94,11 +55,21 @@ class basexmpp(object):
 | 
			
		||||
		self.auto_subscribe = True
 | 
			
		||||
		self.event_handlers = {}
 | 
			
		||||
		self.roster = {}
 | 
			
		||||
		self.registerHandler(Callback('IM', MatchMany((MatchXMLMask("<message xmlns='%s' type='chat'><body /></message>" % self.default_ns),MatchXMLMask("<message xmlns='%s' type='normal'><body /></message>" % self.default_ns),MatchXMLMask("<message xmlns='%s' type='__None__'><body /></message>" % self.default_ns))), self._handleMessage, thread=False))
 | 
			
		||||
		self.registerHandler(Callback('Presence', MatchMany((MatchXMLMask("<presence xmlns='%s' type='available'/>" % self.default_ns),MatchXMLMask("<presence xmlns='%s' type='__None__'/>" % self.default_ns),MatchXMLMask("<presence xmlns='%s' type='unavailable'/>" % self.default_ns))), self._handlePresence, thread=False))
 | 
			
		||||
		self.registerHandler(Callback('PresenceSubscribe', MatchMany((MatchXMLMask("<presence xmlns='%s' type='subscribe'/>" % self.default_ns),MatchXMLMask("<presence xmlns='%s' type='unsubscribed'/>" % self.default_ns))), self._handlePresenceSubscribe))
 | 
			
		||||
		self.registerHandler(Callback('IM', MatchXMLMask("<message xmlns='%s'><body /></message>" % self.default_ns), self._handleMessage))
 | 
			
		||||
		self.registerHandler(Callback('Presence', MatchXMLMask("<presence xmlns='%s' />" % self.default_ns), self._handlePresence))
 | 
			
		||||
		self.add_event_handler('presence_subscribe', self._handlePresenceSubscribe)
 | 
			
		||||
		self.registerStanza(Message)
 | 
			
		||||
		self.registerStanza(Iq)
 | 
			
		||||
		self.registerStanza(Presence)
 | 
			
		||||
	
 | 
			
		||||
	def Message(self, *args, **kwargs):
 | 
			
		||||
		return Presence(self, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
	def Iq(self, *args, **kwargs):
 | 
			
		||||
		return Iq(self, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
	def Presence(self, *args, **kwargs):
 | 
			
		||||
		return Presence(self, *args, **kwargs)
 | 
			
		||||
	
 | 
			
		||||
	def set_jid(self, jid):
 | 
			
		||||
		"""Rip a JID apart and claim it as our own."""
 | 
			
		||||
@@ -147,11 +118,17 @@ class basexmpp(object):
 | 
			
		||||
	
 | 
			
		||||
	def getId(self):
 | 
			
		||||
		return "%x".upper() % self.id
 | 
			
		||||
 | 
			
		||||
	def sendXML(self, data, mask=None, timeout=10):
 | 
			
		||||
		return self.send(self.tostring(data), mask, timeout)
 | 
			
		||||
	
 | 
			
		||||
	def send(self, data, mask=None, timeout=60):
 | 
			
		||||
	def send(self, data, mask=None, timeout=10):
 | 
			
		||||
		#logging.warning("Deprecated send used for \"%s\"" % (data,))
 | 
			
		||||
		if not type(data) == type(''):
 | 
			
		||||
			data = self.tostring(data)
 | 
			
		||||
		#if not type(data) == type(''):
 | 
			
		||||
		#	data = self.tostring(data)
 | 
			
		||||
		if hasattr(mask, 'xml'):
 | 
			
		||||
			mask = mask.xml
 | 
			
		||||
		data = str(data)
 | 
			
		||||
		if mask is not None:
 | 
			
		||||
			waitfor = XMLWaiter('SendWait_%s' % self.getNewId(), MatchXMLMask(mask))
 | 
			
		||||
			self.registerHandler(waitfor)
 | 
			
		||||
@@ -160,86 +137,28 @@ class basexmpp(object):
 | 
			
		||||
			return waitfor.wait(timeout)
 | 
			
		||||
	
 | 
			
		||||
	def makeIq(self, id=0, ifrom=None):
 | 
			
		||||
		iq = ET.Element('{%s}iq' % self.default_ns)
 | 
			
		||||
		if id == 0:
 | 
			
		||||
			id = self.getNewId()
 | 
			
		||||
		iq.set('id', str(id))
 | 
			
		||||
		if ifrom is not None:
 | 
			
		||||
			iq.attrib['from'] = ifrom
 | 
			
		||||
		return iq
 | 
			
		||||
		return self.Iq().setValues({'id': id, 'from': ifrom})
 | 
			
		||||
	
 | 
			
		||||
	def makeIqGet(self, queryxmlns = None):
 | 
			
		||||
		iq = self.makeIq()
 | 
			
		||||
		iq.set('type', 'get')
 | 
			
		||||
		iq = self.Iq().setValues({'type': 'get'})
 | 
			
		||||
		if queryxmlns:
 | 
			
		||||
			query = ET.Element("{%s}query" % queryxmlns)
 | 
			
		||||
			iq.append(query)
 | 
			
		||||
			iq.append(ET.Element("{%s}query" % queryxmlns))
 | 
			
		||||
		return iq
 | 
			
		||||
	
 | 
			
		||||
	def makeIqResult(self, id):
 | 
			
		||||
		iq = self.makeIq(id)
 | 
			
		||||
		iq.set('type', 'result')
 | 
			
		||||
		return iq
 | 
			
		||||
		return self.Iq().setValues({'id': id, 'type': 'result'})
 | 
			
		||||
	
 | 
			
		||||
	def makeIqSet(self, sub=None):
 | 
			
		||||
		iq = self.makeIq()
 | 
			
		||||
		iq.set('type', 'set')
 | 
			
		||||
		iq = self.Iq().setValues({'type': 'set'})
 | 
			
		||||
		if sub != None:
 | 
			
		||||
			iq.append(sub)
 | 
			
		||||
		return iq
 | 
			
		||||
 | 
			
		||||
	def makeIqError(self, id):
 | 
			
		||||
		iq = self.makeIq(id)
 | 
			
		||||
		iq.set('type', 'error')
 | 
			
		||||
	def makeIqError(self, id, type='cancel', condition='feature-not-implemented', text=None):
 | 
			
		||||
		iq = self.Iq().setValues({'id': id})
 | 
			
		||||
		iq['error'].setValues({'type': type, 'condition': condition, 'text': text})
 | 
			
		||||
		return iq
 | 
			
		||||
 | 
			
		||||
	def makeStanzaErrorCondition(self, condition, cdata=None):
 | 
			
		||||
		if condition not in self.stanza_errors:
 | 
			
		||||
			raise ValueError()
 | 
			
		||||
		stanzaError = ET.Element('{urn:ietf:params:xml:ns:xmpp-stanzas}'+condition)
 | 
			
		||||
		if cdata is not None:
 | 
			
		||||
			if not self.stanza_errors[condition]:
 | 
			
		||||
				raise ValueError()
 | 
			
		||||
			stanzaError.text = cdata
 | 
			
		||||
		return stanzaError
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	def makeStanzaError(self, condition, errorType, code=None, text=None, customElem=None):
 | 
			
		||||
		if errorType not in ['auth', 'cancel', 'continue', 'modify', 'wait']:
 | 
			
		||||
			raise ValueError()
 | 
			
		||||
		error = ET.Element('error')
 | 
			
		||||
		error.append(self.makeStanzaErrorCondition(condition))
 | 
			
		||||
		error.set('type',errorType)
 | 
			
		||||
		if code is not None:
 | 
			
		||||
			error.set('code', code)
 | 
			
		||||
		if text is not None:
 | 
			
		||||
			textElem = ET.Element('text')
 | 
			
		||||
			textElem.text = text
 | 
			
		||||
			error.append(textElem)
 | 
			
		||||
		if customElem is not None:
 | 
			
		||||
			error.append(customElem)
 | 
			
		||||
		return error
 | 
			
		||||
 | 
			
		||||
	def makeStreamErrorCondition(self, condition, cdata=None):
 | 
			
		||||
		if condition not in self.stream_errors:
 | 
			
		||||
			raise ValueError()
 | 
			
		||||
		streamError = ET.Element('{urn:ietf:params:xml:ns:xmpp-streams}'+condition)
 | 
			
		||||
		if cdata is not None:
 | 
			
		||||
			if not self.stream_errors[condition]:
 | 
			
		||||
				raise ValueError()
 | 
			
		||||
			textElem = ET.Element('text')
 | 
			
		||||
			textElem.text = text
 | 
			
		||||
			streamError.append(textElem)
 | 
			
		||||
 | 
			
		||||
	def makeStreamError(self, errorElem, text=None):
 | 
			
		||||
		error = ET.Element('error')
 | 
			
		||||
		error.append(errorElem)
 | 
			
		||||
		if text is not None:
 | 
			
		||||
			textElem = ET.Element('text')
 | 
			
		||||
			textElem.text = text
 | 
			
		||||
			error.append(text)
 | 
			
		||||
		return error
 | 
			
		||||
 | 
			
		||||
	def makeIqQuery(self, iq, xmlns):
 | 
			
		||||
		query = ET.Element("{%s}query" % xmlns)
 | 
			
		||||
		iq.append(query)
 | 
			
		||||
@@ -355,61 +274,21 @@ class basexmpp(object):
 | 
			
		||||
 | 
			
		||||
	def _handleMessage(self, msg):
 | 
			
		||||
		self.event('message', msg)
 | 
			
		||||
		#xml = msg.xml
 | 
			
		||||
		#ns = xml.tag.split('}')[0]
 | 
			
		||||
		#if ns == 'message':
 | 
			
		||||
		#	ns = ''
 | 
			
		||||
		#else:
 | 
			
		||||
		#	ns = "%s}" % ns
 | 
			
		||||
		#mfrom = xml.attrib['from']
 | 
			
		||||
		#message = xml.find('%sbody' % ns).text
 | 
			
		||||
		#subject = xml.find('%ssubject' % ns)
 | 
			
		||||
		#if subject is not None:
 | 
			
		||||
		#	subject = subject.text
 | 
			
		||||
		#else:
 | 
			
		||||
		#	subject = ''
 | 
			
		||||
		#resource = self.getjidresource(mfrom)
 | 
			
		||||
		#mfrom = self.getjidbare(mfrom)
 | 
			
		||||
		#mtype = xml.attrib.get('type', 'normal')
 | 
			
		||||
		#name = self.roster.get('name', '')
 | 
			
		||||
		#self.event("message", {'jid': mfrom, 'resource': resource, 'name': name, 'type': mtype, 'subject': subject, 'message': message, 'to': xml.attrib.get('to', '')})
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	def _handlePresence(self, presence):
 | 
			
		||||
		xml = presence.xml
 | 
			
		||||
		ns = xml.tag.split('}')[0]
 | 
			
		||||
		if ns == 'presence':
 | 
			
		||||
			ns = ''
 | 
			
		||||
		else:
 | 
			
		||||
			ns = "%s}" % ns
 | 
			
		||||
		"""Update roster items based on presence"""
 | 
			
		||||
		show = xml.find('%sshow' % ns)
 | 
			
		||||
		status = xml.find('%sstatus' % ns)
 | 
			
		||||
		priority = xml.find('%spriority' % ns)
 | 
			
		||||
		fulljid = xml.attrib['from']
 | 
			
		||||
		to = xml.attrib['to']
 | 
			
		||||
		resource = self.getjidresource(fulljid)
 | 
			
		||||
		if not resource:
 | 
			
		||||
			resouce = None
 | 
			
		||||
		jid = self.getjidbare(fulljid)
 | 
			
		||||
		if type(status) == type(None) or status.text is None:
 | 
			
		||||
			status = ''
 | 
			
		||||
		else:
 | 
			
		||||
			status = status.text
 | 
			
		||||
		if type(show) == type(None): 
 | 
			
		||||
			show = 'available'
 | 
			
		||||
		else:
 | 
			
		||||
			show = show.text
 | 
			
		||||
		if xml.get('type', None) == 'unavailable':
 | 
			
		||||
			show = 'unavailable'
 | 
			
		||||
		if type(priority) == type(None):
 | 
			
		||||
			priority = 0
 | 
			
		||||
		else:
 | 
			
		||||
			priority = int(priority.text)
 | 
			
		||||
		self.event("presence_%s" % presence['type'], presence)
 | 
			
		||||
		if not presence['type'] in ('available', 'unavailable'):
 | 
			
		||||
			return
 | 
			
		||||
		jid = presence['from'].bare
 | 
			
		||||
		resource = presence['from'].resource
 | 
			
		||||
		show = presence['type']
 | 
			
		||||
		status = presence['status']
 | 
			
		||||
		priority = presence['priority']
 | 
			
		||||
		wasoffline = False
 | 
			
		||||
		oldroster = self.roster.get(jid, {}).get(resource, {})
 | 
			
		||||
		if not jid in self.roster:
 | 
			
		||||
				self.roster[jid] = {'groups': [], 'name': '', 'subscription': 'none', 'presence': {}, 'in_roster': False}
 | 
			
		||||
		if not presence['from'].bare in self.roster:
 | 
			
		||||
			self.roster[jid] = {'groups': [], 'name': '', 'subscription': 'none', 'presence': {}, 'in_roster': False}
 | 
			
		||||
		if not resource in self.roster[jid]['presence']:
 | 
			
		||||
			wasoffline = True
 | 
			
		||||
			self.roster[jid]['presence'][resource] = {'show': show, 'status': status, 'priority': priority}
 | 
			
		||||
@@ -417,12 +296,10 @@ class basexmpp(object):
 | 
			
		||||
			if self.roster[jid]['presence'][resource].get('show', None) == 'unavailable':
 | 
			
		||||
				wasoffline = True
 | 
			
		||||
			self.roster[jid]['presence'][resource] = {'show': show, 'status': status}
 | 
			
		||||
			if priority:
 | 
			
		||||
				self.roster[jid]['presence'][resource]['priority'] = priority
 | 
			
		||||
			self.roster[jid]['presence'][resource]['priority'] = priority
 | 
			
		||||
		name = self.roster[jid].get('name', '')
 | 
			
		||||
		eventdata = {'jid': jid, 'to': to, 'resource': resource, 'name': name, 'type': show, 'priority': priority, 'message': status}
 | 
			
		||||
		if wasoffline and show in ('available', 'away', 'xa', 'na'):
 | 
			
		||||
			self.event("got_online", eventdata)
 | 
			
		||||
		if wasoffline and show in ('available', 'away', 'xa', 'na', 'ffc'):
 | 
			
		||||
			self.event("got_online", presence)
 | 
			
		||||
		elif not wasoffline and show == 'unavailable':
 | 
			
		||||
			self.event("got_offline", eventdata)
 | 
			
		||||
			if len(self.roster[jid]['presence']) > 1:
 | 
			
		||||
@@ -430,7 +307,7 @@ class basexmpp(object):
 | 
			
		||||
			else:
 | 
			
		||||
				del self.roster[jid]
 | 
			
		||||
		elif oldroster != self.roster.get(jid, {'presence': {}})['presence'].get(resource, {}) and show != 'unavailable':
 | 
			
		||||
			self.event("changed_status", eventdata)
 | 
			
		||||
			self.event("changed_status", presence)
 | 
			
		||||
		name = ''
 | 
			
		||||
		if name:
 | 
			
		||||
			name = "(%s) " % name
 | 
			
		||||
@@ -438,13 +315,9 @@ class basexmpp(object):
 | 
			
		||||
	
 | 
			
		||||
	def _handlePresenceSubscribe(self, presence):
 | 
			
		||||
		"""Handling subscriptions automatically."""
 | 
			
		||||
		xml = presence.xml
 | 
			
		||||
		if self.auto_authorize == True:
 | 
			
		||||
			#self.updateRoster(self.getjidbare(xml.attrib['from']))
 | 
			
		||||
			self.send(self.makePresence(ptype='subscribed', pto=self.getjidbare(xml.attrib['from'])))
 | 
			
		||||
			self.send(self.makePresence(ptype='subscribed', pto=presence['from'].bare))
 | 
			
		||||
			if self.auto_subscribe:
 | 
			
		||||
				self.send(self.makePresence(ptype='subscribe', pto=self.getjidbare(xml.attrib['from'])))
 | 
			
		||||
				self.send(self.makePresence(ptype='subscribe', pto=presence['from'].bare))
 | 
			
		||||
		elif self.auto_authorize == False:
 | 
			
		||||
			self.send(self.makePresence(ptype='unsubscribed', pto=self.getjidbare(xml.attrib['from'])))
 | 
			
		||||
		elif self.auto_authorize == None:
 | 
			
		||||
			pass
 | 
			
		||||
			self.send(self.makePresence(ptype='unsubscribed', pto=presence['from'].bare))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
from .. xmlstream.stanzabase import StanzaBase
 | 
			
		||||
from xml.etree import cElementTree as ET
 | 
			
		||||
from . error import Error
 | 
			
		||||
from .. xmlstream.handler.waiter import Waiter
 | 
			
		||||
from .. xmlstream.matcher.id import MatcherId
 | 
			
		||||
 | 
			
		||||
class Iq(StanzaBase):
 | 
			
		||||
	interfaces = set(('type', 'to', 'from', 'id', 'body', 'subject'))
 | 
			
		||||
@@ -11,7 +14,6 @@ class Iq(StanzaBase):
 | 
			
		||||
		StanzaBase.__init__(self, *args, **kwargs)
 | 
			
		||||
		if self['id'] == '':
 | 
			
		||||
			self['id'] = self.stream.getId()
 | 
			
		||||
		print("________LOADED IQ CLASS")
 | 
			
		||||
	
 | 
			
		||||
	def result(self):
 | 
			
		||||
		self['type'] = 'result'
 | 
			
		||||
@@ -37,3 +39,19 @@ class Iq(StanzaBase):
 | 
			
		||||
	def unhandled(self):
 | 
			
		||||
		pass
 | 
			
		||||
		# returned unhandled error
 | 
			
		||||
	
 | 
			
		||||
	def exception(self, traceback=None):
 | 
			
		||||
		pass
 | 
			
		||||
	
 | 
			
		||||
	def send(self, block=True, timeout=10):
 | 
			
		||||
		if block:
 | 
			
		||||
			waitfor = Waiter('IqWait_%s' % self['id'], MatcherId(self['id']))
 | 
			
		||||
			self.stream.registerHandler(waitfor)
 | 
			
		||||
			StanzaBase.send(self)
 | 
			
		||||
			return waitfor.wait(timeout)
 | 
			
		||||
		else:
 | 
			
		||||
			return StanzaBase.send(self)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
Iq.plugin_attrib_map['error'] = Error
 | 
			
		||||
Iq.plugin_tag_map["{%s}%s" % (Error.namespace, Error.name)] = Error
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
from .. xmlstream.stanzabase import StanzaBase
 | 
			
		||||
from xml.etree import cElementTree as ET
 | 
			
		||||
from . error import Error
 | 
			
		||||
 | 
			
		||||
class Message(StanzaBase):
 | 
			
		||||
	interfaces = set(('type', 'to', 'from', 'id', 'body', 'subject'))
 | 
			
		||||
@@ -25,21 +26,5 @@ class Message(StanzaBase):
 | 
			
		||||
			self['body'] = body
 | 
			
		||||
		return self
 | 
			
		||||
	
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
	m = Message()
 | 
			
		||||
	m['to'] = 'me'
 | 
			
		||||
	m['from'] = 'you'
 | 
			
		||||
	m['type'] = 'chat'
 | 
			
		||||
	m.reply()
 | 
			
		||||
	m['body'] = 'Hello there!'
 | 
			
		||||
	m['subject'] = 'whatever'
 | 
			
		||||
	m['id'] = 'abc'
 | 
			
		||||
	print(str(m))
 | 
			
		||||
	print(m['body'])
 | 
			
		||||
	print(m['subject'])
 | 
			
		||||
	print(m['id'])
 | 
			
		||||
	m['type'] = None
 | 
			
		||||
	m['body'] = None
 | 
			
		||||
	m['id'] = None
 | 
			
		||||
	print(str(m))
 | 
			
		||||
	print(m['type'])
 | 
			
		||||
Message.plugin_attrib_map['error'] = Error
 | 
			
		||||
Message.plugin_tag_map["{%s}%s" % (Error.namespace, Error.name)] = Error
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,51 @@
 | 
			
		||||
from .. xmlstream.stanzabase import StanzaBase
 | 
			
		||||
from .. xmlstream import xmlstream as xmlstreammod
 | 
			
		||||
from .. xmlstream.matcher.xpath import MatchXPath
 | 
			
		||||
from xml.etree import cElementTree as ET
 | 
			
		||||
from . error import Error
 | 
			
		||||
 | 
			
		||||
#_bases = [StanzaBase] + xmlstreammod.stanza_extensions.get('PresenceStanza', [])
 | 
			
		||||
class Presence(StanzaBase):
 | 
			
		||||
	interfaces = set(('type', 'to', 'from', 'id', 'status', 'priority'))
 | 
			
		||||
	types = set(('available', 'unavailable', 'error', 'probe', 'subscribe', 'subscribed', 'unsubscribe', 'unsubscribed'))
 | 
			
		||||
	showtypes = set(('dnd', 'ffc', 'xa', 'away'))
 | 
			
		||||
	sub_interfaces = set(('status', 'priority'))
 | 
			
		||||
	name = 'presence'
 | 
			
		||||
	namespace = 'jabber:client'
 | 
			
		||||
 | 
			
		||||
#class PresenceStanza(*_bases):
 | 
			
		||||
class PresenceStanza(StanzaBase):
 | 
			
		||||
	def getShowElement(self):
 | 
			
		||||
		return self.xml.find("{%s}show" % self.namespace)
 | 
			
		||||
 | 
			
		||||
	def setType(self, value):
 | 
			
		||||
		if value in self.types:
 | 
			
		||||
			show = self.getShowElement()
 | 
			
		||||
			if value in self.types:
 | 
			
		||||
				if show is not None:
 | 
			
		||||
					self.xml.remove(show)
 | 
			
		||||
				self._setAttr('type', value)
 | 
			
		||||
			elif value in self.showtypes:
 | 
			
		||||
				if show is None:
 | 
			
		||||
					show = ET.Element("{%s}show" % self.namespace)
 | 
			
		||||
				show.text = value
 | 
			
		||||
		return self
 | 
			
		||||
 | 
			
		||||
	def setPriority(self, value):
 | 
			
		||||
		self._setSubText('priority', str(value))
 | 
			
		||||
	
 | 
			
		||||
	def __init__(self, stream, xml=None):
 | 
			
		||||
		self.pfrom = ''
 | 
			
		||||
		self.pto = ''
 | 
			
		||||
		StanzaBase.__init__(self, stream, xml, xmlstreammod.stanza_extensions.get('PresenceStanza', []))
 | 
			
		||||
	def getPriority(self):
 | 
			
		||||
		p = self._getSubText('priority')
 | 
			
		||||
		if not p: p = 0
 | 
			
		||||
		return int(p)
 | 
			
		||||
	
 | 
			
		||||
	def getType(self):
 | 
			
		||||
		out = self._getAttr('type')
 | 
			
		||||
		if not out:
 | 
			
		||||
			show = self.getShowElement()
 | 
			
		||||
			if show is not None:
 | 
			
		||||
				out = show.text
 | 
			
		||||
		if not out or out is None:
 | 
			
		||||
			out = 'available'
 | 
			
		||||
		return out
 | 
			
		||||
	
 | 
			
		||||
	def delType(self):
 | 
			
		||||
		self.setType('available')
 | 
			
		||||
 | 
			
		||||
	def fromXML(self, xml):
 | 
			
		||||
		StanzaBase.fromXML(self, xml)
 | 
			
		||||
		self.pfrom = xml.get('from')
 | 
			
		||||
		self.pto = xml.get('to')
 | 
			
		||||
		self.ptype = xml.get('type')
 | 
			
		||||
 | 
			
		||||
stanzas = ({'stanza_class': PresenceStanza, 'matcher': MatchXPath('{jabber:client}presence'), 'root': True},)
 | 
			
		||||
Presence.plugin_attrib_map['error'] = Error
 | 
			
		||||
Presence.plugin_tag_map["{%s}%s" % (Error.namespace, Error.name)] = Error
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
from . import base
 | 
			
		||||
import queue
 | 
			
		||||
import logging
 | 
			
		||||
from .. stanzabase import StanzaBase
 | 
			
		||||
 | 
			
		||||
class Waiter(base.BaseHandler):
 | 
			
		||||
	
 | 
			
		||||
@@ -19,7 +20,7 @@ class Waiter(base.BaseHandler):
 | 
			
		||||
			return self._payload.get(True, timeout)
 | 
			
		||||
		except queue.Empty:
 | 
			
		||||
			logging.warning("Timed out waiting for %s" % self.name)
 | 
			
		||||
			return False
 | 
			
		||||
			return StanzaBase(stype='error')
 | 
			
		||||
	
 | 
			
		||||
	def checkDelete(self):
 | 
			
		||||
		return True
 | 
			
		||||
 
 | 
			
		||||
@@ -13,33 +13,53 @@ class JID(object):
 | 
			
		||||
			return self.jid.split('@', 1)[-1].split('/', 1)[0]
 | 
			
		||||
		elif name == 'full':
 | 
			
		||||
			return self.jid
 | 
			
		||||
		elif name == 'bare':
 | 
			
		||||
			return self.jid.split('/', 1)[0]
 | 
			
		||||
	
 | 
			
		||||
	def __str__(self):
 | 
			
		||||
		return self.jid
 | 
			
		||||
 | 
			
		||||
class StanzaBase(object):
 | 
			
		||||
class ElementBase(object):
 | 
			
		||||
	name = 'stanza'
 | 
			
		||||
	plugin_attrib = 'plugin'
 | 
			
		||||
	namespace = 'jabber:client'
 | 
			
		||||
	interfaces = set(('type', 'to', 'from', 'id', 'payload'))
 | 
			
		||||
	types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat'))
 | 
			
		||||
	sub_interfaces = tuple()
 | 
			
		||||
	plugin_attrib_map = {}
 | 
			
		||||
	plugin_tag_map = {}
 | 
			
		||||
 | 
			
		||||
	def __init__(self, stream, xml=None, stype=None, sto=None, sfrom=None, sid=None):
 | 
			
		||||
		self.stream = stream
 | 
			
		||||
	def __init__(self, xml=None, parent=None):
 | 
			
		||||
		self.parent = parent
 | 
			
		||||
		self.xml = xml
 | 
			
		||||
		if xml is None:
 | 
			
		||||
			self.xml = ET.Element("{%(namespace)s}%(name)s" % {'name': self.name, 'namespace': self.namespace})
 | 
			
		||||
		if stype is not None:
 | 
			
		||||
			self['type'] = stype
 | 
			
		||||
		if sto is not None:
 | 
			
		||||
			self['to'] = sto
 | 
			
		||||
		if sfrom is not None:
 | 
			
		||||
			self['from'] = sfrom
 | 
			
		||||
		self.tag = "{%s}%s" % (self.stream.default_ns, self.name)
 | 
			
		||||
	
 | 
			
		||||
		self.plugins = {}
 | 
			
		||||
		if not self.setup(xml) and len(self.plugin_attrib_map):
 | 
			
		||||
			for child in self.xml.getchildren():
 | 
			
		||||
				if child.tag in self.plugin_tag_map:
 | 
			
		||||
					self.plugins[self.plugin_tag_map[child.tag].plugin_attrib] = self.plugin_tag_map[child.tag](xml=child, parent=self)
 | 
			
		||||
 | 
			
		||||
	def match(self, xml):
 | 
			
		||||
		return xml.tag == self.tag
 | 
			
		||||
	
 | 
			
		||||
	def setup(self, xml=None):
 | 
			
		||||
		if self.xml is None:
 | 
			
		||||
			self.xml = xml
 | 
			
		||||
		if self.xml is None:
 | 
			
		||||
			self.xml = ET.Element("{%(namespace)s}%(name)s" % {'name': self.name, 'namespace': self.namespace})
 | 
			
		||||
			if self.parent is not None:
 | 
			
		||||
				self.parent.xml.append(self.xml)
 | 
			
		||||
			return True #had to generate XML
 | 
			
		||||
		else:
 | 
			
		||||
			return False
 | 
			
		||||
 | 
			
		||||
	def enable(self, attrib):
 | 
			
		||||
		self.initPlugin(attrib)
 | 
			
		||||
		return self
 | 
			
		||||
	
 | 
			
		||||
	def initPlugin(self, attrib):
 | 
			
		||||
		if attrib not in self.plugins:
 | 
			
		||||
			self.plugins[attrib] = self.plugin_attrib_map[attrib](parent=self)
 | 
			
		||||
	
 | 
			
		||||
	def __getitem__(self, attrib):
 | 
			
		||||
		if attrib in self.interfaces:
 | 
			
		||||
			if hasattr(self, "get%s" % attrib.title()):
 | 
			
		||||
@@ -49,11 +69,14 @@ class StanzaBase(object):
 | 
			
		||||
					return self._getSubText(attrib)
 | 
			
		||||
				else:
 | 
			
		||||
					return self._getAttr(attrib)
 | 
			
		||||
		elif attrib in self.plugin_attrib_map:
 | 
			
		||||
			self.initPlugin(attrib)
 | 
			
		||||
			return self.plugins[attrib]
 | 
			
		||||
		else:
 | 
			
		||||
			return ''
 | 
			
		||||
	
 | 
			
		||||
	def __setitem__(self, attrib, value):
 | 
			
		||||
		if attrib.lower() in self.interfaces:
 | 
			
		||||
		if attrib in self.interfaces:
 | 
			
		||||
			if value is not None:
 | 
			
		||||
				if hasattr(self, "set%s" % attrib.title()):
 | 
			
		||||
					getattr(self, "set%s" % attrib.title())(value,)
 | 
			
		||||
@@ -64,6 +87,9 @@ class StanzaBase(object):
 | 
			
		||||
						self._setAttr(attrib, value)
 | 
			
		||||
			else:
 | 
			
		||||
				self.__delitem__(attrib)
 | 
			
		||||
		elif attrib in self.plugin_map:
 | 
			
		||||
			self.initPlugin(attrib)
 | 
			
		||||
			self.plugins[attrib].setValues(value)
 | 
			
		||||
		return self
 | 
			
		||||
	
 | 
			
		||||
	def __delitem__(self, attrib):
 | 
			
		||||
@@ -75,62 +101,18 @@ class StanzaBase(object):
 | 
			
		||||
					return self._delSub(attrib)
 | 
			
		||||
				else:
 | 
			
		||||
					self._delAttr(attrib)
 | 
			
		||||
		return self
 | 
			
		||||
 | 
			
		||||
	def setType(self, value):
 | 
			
		||||
		if value in self.types:
 | 
			
		||||
			if value is None and 'type' in self.xml.attrib:
 | 
			
		||||
				del self.xml.attrib['type']
 | 
			
		||||
			elif value is not None:
 | 
			
		||||
				self.xml.attrib['type'] = value
 | 
			
		||||
		else:
 | 
			
		||||
			raise ValueError
 | 
			
		||||
		return self
 | 
			
		||||
 | 
			
		||||
	def getPayload(self):
 | 
			
		||||
		return self.xml.getchildren()
 | 
			
		||||
	
 | 
			
		||||
	def setPayload(self, value):
 | 
			
		||||
		self.xml.append(value)
 | 
			
		||||
	
 | 
			
		||||
	def delPayload(self):
 | 
			
		||||
		self.clear()
 | 
			
		||||
	
 | 
			
		||||
	def clear(self):
 | 
			
		||||
		for child in self.xml.getchildren():
 | 
			
		||||
			self.xml.remove(child)
 | 
			
		||||
	
 | 
			
		||||
	def reply(self):
 | 
			
		||||
		self['from'], self['to'] = self['to'], self['from']
 | 
			
		||||
		self.clear()
 | 
			
		||||
		elif attrib in self.plugin_map:
 | 
			
		||||
			if attrib in self.plugins:
 | 
			
		||||
				del self.plugins[attrib]
 | 
			
		||||
		return self
 | 
			
		||||
	
 | 
			
		||||
	def error(self):
 | 
			
		||||
		self['type'] = 'error'
 | 
			
		||||
	def __eq__(self, other):
 | 
			
		||||
		values = self.getValues()
 | 
			
		||||
		for key in other:
 | 
			
		||||
			if key not in values or values[key] != other[key]:
 | 
			
		||||
				return False
 | 
			
		||||
		return True
 | 
			
		||||
	
 | 
			
		||||
	def getTo(self):
 | 
			
		||||
		return JID(self._getAttr('to'))
 | 
			
		||||
	
 | 
			
		||||
	def setTo(self, value):
 | 
			
		||||
		return self._setAttr('to', str(value))
 | 
			
		||||
	
 | 
			
		||||
	def getFrom(self):
 | 
			
		||||
		return JID(self._getAttr('from'))
 | 
			
		||||
	
 | 
			
		||||
	def setFrom(self, value):
 | 
			
		||||
		return self._setAttr('from', str(value))
 | 
			
		||||
	
 | 
			
		||||
	def getValues(self):
 | 
			
		||||
		out = {}
 | 
			
		||||
		for interface in self.interfaces:
 | 
			
		||||
			out[interface] = self[interface]
 | 
			
		||||
		return out
 | 
			
		||||
	
 | 
			
		||||
	def setValues(self, attrib):
 | 
			
		||||
		for interface in attrib:
 | 
			
		||||
			if interface in self.interfaces:
 | 
			
		||||
				self[interface] = attrib[interface]
 | 
			
		||||
 | 
			
		||||
	def _setAttr(self, name, value):
 | 
			
		||||
		self.xml.attrib[name] = value
 | 
			
		||||
	
 | 
			
		||||
@@ -162,6 +144,87 @@ class StanzaBase(object):
 | 
			
		||||
			if child.tag == "{%s}%s" % (self.namespace, name):
 | 
			
		||||
				self.xml.remove(child)
 | 
			
		||||
	
 | 
			
		||||
	def getValues(self):
 | 
			
		||||
		out = {}
 | 
			
		||||
		for interface in self.interfaces:
 | 
			
		||||
			out[interface] = self[interface]
 | 
			
		||||
		return out
 | 
			
		||||
	
 | 
			
		||||
	def setValues(self, attrib):
 | 
			
		||||
		for interface in attrib:
 | 
			
		||||
			if interface in self.interfaces:
 | 
			
		||||
				self[interface] = attrib[interface]
 | 
			
		||||
		return self
 | 
			
		||||
	
 | 
			
		||||
	def append(self, xml):
 | 
			
		||||
		self.xml.append(xml)
 | 
			
		||||
		return self
 | 
			
		||||
	
 | 
			
		||||
	def __del__(self):
 | 
			
		||||
		if self.parent is not None:
 | 
			
		||||
			self.parent.xml.remove(self.xml)
 | 
			
		||||
 | 
			
		||||
class StanzaBase(ElementBase):
 | 
			
		||||
	name = 'stanza'
 | 
			
		||||
	namespace = 'jabber:client'
 | 
			
		||||
	interfaces = set(('type', 'to', 'from', 'id', 'payload'))
 | 
			
		||||
	types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat'))
 | 
			
		||||
	sub_interfaces = tuple()
 | 
			
		||||
 | 
			
		||||
	def __init__(self, stream, xml=None, stype=None, sto=None, sfrom=None, sid=None):
 | 
			
		||||
		self.stream = stream
 | 
			
		||||
		self.namespace = stream.default_ns
 | 
			
		||||
		ElementBase.__init__(self, xml)
 | 
			
		||||
		if stype is not None:
 | 
			
		||||
			self['type'] = stype
 | 
			
		||||
		if sto is not None:
 | 
			
		||||
			self['to'] = sto
 | 
			
		||||
		if sfrom is not None:
 | 
			
		||||
			self['from'] = sfrom
 | 
			
		||||
		self.tag = "{%s}%s" % (self.stream.default_ns, self.name)
 | 
			
		||||
	
 | 
			
		||||
	def setType(self, value):
 | 
			
		||||
		if value in self.types:
 | 
			
		||||
				self.xml.attrib['type'] = value
 | 
			
		||||
		else:
 | 
			
		||||
			raise ValueError
 | 
			
		||||
		return self
 | 
			
		||||
 | 
			
		||||
	def getPayload(self):
 | 
			
		||||
		return self.xml.getchildren()
 | 
			
		||||
	
 | 
			
		||||
	def setPayload(self, value):
 | 
			
		||||
		self.xml.append(value)
 | 
			
		||||
	
 | 
			
		||||
	def delPayload(self):
 | 
			
		||||
		self.clear()
 | 
			
		||||
	
 | 
			
		||||
	def clear(self):
 | 
			
		||||
		for child in self.xml.getchildren():
 | 
			
		||||
			self.xml.remove(child)
 | 
			
		||||
		for plugin in self.plugins:
 | 
			
		||||
			del self.plugins[plugin]
 | 
			
		||||
	
 | 
			
		||||
	def reply(self):
 | 
			
		||||
		self['from'], self['to'] = self['to'], self['from']
 | 
			
		||||
		self.clear()
 | 
			
		||||
		return self
 | 
			
		||||
	
 | 
			
		||||
	def error(self):
 | 
			
		||||
		self['type'] = 'error'
 | 
			
		||||
	
 | 
			
		||||
	def getTo(self):
 | 
			
		||||
		return JID(self._getAttr('to'))
 | 
			
		||||
	
 | 
			
		||||
	def setTo(self, value):
 | 
			
		||||
		return self._setAttr('to', str(value))
 | 
			
		||||
	
 | 
			
		||||
	def getFrom(self):
 | 
			
		||||
		return JID(self._getAttr('from'))
 | 
			
		||||
	
 | 
			
		||||
	def setFrom(self, value):
 | 
			
		||||
		return self._setAttr('from', str(value))
 | 
			
		||||
	
 | 
			
		||||
	def unhandled(self):
 | 
			
		||||
		pass
 | 
			
		||||
	
 | 
			
		||||
@@ -226,15 +289,3 @@ class StanzaBase(object):
 | 
			
		||||
					text[cc] = '"'
 | 
			
		||||
			cc += 1
 | 
			
		||||
		return ''.join(text)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
	x = Stanza()
 | 
			
		||||
	x['from'] = 'you'
 | 
			
		||||
	x['to'] = 'me'
 | 
			
		||||
	print(x['from'], x['to'])
 | 
			
		||||
	x.reply()
 | 
			
		||||
	print(x['from'], x['to'])
 | 
			
		||||
	x['from'] = None
 | 
			
		||||
	print(x['from'], x['to'])
 | 
			
		||||
	print(str(x))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user