Added plugin and tests for XEP-0033, Extended Stanza Addresses.

XEP-0033 can be useful for interacting with XMPP<->Email gateways.
This commit is contained in:
Lance Stout 2010-06-22 23:09:50 -04:00
parent 8bb0f5e34c
commit 646a609c0b
3 changed files with 243 additions and 1 deletions

View file

@ -17,4 +17,4 @@
along with SleekXMPP; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
__all__ = ['xep_0004', 'xep_0030', 'xep_0045', 'xep_0050', 'xep_0078', 'xep_0085', 'xep_0092', 'xep_0199', 'gmail_notify', 'xep_0060']
__all__ = ['xep_0004', 'xep_0030', 'xep_0033', 'xep_0045', 'xep_0050', 'xep_0078', 'xep_0085', 'xep_0092', 'xep_0199', 'gmail_notify', 'xep_0060']

View file

@ -0,0 +1,159 @@
"""
SleekXMPP: The Sleek XMPP Library
Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
This file is part of SleekXMPP.
See the file license.txt for copying permission.
"""
import logging
from . import base
from .. xmlstream.handler.callback import Callback
from .. xmlstream.matcher.xpath import MatchXPath
from .. xmlstream.stanzabase import ElementBase, ET, JID
from .. stanza.message import Message
class Addresses(ElementBase):
namespace = 'http://jabber.org/protocol/address'
name = 'addresses'
plugin_attrib = 'addresses'
interfaces = set(('addresses', 'bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'))
def addAddress(self, atype='to', jid='', node='', uri='', desc='', delivered=False):
address = Address(parent=self)
address['type'] = atype
address['jid'] = jid
address['node'] = node
address['uri'] = uri
address['desc'] = desc
address['delivered'] = delivered
return address
def getAddresses(self, atype=None):
addresses = []
for addrXML in self.xml.findall('{%s}address' % Address.namespace):
# ElementTree 1.2.6 does not support [@attr='value'] in findall
if atype is not None and addrXML.get('type') == atype:
self.xml.remove(addrXML)
addresses.append(Address(xml=addrXML, parent=None))
return addresses
def setAddresses(self, addresses, set_type=None):
self.delAddresses(set_type)
for addr in addresses:
# Remap 'type' to 'atype' to match the add method
if set_type is not None:
addr['type'] = set_type
curr_type = addr.get('type', None)
if curr_type is not None:
del addr['type']
addr['atype'] = curr_type
self.addAddress(**addr)
def delAddresses(self, atype=None):
for addrXML in self.xml.findall('{%s}address' % Address.namespace):
# ElementTree 1.2.6 does not support [@attr='value'] in findall
if atype is not None and addrXML.get('type') == atype:
self.xml.remove(addrXML)
# --------------------------------------------------------------
def delBcc(self):
self.delAddresses('bcc')
def delCc(self):
self.delAddresses('cc')
def delNoreply(self):
self.delAddresses('noreply')
def delReplyroom(self):
self.delAddresses('replyroom')
def delReplyto(self):
self.delAddresses('replyto')
def delTo(self):
self.delAddresses('to')
# --------------------------------------------------------------
def getBcc(self):
return self.getAddresses('bcc')
def getCc(self):
return self.getAddresses('cc')
def getNoreply(self):
return self.getAddresses('noreply')
def getReplyroom(self):
return self.getAddresses('replyroom')
def getReplyto(self):
return self.getAddresses('replyto')
def getTo(self):
return self.getAddresses('to')
# --------------------------------------------------------------
def setBcc(self, addresses):
self.setAddresses(addresses, 'bcc')
def setCc(self, addresses):
self.setAddresses(addresses, 'cc')
def setNoreply(self, addresses):
self.setAddresses(addresses, 'noreply')
def setReplyroom(self, addresses):
self.setAddresses(addresses, 'replyroom')
def setReplyto(self, addresses):
self.setAddresses(addresses, 'replyto')
def setTo(self, addresses):
self.setAddresses(addresses, 'to')
class Address(ElementBase):
namespace = 'http://jabber.org/protocol/address'
name = 'address'
plugin_attrib = 'address'
interfaces = set(('delivered', 'desc', 'jid', 'node', 'type', 'uri'))
address_types = set(('bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'))
def getDelivered(self):
return self.attrib.get('delivered', False)
def setDelivered(self, delivered):
if delivered:
self.xml.attrib['delivered'] = "true"
else:
del self['delivered']
def setUri(self, uri):
if uri:
del self['jid']
del self['node']
self.xml.attrib['uri'] = uri
elif 'uri' in self.xml.attrib:
del self.xml.attrib['uri']
class xep_0030(base.base_plugin):
"""
XEP-0033: Extended Stanza Addressing
"""
def plugin_init(self):
self.xep = '0033'
self.description = 'Extended Stanza Addressing'
self.xmpp.stanzaPlugin(Message, Addresses)
def post_init(self):
base.base_plugin.post_init(self)
self.xmpp.plugin['xep_0030'].add_feature(Addresses.namespace)

83
tests/test_addresses.py Normal file
View file

@ -0,0 +1,83 @@
import unittest
from xml.etree import cElementTree as ET
from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath
from . import xmlcompare
import sleekxmpp.plugins.xep_0033 as addr
def stanzaPlugin(stanza, plugin):
stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin
stanza.plugin_tag_map["{%s}%s" % (plugin.namespace, plugin.name)] = plugin
class testaddresses(unittest.TestCase):
def setUp(self):
self.addr = addr
stanzaPlugin(self.addr.Message, self.addr.Addresses)
def try2Methods(self, xmlstring, msg):
msg2 = self.addr.Message(None, self.addr.ET.fromstring(xmlstring))
self.failUnless(xmlstring == str(msg) == str(msg2),
"""Three methods for creating stanza don't match:\n%s\n%s\n%s""" % (xmlstring, str(msg), str(msg2)))
def testAddAddress(self):
"""Testing adding extended stanza address."""
xmlstring = """<message><addresses xmlns="http://jabber.org/protocol/address"><address jid="to@header1.org" type="to" /></addresses></message>"""
msg = self.addr.Message()
msg['addresses'].addAddress(atype='to', jid='to@header1.org')
self.try2Methods(xmlstring, msg)
xmlstring = """<message><addresses xmlns="http://jabber.org/protocol/address"><address jid="replyto@header1.org" type="replyto" desc="Reply address" /></addresses></message>"""
msg = self.addr.Message()
msg['addresses'].addAddress(atype='replyto', jid='replyto@header1.org', desc='Reply address')
self.try2Methods(xmlstring, msg)
def testAddAddresses(self):
"""Testing adding multiple extended stanza addresses."""
xmlstring = """<message><addresses xmlns="http://jabber.org/protocol/address"><address jid="replyto@header1.org" type="replyto" desc="Reply address" /><address jid="cc@header2.org" type="cc" /><address jid="bcc@header2.org" type="bcc" /></addresses></message>"""
msg = self.addr.Message()
msg['addresses'].setAddresses([{'type':'replyto', 'jid':'replyto@header1.org', 'desc':'Reply address'},
{'type':'cc', 'jid':'cc@header2.org'},
{'type':'bcc', 'jid':'bcc@header2.org'}])
self.try2Methods(xmlstring, msg)
msg = self.addr.Message()
msg['addresses']['replyto'] = [{'jid':'replyto@header1.org', 'desc':'Reply address'}]
msg['addresses']['cc'] = [{'jid':'cc@header2.org'}]
msg['addresses']['bcc'] = [{'jid':'bcc@header2.org'}]
self.try2Methods(xmlstring, msg)
def testAddURI(self):
"""Testing adding URI attribute to extended stanza address."""
xmlstring = """<message><addresses xmlns="http://jabber.org/protocol/address"><address node="foo" jid="to@header1.org" type="to" /></addresses></message>"""
msg = self.addr.Message()
addr = msg['addresses'].addAddress(atype='to', jid='to@header1.org', node='foo')
self.try2Methods(xmlstring, msg)
xmlstring = """<message><addresses xmlns="http://jabber.org/protocol/address"><address type="to" uri="mailto:to@header2.org" /></addresses></message>"""
addr['uri'] = 'mailto:to@header2.org'
self.try2Methods(xmlstring, msg)
def testDelivered(self):
"""Testing delivered attribute of extended stanza addresses."""
xmlstring = """<message><addresses xmlns="http://jabber.org/protocol/address"><address %sjid="to@header1.org" type="to" /></addresses></message>"""
msg = self.addr.Message()
addr = msg['addresses'].addAddress(jid='to@header1.org', atype='to')
self.try2Methods(xmlstring % '', msg)
addr['delivered'] = True
self.try2Methods(xmlstring % 'delivered="true" ', msg)
addr['delivered'] = False
self.try2Methods(xmlstring % '', msg)
suite = unittest.TestLoader().loadTestsFromTestCase(testaddresses)