Compare commits
	
		
			30 Commits
		
	
	
		
			1.1.7
			...
			sleek-1.1.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					acd9c32a9f | ||
| 
						 | 
					b8581b0278 | ||
| 
						 | 
					917faecdcb | ||
| 
						 | 
					f6edaa56a6 | ||
| 
						 | 
					51fee28bf4 | ||
| 
						 | 
					e8a3e92ceb | ||
| 
						 | 
					5df3839b7a | ||
| 
						 | 
					8dcb441f44 | ||
| 
						 | 
					a347cf625a | ||
| 
						 | 
					46f49c7a12 | ||
| 
						 | 
					99701c947e | ||
| 
						 | 
					1baae1b81e | ||
| 
						 | 
					7d20f0e9a6 | ||
| 
						 | 
					fbad22a1cd | ||
| 
						 | 
					5af2f62c04 | ||
| 
						 | 
					4a4a03858e | ||
| 
						 | 
					6819b57353 | ||
| 
						 | 
					88b5e60807 | ||
| 
						 | 
					a26a8bd79c | ||
| 
						 | 
					9307a6915f | ||
| 
						 | 
					85ef2d8d0b | ||
| 
						 | 
					c2c7cc032b | ||
| 
						 | 
					e4911e9391 | ||
| 
						 | 
					b11e1ee92d | ||
| 
						 | 
					5027d00c10 | ||
| 
						 | 
					69ddeceb49 | ||
| 
						 | 
					82698672bb | ||
| 
						 | 
					9cec284947 | ||
| 
						 | 
					dc501d1902 | ||
| 
						 | 
					100e504b7f | 
@@ -45,7 +45,7 @@ The latest source code for SleekXMPP may be found on `Github
 | 
				
			|||||||
``develop`` branch.
 | 
					``develop`` branch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Latest Release**
 | 
					**Latest Release**
 | 
				
			||||||
    - `1.1.7 <http://github.com/fritzy/SleekXMPP/zipball/1.1.7>`_
 | 
					    - `1.1.9 <http://github.com/fritzy/SleekXMPP/zipball/1.1.9>`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Develop Releases**
 | 
					**Develop Releases**
 | 
				
			||||||
    - `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_
 | 
					    - `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_
 | 
				
			||||||
@@ -74,6 +74,7 @@ help with SleekXMPP.
 | 
				
			|||||||
**Chat**
 | 
					**Chat**
 | 
				
			||||||
    `sleek@conference.jabber.org <xmpp:sleek@conference.jabber.org?join>`_
 | 
					    `sleek@conference.jabber.org <xmpp:sleek@conference.jabber.org?join>`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Documentation and Testing
 | 
					Documentation and Testing
 | 
				
			||||||
-------------------------
 | 
					-------------------------
 | 
				
			||||||
Documentation can be found both inline in the code, and as a Sphinx project in ``/docs``.
 | 
					Documentation can be found both inline in the code, and as a Sphinx project in ``/docs``.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,6 +122,19 @@ if __name__ == '__main__':
 | 
				
			|||||||
    xmpp.register_plugin('xep_0060') # PubSub
 | 
					    xmpp.register_plugin('xep_0060') # PubSub
 | 
				
			||||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
					    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # If you are connecting to Facebook and wish to use the
 | 
				
			||||||
 | 
					    # X-FACEBOOK-PLATFORM authentication mechanism, you will need
 | 
				
			||||||
 | 
					    # your API key and an access token. Then you'll set:
 | 
				
			||||||
 | 
					    # xmpp.credentials['api_key'] = 'THE_API_KEY'
 | 
				
			||||||
 | 
					    # xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # If you are connecting to MSN, then you will need an
 | 
				
			||||||
 | 
					    # access token, and it does not matter what JID you
 | 
				
			||||||
 | 
					    # specify other than that the domain is 'messenger.live.com',
 | 
				
			||||||
 | 
					    # so '_@messenger.live.com' will work. You can specify
 | 
				
			||||||
 | 
					    # the access token as so:
 | 
				
			||||||
 | 
					    # xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # If you are working with an OpenFire server, you may need
 | 
					    # If you are working with an OpenFire server, you may need
 | 
				
			||||||
    # to adjust the SSL version used:
 | 
					    # to adjust the SSL version used:
 | 
				
			||||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
					    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								setup.py
									
									
									
									
									
								
							@@ -85,6 +85,7 @@ packages     = [ 'sleekxmpp',
 | 
				
			|||||||
                 'sleekxmpp/plugins/xep_0172',
 | 
					                 'sleekxmpp/plugins/xep_0172',
 | 
				
			||||||
                 'sleekxmpp/plugins/xep_0184',
 | 
					                 'sleekxmpp/plugins/xep_0184',
 | 
				
			||||||
                 'sleekxmpp/plugins/xep_0186',
 | 
					                 'sleekxmpp/plugins/xep_0186',
 | 
				
			||||||
 | 
					                 'sleekxmpp/plugins/xep_0191',
 | 
				
			||||||
                 'sleekxmpp/plugins/xep_0198',
 | 
					                 'sleekxmpp/plugins/xep_0198',
 | 
				
			||||||
                 'sleekxmpp/plugins/xep_0199',
 | 
					                 'sleekxmpp/plugins/xep_0199',
 | 
				
			||||||
                 'sleekxmpp/plugins/xep_0202',
 | 
					                 'sleekxmpp/plugins/xep_0202',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,7 +99,7 @@ class APIRegistry(object):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        self._setup(ctype, op)
 | 
					        self._setup(ctype, op)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if jid in (None, ''):
 | 
					        if not jid:
 | 
				
			||||||
            jid = self.xmpp.boundjid
 | 
					            jid = self.xmpp.boundjid
 | 
				
			||||||
        if jid and not isinstance(jid, JID):
 | 
					        if jid and not isinstance(jid, JID):
 | 
				
			||||||
            jid = JID(jid)
 | 
					            jid = JID(jid)
 | 
				
			||||||
@@ -113,7 +113,7 @@ class APIRegistry(object):
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                jid = jid.full
 | 
					                jid = jid.full
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            if self.settings[ctype].get('client_bare', True):
 | 
					            if self.settings[ctype].get('client_bare', False):
 | 
				
			||||||
                jid = jid.bare
 | 
					                jid = jid.bare
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                jid = jid.full
 | 
					                jid = jid.full
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ from __future__ import with_statement, unicode_literals
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					import threading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sleekxmpp
 | 
					import sleekxmpp
 | 
				
			||||||
from sleekxmpp import plugins, features, roster
 | 
					from sleekxmpp import plugins, features, roster
 | 
				
			||||||
@@ -69,8 +70,11 @@ class BaseXMPP(XMLStream):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        #: The JabberID (JID) used by this connection.
 | 
					        #: The JabberID (JID) used by this connection.
 | 
				
			||||||
        self.boundjid = JID(jid)
 | 
					        self.boundjid = JID(jid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._expected_server_name = self.boundjid.host
 | 
					        self._expected_server_name = self.boundjid.host
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.session_bind_event = threading.Event()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #: A dictionary mapping plugin names to plugins.
 | 
					        #: A dictionary mapping plugin names to plugins.
 | 
				
			||||||
        self.plugin = PluginManager(self)
 | 
					        self.plugin = PluginManager(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,13 +91,13 @@ class BaseXMPP(XMLStream):
 | 
				
			|||||||
        #: owner JIDs, as in the case for components. For clients
 | 
					        #: owner JIDs, as in the case for components. For clients
 | 
				
			||||||
        #: which only have a single JID, see :attr:`client_roster`.
 | 
					        #: which only have a single JID, see :attr:`client_roster`.
 | 
				
			||||||
        self.roster = roster.Roster(self)
 | 
					        self.roster = roster.Roster(self)
 | 
				
			||||||
        self.roster.add(self.boundjid.bare)
 | 
					        self.roster.add(self.boundjid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #: The single roster for the bound JID. This is the
 | 
					        #: The single roster for the bound JID. This is the
 | 
				
			||||||
        #: equivalent of::
 | 
					        #: equivalent of::
 | 
				
			||||||
        #:
 | 
					        #:
 | 
				
			||||||
        #:     self.roster[self.boundjid.bare]
 | 
					        #:     self.roster[self.boundjid.bare]
 | 
				
			||||||
        self.client_roster = self.roster[self.boundjid.bare]
 | 
					        self.client_roster = self.roster[self.boundjid]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #: The distinction between clients and components can be
 | 
					        #: The distinction between clients and components can be
 | 
				
			||||||
        #: important, primarily for choosing how to handle the
 | 
					        #: important, primarily for choosing how to handle the
 | 
				
			||||||
@@ -134,6 +138,7 @@ class BaseXMPP(XMLStream):
 | 
				
			|||||||
            Callback('Presence',
 | 
					            Callback('Presence',
 | 
				
			||||||
                     MatchXPath("{%s}presence" % self.default_ns),
 | 
					                     MatchXPath("{%s}presence" % self.default_ns),
 | 
				
			||||||
                     self._handle_presence))
 | 
					                     self._handle_presence))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.register_handler(
 | 
					        self.register_handler(
 | 
				
			||||||
            Callback('Stream Error',
 | 
					            Callback('Stream Error',
 | 
				
			||||||
                     MatchXPath("{%s}error" % self.stream_ns),
 | 
					                     MatchXPath("{%s}error" % self.stream_ns),
 | 
				
			||||||
@@ -654,27 +659,45 @@ class BaseXMPP(XMLStream):
 | 
				
			|||||||
    def _handle_disconnected(self, event):
 | 
					    def _handle_disconnected(self, event):
 | 
				
			||||||
        """When disconnected, reset the roster"""
 | 
					        """When disconnected, reset the roster"""
 | 
				
			||||||
        self.roster.reset()
 | 
					        self.roster.reset()
 | 
				
			||||||
 | 
					        self.session_bind_event.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_stream_error(self, error):
 | 
					    def _handle_stream_error(self, error):
 | 
				
			||||||
        self.event('stream_error', error)
 | 
					        self.event('stream_error', error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if error['condition'] == 'see-other-host':
 | 
				
			||||||
 | 
					            other_host = error['see_other_host']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            host = other_host
 | 
				
			||||||
 | 
					            port = 5222
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if '[' in other_host and ']' in other_host:
 | 
				
			||||||
 | 
					                host = other_host.split(']')[0][1:]
 | 
				
			||||||
 | 
					            elif ':' in other_host:
 | 
				
			||||||
 | 
					                host = other_host.split(':')[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            port_sec = other_host.split(']')[-1]
 | 
				
			||||||
 | 
					            if ':' in port_sec:
 | 
				
			||||||
 | 
					                port = int(port_sec.split(':')[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.address = (host, port)
 | 
				
			||||||
 | 
					            self.default_domain = host
 | 
				
			||||||
 | 
					            self.dns_records = None
 | 
				
			||||||
 | 
					            self.reconnect_delay = None
 | 
				
			||||||
 | 
					            self.reconnect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_message(self, msg):
 | 
					    def _handle_message(self, msg):
 | 
				
			||||||
        """Process incoming message stanzas."""
 | 
					        """Process incoming message stanzas."""
 | 
				
			||||||
        if not self.is_component and not msg['to'].bare:
 | 
					        if not self.is_component and not msg['to'].bare:
 | 
				
			||||||
            msg['to'] = self.boundjid
 | 
					            msg['to'] = self.boundjid
 | 
				
			||||||
        self.event('message', msg)
 | 
					        self.event('message', msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_available(self, presence):
 | 
					    def _handle_available(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_available(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].handle_available(presence)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_unavailable(self, presence):
 | 
					    def _handle_unavailable(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_unavailable(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].handle_unavailable(presence)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_new_subscription(self, stanza):
 | 
					    def _handle_new_subscription(self, pres):
 | 
				
			||||||
        """Attempt to automatically handle subscription requests.
 | 
					        """Attempt to automatically handle subscription requests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Subscriptions will be approved if the request is from
 | 
					        Subscriptions will be approved if the request is from
 | 
				
			||||||
@@ -686,8 +709,8 @@ class BaseXMPP(XMLStream):
 | 
				
			|||||||
        If a subscription is accepted, a request for a mutual
 | 
					        If a subscription is accepted, a request for a mutual
 | 
				
			||||||
        subscription will be sent if :attr:`auto_subscribe` is ``True``.
 | 
					        subscription will be sent if :attr:`auto_subscribe` is ``True``.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        roster = self.roster[stanza['to'].bare]
 | 
					        roster = self.roster[pres['to']]
 | 
				
			||||||
        item = self.roster[stanza['to'].bare][stanza['from'].bare]
 | 
					        item = self.roster[pres['to']][pres['from']]
 | 
				
			||||||
        if item['whitelisted']:
 | 
					        if item['whitelisted']:
 | 
				
			||||||
            item.authorize()
 | 
					            item.authorize()
 | 
				
			||||||
        elif roster.auto_authorize:
 | 
					        elif roster.auto_authorize:
 | 
				
			||||||
@@ -697,30 +720,20 @@ class BaseXMPP(XMLStream):
 | 
				
			|||||||
        elif roster.auto_authorize == False:
 | 
					        elif roster.auto_authorize == False:
 | 
				
			||||||
            item.unauthorize()
 | 
					            item.unauthorize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_removed_subscription(self, presence):
 | 
					    def _handle_removed_subscription(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_unauthorize(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].unauthorize()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_subscribe(self, presence):
 | 
					    def _handle_subscribe(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_subscribe(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].handle_subscribe(presence)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_subscribed(self, presence):
 | 
					    def _handle_subscribed(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_subscribed(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].handle_subscribed(presence)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_unsubscribe(self, presence):
 | 
					    def _handle_unsubscribe(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_unsubscribe(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].handle_unsubscribe(presence)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_unsubscribed(self, presence):
 | 
					    def _handle_unsubscribed(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_unsubscribed(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].handle_unsubscribed(presence)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_presence(self, presence):
 | 
					    def _handle_presence(self, presence):
 | 
				
			||||||
        """Process incoming presence stanzas.
 | 
					        """Process incoming presence stanzas.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,6 +173,12 @@ class ClientXMPP(BaseXMPP):
 | 
				
			|||||||
        self._stream_feature_order.append((order, name))
 | 
					        self._stream_feature_order.append((order, name))
 | 
				
			||||||
        self._stream_feature_order.sort()
 | 
					        self._stream_feature_order.sort()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def unregister_feature(self, name, order):
 | 
				
			||||||
 | 
					        if name in self._stream_feature_handlers:
 | 
				
			||||||
 | 
					            del self._stream_feature_handlers[name]
 | 
				
			||||||
 | 
					        self._stream_feature_order.remove((order, name))
 | 
				
			||||||
 | 
					        self._stream_feature_order.sort()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_roster(self, jid, name=None, subscription=None, groups=[],
 | 
					    def update_roster(self, jid, name=None, subscription=None, groups=[],
 | 
				
			||||||
                            block=True, timeout=None, callback=None):
 | 
					                            block=True, timeout=None, callback=None):
 | 
				
			||||||
        """Add or change a roster item.
 | 
					        """Add or change a roster item.
 | 
				
			||||||
@@ -270,8 +276,9 @@ class ClientXMPP(BaseXMPP):
 | 
				
			|||||||
        roster = self.client_roster
 | 
					        roster = self.client_roster
 | 
				
			||||||
        if iq['roster']['ver']:
 | 
					        if iq['roster']['ver']:
 | 
				
			||||||
            roster.version = iq['roster']['ver']
 | 
					            roster.version = iq['roster']['ver']
 | 
				
			||||||
        for jid in iq['roster']['items']:
 | 
					        items = iq['roster']['items']
 | 
				
			||||||
            item = iq['roster']['items'][jid]
 | 
					        for jid in items:
 | 
				
			||||||
 | 
					            item = items[jid]
 | 
				
			||||||
            roster[jid]['name'] = item['name']
 | 
					            roster[jid]['name'] = item['name']
 | 
				
			||||||
            roster[jid]['groups'] = item['groups']
 | 
					            roster[jid]['groups'] = item['groups']
 | 
				
			||||||
            roster[jid]['from'] = item['subscription'] in ['from', 'both']
 | 
					            roster[jid]['from'] = item['subscription'] in ['from', 'both']
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -156,10 +156,10 @@ class ComponentXMPP(BaseXMPP):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        :param xml: The reply handshake stanza.
 | 
					        :param xml: The reply handshake stanza.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					        self.session_bind_event.set()
 | 
				
			||||||
        self.session_started_event.set()
 | 
					        self.session_started_event.set()
 | 
				
			||||||
 | 
					        self.event("session_bind", self.xmpp.boundjid, direct=True)
 | 
				
			||||||
        self.event("session_start")
 | 
					        self.event("session_start")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_probe(self, presence):
 | 
					    def _handle_probe(self, pres):
 | 
				
			||||||
        pto = presence['to'].bare
 | 
					        self.roster[pres['to']][pres['from']].handle_probe(pres)
 | 
				
			||||||
        pfrom = presence['from'].bare
 | 
					 | 
				
			||||||
        self.roster[pto][pfrom].handle_probe(presence)
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,7 @@ class FeatureBind(BasePlugin):
 | 
				
			|||||||
        self.xmpp.set_jid(response['bind']['jid'])
 | 
					        self.xmpp.set_jid(response['bind']['jid'])
 | 
				
			||||||
        self.xmpp.bound = True
 | 
					        self.xmpp.bound = True
 | 
				
			||||||
        self.xmpp.event('session_bind', self.xmpp.boundjid, direct=True)
 | 
					        self.xmpp.event('session_bind', self.xmpp.boundjid, direct=True)
 | 
				
			||||||
 | 
					        self.xmpp.session_bind_event.set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp.features.add('bind')
 | 
					        self.xmpp.features.add('bind')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,7 @@ __all__ = [
 | 
				
			|||||||
    'xep_0172',  # User Nickname
 | 
					    'xep_0172',  # User Nickname
 | 
				
			||||||
    'xep_0184',  # Message Receipts
 | 
					    'xep_0184',  # Message Receipts
 | 
				
			||||||
    'xep_0186',  # Invisible Command
 | 
					    'xep_0186',  # Invisible Command
 | 
				
			||||||
 | 
					    'xep_0191',  # Blocking Command
 | 
				
			||||||
    'xep_0198',  # Stream Management
 | 
					    'xep_0198',  # Stream Management
 | 
				
			||||||
    'xep_0199',  # Ping
 | 
					    'xep_0199',  # Ping
 | 
				
			||||||
    'xep_0202',  # Entity Time
 | 
					    'xep_0202',  # Entity Time
 | 
				
			||||||
@@ -56,5 +57,8 @@ __all__ = [
 | 
				
			|||||||
    'xep_0224',  # Attention
 | 
					    'xep_0224',  # Attention
 | 
				
			||||||
    'xep_0231',  # Bits of Binary
 | 
					    'xep_0231',  # Bits of Binary
 | 
				
			||||||
    'xep_0249',  # Direct MUC Invitations
 | 
					    'xep_0249',  # Direct MUC Invitations
 | 
				
			||||||
 | 
					    'xep_0256',  # Last Activity in Presence
 | 
				
			||||||
    'xep_0258',  # Security Labels in XMPP
 | 
					    'xep_0258',  # Security Labels in XMPP
 | 
				
			||||||
 | 
					    'xep_0270',  # XMPP Compliance Suites 2010
 | 
				
			||||||
 | 
					    'xep_0302',  # XMPP Compliance Suites 2012
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -167,8 +167,7 @@ class PluginManager(object):
 | 
				
			|||||||
                self._plugins[name] = plugin
 | 
					                self._plugins[name] = plugin
 | 
				
			||||||
                for dep in plugin.dependencies:
 | 
					                for dep in plugin.dependencies:
 | 
				
			||||||
                    self.enable(dep, enabled=enabled)
 | 
					                    self.enable(dep, enabled=enabled)
 | 
				
			||||||
                plugin.plugin_init()
 | 
					                plugin._init()
 | 
				
			||||||
                log.debug("Loaded Plugin: %s", plugin.description)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if top_level:
 | 
					        if top_level:
 | 
				
			||||||
            for name in enabled:
 | 
					            for name in enabled:
 | 
				
			||||||
@@ -229,7 +228,7 @@ class PluginManager(object):
 | 
				
			|||||||
                    raise PluginNotFound(name)
 | 
					                    raise PluginNotFound(name)
 | 
				
			||||||
                for dep in PLUGIN_DEPENDENTS[name]:
 | 
					                for dep in PLUGIN_DEPENDENTS[name]:
 | 
				
			||||||
                    self.disable(dep, _disabled)
 | 
					                    self.disable(dep, _disabled)
 | 
				
			||||||
                plugin.plugin_end()
 | 
					                plugin._end()
 | 
				
			||||||
                if name in self._enabled:
 | 
					                if name in self._enabled:
 | 
				
			||||||
                    self._enabled.remove(name)
 | 
					                    self._enabled.remove(name)
 | 
				
			||||||
                del self._plugins[name]
 | 
					                del self._plugins[name]
 | 
				
			||||||
@@ -282,6 +281,28 @@ class BasePlugin(object):
 | 
				
			|||||||
        #: configuration settings will be provided as a dictionary.
 | 
					        #: configuration settings will be provided as a dictionary.
 | 
				
			||||||
        self.config = config if config is not None else {}
 | 
					        self.config = config if config is not None else {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _init(self):
 | 
				
			||||||
 | 
					        """Initialize plugin state, such as registering event handlers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Also sets up required event handlers.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if self.xmpp is not None:
 | 
				
			||||||
 | 
					            self.xmpp.add_event_handler('session_bind', self.session_bind)
 | 
				
			||||||
 | 
					            if self.xmpp.session_bind_event.is_set():
 | 
				
			||||||
 | 
					                self.session_bind(self.xmpp.boundjid.full)
 | 
				
			||||||
 | 
					        self.plugin_init()
 | 
				
			||||||
 | 
					        log.debug('Loaded Plugin: %s', self.description)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _end(self):
 | 
				
			||||||
 | 
					        """Cleanup plugin state, and prepare for plugin removal.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Also removes required event handlers.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if self.xmpp is not None:
 | 
				
			||||||
 | 
					            self.xmpp.del_event_handler('session_bind', self.session_bind)
 | 
				
			||||||
 | 
					        self.plugin_end()
 | 
				
			||||||
 | 
					        log.debug('Disabled Plugin: %s' % self.description)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        """Initialize plugin state, such as registering event handlers."""
 | 
					        """Initialize plugin state, such as registering event handlers."""
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
@@ -290,6 +311,10 @@ class BasePlugin(object):
 | 
				
			|||||||
        """Cleanup plugin state, and prepare for plugin removal."""
 | 
					        """Cleanup plugin state, and prepare for plugin removal."""
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        """Initialize plugin state based on the bound JID."""
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def post_init(self):
 | 
					    def post_init(self):
 | 
				
			||||||
        """Initialize any cross-plugin state.
 | 
					        """Initialize any cross-plugin state.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@ class XEP_0004(BasePlugin):
 | 
				
			|||||||
    stanza = stanza
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        self.xmpp.registerHandler(
 | 
					        self.xmpp.register_handler(
 | 
				
			||||||
            Callback('Data Form',
 | 
					            Callback('Data Form',
 | 
				
			||||||
                 StanzaPath('message/form'),
 | 
					                 StanzaPath('message/form'),
 | 
				
			||||||
                 self.handle_form))
 | 
					                 self.handle_form))
 | 
				
			||||||
@@ -36,6 +36,11 @@ class XEP_0004(BasePlugin):
 | 
				
			|||||||
        register_stanza_plugin(Form, FormField, iterable=True)
 | 
					        register_stanza_plugin(Form, FormField, iterable=True)
 | 
				
			||||||
        register_stanza_plugin(Message, Form)
 | 
					        register_stanza_plugin(Message, Form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Data Form')
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature='jabber:x:data')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature('jabber:x:data')
 | 
					        self.xmpp['xep_0030'].add_feature('jabber:x:data')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def make_form(self, ftype='form', title='', instructions=''):
 | 
					    def make_form(self, ftype='form', title='', instructions=''):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,13 +37,11 @@ class XEP_0012(BasePlugin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self._last_activities = {}
 | 
					        self._last_activities = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp.registerHandler(
 | 
					        self.xmpp.register_handler(
 | 
				
			||||||
            Callback('Last Activity',
 | 
					            Callback('Last Activity',
 | 
				
			||||||
                 StanzaPath('iq@type=get/last_activity'),
 | 
					                 StanzaPath('iq@type=get/last_activity'),
 | 
				
			||||||
                 self._handle_get_last_activity))
 | 
					                 self._handle_get_last_activity))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:last')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.api.register(self._default_get_last_activity,
 | 
					        self.api.register(self._default_get_last_activity,
 | 
				
			||||||
                'get_last_activity',
 | 
					                'get_last_activity',
 | 
				
			||||||
                default=True)
 | 
					                default=True)
 | 
				
			||||||
@@ -54,6 +52,13 @@ class XEP_0012(BasePlugin):
 | 
				
			|||||||
                'del_last_activity',
 | 
					                'del_last_activity',
 | 
				
			||||||
                default=True)
 | 
					                default=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Last Activity')
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature='jabber:iq:last')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].add_feature('jabber:iq:last')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def begin_idle(self, jid=None, status=None):
 | 
					    def begin_idle(self, jid=None, status=None):
 | 
				
			||||||
        self.set_last_activity(jid, 0, status)
 | 
					        self.set_last_activity(jid, 0, status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,13 @@ class XEP_0027(BasePlugin):
 | 
				
			|||||||
                    StanzaPath('message/encrypted'),
 | 
					                    StanzaPath('message/encrypted'),
 | 
				
			||||||
                    self._handle_encrypted_message))
 | 
					                    self._handle_encrypted_message))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Encrypted Message')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Signed Presence')
 | 
				
			||||||
 | 
					        self.xmpp.del_filter('out', self._sign_presence)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('unverified_signed_presence',
 | 
				
			||||||
 | 
					                self._handle_unverified_signed_presence)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _sign_presence(self, stanza):
 | 
					    def _sign_presence(self, stanza):
 | 
				
			||||||
        if isinstance(stanza, Presence):
 | 
					        if isinstance(stanza, Presence):
 | 
				
			||||||
            if stanza['type'] == 'available' or \
 | 
					            if stanza['type'] == 'available' or \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -622,11 +622,7 @@ class XEP_0030(BasePlugin):
 | 
				
			|||||||
        if iq['type'] == 'get':
 | 
					        if iq['type'] == 'get':
 | 
				
			||||||
            log.debug("Received disco info query from " + \
 | 
					            log.debug("Received disco info query from " + \
 | 
				
			||||||
                      "<%s> to <%s>.", iq['from'], iq['to'])
 | 
					                      "<%s> to <%s>.", iq['from'], iq['to'])
 | 
				
			||||||
            if self.xmpp.is_component:
 | 
					            info = self.api['get_info'](iq['to'],
 | 
				
			||||||
                jid = iq['to'].full
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                jid = iq['to'].bare
 | 
					 | 
				
			||||||
            info = self.api['get_info'](jid,
 | 
					 | 
				
			||||||
                                        iq['disco_info']['node'],
 | 
					                                        iq['disco_info']['node'],
 | 
				
			||||||
                                        iq['from'],
 | 
					                                        iq['from'],
 | 
				
			||||||
                                        iq)
 | 
					                                        iq)
 | 
				
			||||||
@@ -649,7 +645,7 @@ class XEP_0030(BasePlugin):
 | 
				
			|||||||
                    ito = iq['to'].full
 | 
					                    ito = iq['to'].full
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    ito = None
 | 
					                    ito = None
 | 
				
			||||||
                self.api['cache_info'](iq['from'].full,
 | 
					                self.api['cache_info'](iq['from'],
 | 
				
			||||||
                                       iq['disco_info']['node'],
 | 
					                                       iq['disco_info']['node'],
 | 
				
			||||||
                                       ito,
 | 
					                                       ito,
 | 
				
			||||||
                                       iq)
 | 
					                                       iq)
 | 
				
			||||||
@@ -667,13 +663,9 @@ class XEP_0030(BasePlugin):
 | 
				
			|||||||
        if iq['type'] == 'get':
 | 
					        if iq['type'] == 'get':
 | 
				
			||||||
            log.debug("Received disco items query from " + \
 | 
					            log.debug("Received disco items query from " + \
 | 
				
			||||||
                      "<%s> to <%s>.", iq['from'], iq['to'])
 | 
					                      "<%s> to <%s>.", iq['from'], iq['to'])
 | 
				
			||||||
            if self.xmpp.is_component:
 | 
					            items = self.api['get_items'](iq['to'],
 | 
				
			||||||
                jid = iq['to'].full
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                jid = iq['to'].bare
 | 
					 | 
				
			||||||
            items = self.api['get_items'](jid,
 | 
					 | 
				
			||||||
                                          iq['disco_items']['node'],
 | 
					                                          iq['disco_items']['node'],
 | 
				
			||||||
                                          iq['from'].full,
 | 
					                                          iq['from'],
 | 
				
			||||||
                                          iq)
 | 
					                                          iq)
 | 
				
			||||||
            if isinstance(items, Iq):
 | 
					            if isinstance(items, Iq):
 | 
				
			||||||
                items.send()
 | 
					                items.send()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -237,7 +237,7 @@ class StaticDisco(object):
 | 
				
			|||||||
        with self.lock:
 | 
					        with self.lock:
 | 
				
			||||||
            if not self.node_exists(jid, node):
 | 
					            if not self.node_exists(jid, node):
 | 
				
			||||||
                if not node:
 | 
					                if not node:
 | 
				
			||||||
                    return DiscoInfo()
 | 
					                    return DiscoItems()
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    raise XMPPError(condition='item-not-found')
 | 
					                    raise XMPPError(condition='item-not-found')
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
@@ -424,9 +424,6 @@ class StaticDisco(object):
 | 
				
			|||||||
        The data parameter is not used.
 | 
					        The data parameter is not used.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        with self.lock:
 | 
					        with self.lock:
 | 
				
			||||||
            if isinstance(jid, JID):
 | 
					 | 
				
			||||||
                jid = jid.full
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if not self.node_exists(jid, node, ifrom):
 | 
					            if not self.node_exists(jid, node, ifrom):
 | 
				
			||||||
                return None
 | 
					                return None
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,12 @@ class XEP_0033(BasePlugin):
 | 
				
			|||||||
    stanza = stanza
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(Addresses.namespace)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        register_stanza_plugin(Message, Addresses)
 | 
					        register_stanza_plugin(Message, Addresses)
 | 
				
			||||||
        register_stanza_plugin(Presence, Addresses)
 | 
					        register_stanza_plugin(Presence, Addresses)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=Addresses.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].add_feature(Addresses.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,13 @@ class XEP_0047(BasePlugin):
 | 
				
			|||||||
            StanzaPath('iq@type=set/ibb_data'),
 | 
					            StanzaPath('iq@type=set/ibb_data'),
 | 
				
			||||||
            self._handle_data))
 | 
					            self._handle_data))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('IBB Open')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('IBB Close')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('IBB Data')
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature='http://jabber.org/protocol/ibb')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature('http://jabber.org/protocol/ibb')
 | 
					        self.xmpp['xep_0030'].add_feature('http://jabber.org/protocol/ibb')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _accept_stream(self, iq):
 | 
					    def _accept_stream(self, iq):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,6 +110,20 @@ class XEP_0050(BasePlugin):
 | 
				
			|||||||
                                    self._handle_command_complete,
 | 
					                                    self._handle_command_complete,
 | 
				
			||||||
                                    threaded=self.threaded)
 | 
					                                    threaded=self.threaded)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('command_execute',
 | 
				
			||||||
 | 
					                                    self._handle_command_start)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('command_next',
 | 
				
			||||||
 | 
					                                    self._handle_command_next)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('command_cancel',
 | 
				
			||||||
 | 
					                                    self._handle_command_cancel)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('command_complete',
 | 
				
			||||||
 | 
					                                    self._handle_command_complete)
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Ad-Hoc Execute')
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=Command.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].set_items(node=Command.namespace, items=tuple())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(Command.namespace)
 | 
					        self.xmpp['xep_0030'].add_feature(Command.namespace)
 | 
				
			||||||
        self.xmpp['xep_0030'].set_items(node=Command.namespace, items=tuple())
 | 
					        self.xmpp['xep_0030'].set_items(node=Command.namespace, items=tuple())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,6 @@ class XEP_0054(BasePlugin):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        register_stanza_plugin(Iq, VCardTemp)
 | 
					        register_stanza_plugin(Iq, VCardTemp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature('vcard-temp')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.api.register(self._set_vcard, 'set_vcard', default=True)
 | 
					        self.api.register(self._set_vcard, 'set_vcard', default=True)
 | 
				
			||||||
        self.api.register(self._get_vcard, 'get_vcard', default=True)
 | 
					        self.api.register(self._get_vcard, 'get_vcard', default=True)
 | 
				
			||||||
@@ -50,6 +49,13 @@ class XEP_0054(BasePlugin):
 | 
				
			|||||||
                    StanzaPath('iq/vcard_temp'),
 | 
					                    StanzaPath('iq/vcard_temp'),
 | 
				
			||||||
                    self._handle_get_vcard))
 | 
					                    self._handle_get_vcard))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('VCardTemp')
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature='vcard-temp')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].add_feature('vcard-temp')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def make_vcard(self):
 | 
					    def make_vcard(self):
 | 
				
			||||||
        return VCardTemp()
 | 
					        return VCardTemp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,7 @@ class ResultIterator():
 | 
				
			|||||||
        self.start = start
 | 
					        self.start = start
 | 
				
			||||||
        self.interface = interface
 | 
					        self.interface = interface
 | 
				
			||||||
        self.reverse = reverse
 | 
					        self.reverse = reverse
 | 
				
			||||||
 | 
					        self._stop = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __iter__(self):
 | 
					    def __iter__(self):
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
@@ -62,6 +63,8 @@ class ResultIterator():
 | 
				
			|||||||
              results will be the items before the current page
 | 
					              results will be the items before the current page
 | 
				
			||||||
              of items.
 | 
					              of items.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					        if self._stop:
 | 
				
			||||||
 | 
					            raise StopIteration
 | 
				
			||||||
        self.query[self.interface]['rsm']['before'] = self.reverse
 | 
					        self.query[self.interface]['rsm']['before'] = self.reverse
 | 
				
			||||||
        self.query['id'] = self.query.stream.new_id()
 | 
					        self.query['id'] = self.query.stream.new_id()
 | 
				
			||||||
        self.query[self.interface]['rsm']['max'] = str(self.amount)
 | 
					        self.query[self.interface]['rsm']['max'] = str(self.amount)
 | 
				
			||||||
@@ -84,7 +87,7 @@ class ResultIterator():
 | 
				
			|||||||
                first = int(r[self.interface]['rsm']['first_index'])
 | 
					                first = int(r[self.interface]['rsm']['first_index'])
 | 
				
			||||||
                num_items = len(r[self.interface]['substanzas'])
 | 
					                num_items = len(r[self.interface]['substanzas'])
 | 
				
			||||||
                if first + num_items == count:
 | 
					                if first + num_items == count:
 | 
				
			||||||
                    raise StopIteration
 | 
					                    self._stop = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self.reverse:
 | 
					            if self.reverse:
 | 
				
			||||||
                self.start = r[self.interface]['rsm']['first']
 | 
					                self.start = r[self.interface]['rsm']['first']
 | 
				
			||||||
@@ -111,10 +114,15 @@ class XEP_0059(BasePlugin):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        Start the XEP-0059 plugin.
 | 
					        Start the XEP-0059 plugin.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(Set.namespace)
 | 
					 | 
				
			||||||
        register_stanza_plugin(self.xmpp['xep_0030'].stanza.DiscoItems,
 | 
					        register_stanza_plugin(self.xmpp['xep_0030'].stanza.DiscoItems,
 | 
				
			||||||
                               self.stanza.Set)
 | 
					                               self.stanza.Set)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=Set.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].add_feature(Set.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def iterate(self, stanza, interface):
 | 
					    def iterate(self, stanza, interface):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Create a new result set iterator for a given stanza query.
 | 
					        Create a new result set iterator for a given stanza query.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,13 @@ class XEP_0060(BasePlugin):
 | 
				
			|||||||
                    StanzaPath('message/pubsub_event/subscription'),
 | 
					                    StanzaPath('message/pubsub_event/subscription'),
 | 
				
			||||||
                    self._handle_event_subscription))
 | 
					                    self._handle_event_subscription))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Pubsub Event: Items')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Pubsub Event: Purge')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Pubsub Event: Delete')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Pubsub Event: Configuration')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Pubsub Event: Subscription')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_event_items(self, msg):
 | 
					    def _handle_event_items(self, msg):
 | 
				
			||||||
        """Raise events for publish and retraction notifications."""
 | 
					        """Raise events for publish and retraction notifications."""
 | 
				
			||||||
        node = msg['pubsub_event']['items']['node']
 | 
					        node = msg['pubsub_event']['items']['node']
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,6 +62,12 @@ class XEP_0066(BasePlugin):
 | 
				
			|||||||
                         StanzaPath('iq@type=set/oob_transfer'),
 | 
					                         StanzaPath('iq@type=set/oob_transfer'),
 | 
				
			||||||
                         self._handle_transfer))
 | 
					                         self._handle_transfer))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('OOB Transfer')
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=stanza.OOBTransfer.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=stanza.OOB.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(stanza.OOBTransfer.namespace)
 | 
					        self.xmpp['xep_0030'].add_feature(stanza.OOBTransfer.namespace)
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(stanza.OOB.namespace)
 | 
					        self.xmpp['xep_0030'].add_feature(stanza.OOB.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,9 +34,7 @@ class XEP_0077(BasePlugin):
 | 
				
			|||||||
        register_stanza_plugin(StreamFeatures, RegisterFeature)
 | 
					        register_stanza_plugin(StreamFeatures, RegisterFeature)
 | 
				
			||||||
        register_stanza_plugin(Iq, Register)
 | 
					        register_stanza_plugin(Iq, Register)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.xmpp.is_component:
 | 
					        if not self.xmpp.is_component:
 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            self.xmpp.register_feature('register',
 | 
					            self.xmpp.register_feature('register',
 | 
				
			||||||
                self._handle_register_feature,
 | 
					                self._handle_register_feature,
 | 
				
			||||||
                restart=False,
 | 
					                restart=False,
 | 
				
			||||||
@@ -45,6 +43,10 @@ class XEP_0077(BasePlugin):
 | 
				
			|||||||
        register_stanza_plugin(Register, self.xmpp['xep_0004'].stanza.Form)
 | 
					        register_stanza_plugin(Register, self.xmpp['xep_0004'].stanza.Form)
 | 
				
			||||||
        register_stanza_plugin(Register, self.xmpp['xep_0066'].stanza.OOB)
 | 
					        register_stanza_plugin(Register, self.xmpp['xep_0066'].stanza.OOB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        if not self.xmpp.is_component:
 | 
				
			||||||
 | 
					            self.xmpp.unregister_feature('register', self.config.get('order', 50))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_register_feature(self, features):
 | 
					    def _handle_register_feature(self, features):
 | 
				
			||||||
        if 'mechanisms' in self.xmpp.features:
 | 
					        if 'mechanisms' in self.xmpp.features:
 | 
				
			||||||
            # We have already logged in with an account
 | 
					            # We have already logged in with an account
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,6 +44,9 @@ class XEP_0078(BasePlugin):
 | 
				
			|||||||
        register_stanza_plugin(Iq, stanza.IqAuth)
 | 
					        register_stanza_plugin(Iq, stanza.IqAuth)
 | 
				
			||||||
        register_stanza_plugin(StreamFeatures, stanza.AuthFeature)
 | 
					        register_stanza_plugin(StreamFeatures, stanza.AuthFeature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.unregister_feature('auth', self.config.get('order', 15))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_auth(self, features):
 | 
					    def _handle_auth(self, features):
 | 
				
			||||||
        # If we can or have already authenticated with SASL, do nothing.
 | 
					        # If we can or have already authenticated with SASL, do nothing.
 | 
				
			||||||
        if 'mechanisms' in features['features']:
 | 
					        if 'mechanisms' in features['features']:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,8 +28,11 @@ class XEP_0080(BasePlugin):
 | 
				
			|||||||
    dependencies = set(['xep_0163'])
 | 
					    dependencies = set(['xep_0163'])
 | 
				
			||||||
    stanza = stanza
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_end(self):
 | 
				
			||||||
        """Start the XEP-0080 plugin."""
 | 
					        self.xmpp['xep_0163'].remove_interest(Geoloc.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=Geoloc.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0163'].register_pep('user_location', Geoloc)
 | 
					        self.xmpp['xep_0163'].register_pep('user_location', Geoloc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publish_location(self, **kwargs):
 | 
					    def publish_location(self, **kwargs):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,14 +28,19 @@ class XEP_0084(BasePlugin):
 | 
				
			|||||||
    stanza = stanza
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        self.xmpp['xep_0163'].register_pep('avatar_metadata', MetaData)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pubsub_stanza = self.xmpp['xep_0060'].stanza
 | 
					        pubsub_stanza = self.xmpp['xep_0060'].stanza
 | 
				
			||||||
        register_stanza_plugin(pubsub_stanza.Item, Data)
 | 
					        register_stanza_plugin(pubsub_stanza.Item, Data)
 | 
				
			||||||
        register_stanza_plugin(pubsub_stanza.EventItem, Data)
 | 
					        register_stanza_plugin(pubsub_stanza.EventItem, Data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp['xep_0060'].map_node_event(Data.namespace, 'avatar_data')
 | 
					        self.xmpp['xep_0060'].map_node_event(Data.namespace, 'avatar_data')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=MetaData.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0163'].remove_interest(MetaData.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0163'].register_pep('avatar_metadata', MetaData)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def retrieve_avatar(self, jid, id, url=None, ifrom=None, block=True,
 | 
					    def retrieve_avatar(self, jid, id, url=None, ifrom=None, block=True,
 | 
				
			||||||
                              callback=None, timeout=None):
 | 
					                              callback=None, timeout=None):
 | 
				
			||||||
        return self.xmpp['xep_0060'].get_item(jid, Data.namespace, id,
 | 
					        return self.xmpp['xep_0060'].get_item(jid, Data.namespace, id,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,6 +43,10 @@ class XEP_0085(BasePlugin):
 | 
				
			|||||||
        register_stanza_plugin(Message, stanza.Inactive)
 | 
					        register_stanza_plugin(Message, stanza.Inactive)
 | 
				
			||||||
        register_stanza_plugin(Message, stanza.Paused)
 | 
					        register_stanza_plugin(Message, stanza.Paused)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Chat State')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp.plugin['xep_0030'].add_feature(ChatState.namespace)
 | 
					        self.xmpp.plugin['xep_0030'].add_feature(ChatState.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_chat_state(self, msg):
 | 
					    def _handle_chat_state(self, msg):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,11 @@ class XEP_0092(BasePlugin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        register_stanza_plugin(Iq, Version)
 | 
					        register_stanza_plugin(Iq, Version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Software Version')
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature='jabber:iq:version')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:version')
 | 
					        self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:version')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_version(self, iq):
 | 
					    def _handle_version(self, iq):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,12 @@ class XEP_0107(BasePlugin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        register_stanza_plugin(Message, UserMood)
 | 
					        register_stanza_plugin(Message, UserMood)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=UserMood.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0163'].remove_interest(UserMood.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0163'].register_pep('user_mood', UserMood)
 | 
					        self.xmpp['xep_0163'].register_pep('user_mood', UserMood)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publish_mood(self, value=None, text=None, options=None,
 | 
					    def publish_mood(self, value=None, text=None, options=None,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,11 @@ class XEP_0108(BasePlugin):
 | 
				
			|||||||
    dependencies = set(['xep_0163'])
 | 
					    dependencies = set(['xep_0163'])
 | 
				
			||||||
    stanza = stanza
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=UserActivity.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0163'].remove_interest(UserActivity.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0163'].register_pep('user_activity', UserActivity)
 | 
					        self.xmpp['xep_0163'].register_pep('user_activity', UserActivity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publish_activity(self, general, specific=None, text=None, options=None,
 | 
					    def publish_activity(self, general, specific=None, text=None, options=None,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,16 +73,15 @@ class XEP_0115(BasePlugin):
 | 
				
			|||||||
                    restart=False,
 | 
					                    restart=False,
 | 
				
			||||||
                    order=10010)
 | 
					                    order=10010)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(stanza.Capabilities.namespace)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        disco = self.xmpp['xep_0030']
 | 
					        disco = self.xmpp['xep_0030']
 | 
				
			||||||
        self.static = StaticCaps(self.xmpp, disco.static)
 | 
					        self.static = StaticCaps(self.xmpp, disco.static)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.api.settings['client_bare'] = False
 | 
					 | 
				
			||||||
        self.api.settings['component_bare'] = False
 | 
					 | 
				
			||||||
        for op in self._disco_ops:
 | 
					        for op in self._disco_ops:
 | 
				
			||||||
            self.api.register(getattr(self.static, op), op, default=True)
 | 
					            self.api.register(getattr(self.static, op), op, default=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for op in ('supports', 'has_identity'):
 | 
				
			||||||
 | 
					            self.xmpp['xep_0030'].api.register(getattr(self.static, op), op)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._run_node_handler = disco._run_node_handler
 | 
					        self._run_node_handler = disco._run_node_handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        disco.cache_caps = self.cache_caps
 | 
					        disco.cache_caps = self.cache_caps
 | 
				
			||||||
@@ -90,6 +89,19 @@ class XEP_0115(BasePlugin):
 | 
				
			|||||||
        disco.assign_verstring = self.assign_verstring
 | 
					        disco.assign_verstring = self.assign_verstring
 | 
				
			||||||
        disco.get_verstring = self.get_verstring
 | 
					        disco.get_verstring = self.get_verstring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=stanza.Capabilities.namespace)
 | 
				
			||||||
 | 
					        self.xmpp.del_filter('out', self._filter_add_caps)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('entity_caps', self._process_caps)
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Entity Capabilities')
 | 
				
			||||||
 | 
					        if not self.xmpp.is_component:
 | 
				
			||||||
 | 
					            self.xmpp.unregister_feature('caps', 10010)
 | 
				
			||||||
 | 
					        for op in ('supports', 'has_identity'):
 | 
				
			||||||
 | 
					            self.xmpp['xep_0030'].restore_defaults(op)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].add_feature(stanza.Capabilities.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _filter_add_caps(self, stanza):
 | 
					    def _filter_add_caps(self, stanza):
 | 
				
			||||||
        if isinstance(stanza, Presence) and self.broadcast:
 | 
					        if isinstance(stanza, Presence) and self.broadcast:
 | 
				
			||||||
            ver = self.get_verstring(stanza['from'])
 | 
					            ver = self.get_verstring(stanza['from'])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,11 @@ class XEP_0118(BasePlugin):
 | 
				
			|||||||
    dependencies = set(['xep_0163'])
 | 
					    dependencies = set(['xep_0163'])
 | 
				
			||||||
    stanza = stanza
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=UserTune.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0163'].remove_interest(UserTune.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0163'].register_pep('user_tune', UserTune)
 | 
					        self.xmpp['xep_0163'].register_pep('user_tune', UserTune)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publish_tune(self, artist=None, length=None, rating=None, source=None,
 | 
					    def publish_tune(self, artist=None, length=None, rating=None, source=None,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,8 +51,6 @@ class XEP_0128(BasePlugin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        register_stanza_plugin(DiscoInfo, Form, iterable=True)
 | 
					        register_stanza_plugin(DiscoInfo, Form, iterable=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def post_init(self):
 | 
					 | 
				
			||||||
        """Handle cross-plugin dependencies."""
 | 
					 | 
				
			||||||
        self.disco = self.xmpp['xep_0030']
 | 
					        self.disco = self.xmpp['xep_0030']
 | 
				
			||||||
        self.static = StaticExtendedDisco(self.disco.static)
 | 
					        self.static = StaticExtendedDisco(self.disco.static)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,15 @@ class XEP_0153(BasePlugin):
 | 
				
			|||||||
        self.api.register(self._set_hash, 'set_hash', default=True)
 | 
					        self.api.register(self._set_hash, 'set_hash', default=True)
 | 
				
			||||||
        self.api.register(self._get_hash, 'get_hash', default=True)
 | 
					        self.api.register(self._get_hash, 'get_hash', default=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.del_filter('out', self._update_presence)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('session_start', self._start)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('presence_available', self._recv_presence)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('presence_dnd', self._recv_presence)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('presence_xa', self._recv_presence)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('presence_chat', self._recv_presence)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('presence_away', self._recv_presence)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_avatar(self, jid=None, avatar=None, mtype=None, block=True,
 | 
					    def set_avatar(self, jid=None, avatar=None, mtype=None, block=True,
 | 
				
			||||||
                   timeout=None, callback=None):
 | 
					                   timeout=None, callback=None):
 | 
				
			||||||
        vcard = self.xmpp['xep_0054'].get_vcard(jid, cached=True)
 | 
					        vcard = self.xmpp['xep_0054'].get_vcard(jid, cached=True)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,7 +74,7 @@ class XEP_0163(BasePlugin):
 | 
				
			|||||||
                         be a list of such namespaces.
 | 
					                         be a list of such namespaces.
 | 
				
			||||||
            jid       -- Optionally specify the JID.
 | 
					            jid       -- Optionally specify the JID.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if not isinstance(namespace, set) and not isinstance(namespace, list):
 | 
					        if not isinstance(namespace, (set, list)):
 | 
				
			||||||
            namespace = [namespace]
 | 
					            namespace = [namespace]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for ns in namespace:
 | 
					        for ns in namespace:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,12 @@ class XEP_0172(BasePlugin):
 | 
				
			|||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        register_stanza_plugin(Message, UserNick)
 | 
					        register_stanza_plugin(Message, UserNick)
 | 
				
			||||||
        register_stanza_plugin(Presence, UserNick)
 | 
					        register_stanza_plugin(Presence, UserNick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=UserNick.namespace)
 | 
				
			||||||
 | 
					        self.xmpp['xep_0163'].remove_interest(UserNick.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0163'].register_pep('user_nick', UserNick)
 | 
					        self.xmpp['xep_0163'].register_pep('user_nick', UserNick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publish_nick(self, nick=None, options=None, ifrom=None, block=True,
 | 
					    def publish_nick(self, nick=None, options=None, ifrom=None, block=True,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,13 @@ class XEP_0184(BasePlugin):
 | 
				
			|||||||
                    StanzaPath('message/request_receipt'),
 | 
					                    StanzaPath('message/request_receipt'),
 | 
				
			||||||
                    self._handle_receipt_request))
 | 
					                    self._handle_receipt_request))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature('urn:xmpp:receipts')
 | 
				
			||||||
 | 
					        self.xmpp.del_filter('out', self._filter_add_receipt_request)
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Message Receipt')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Message Receipt Request')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature('urn:xmpp:receipts')
 | 
					        self.xmpp['xep_0030'].add_feature('urn:xmpp:receipts')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def ack(self, msg):
 | 
					    def ack(self, msg):
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								sleekxmpp/plugins/xep_0191/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								sleekxmpp/plugins/xep_0191/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					    SleekXMPP: The Sleek XMPP Library
 | 
				
			||||||
 | 
					    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
				
			||||||
 | 
					    This file is part of SleekXMPP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the file LICENSE for copying permission.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp.plugins.base import register_plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp.plugins.xep_0191.stanza import Block, Unblock, BlockList
 | 
				
			||||||
 | 
					from sleekxmpp.plugins.xep_0191.blocking import XEP_0191
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					register_plugin(XEP_0191)
 | 
				
			||||||
							
								
								
									
										83
									
								
								sleekxmpp/plugins/xep_0191/blocking.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								sleekxmpp/plugins/xep_0191/blocking.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					    SleekXMPP: The Sleek XMPP Library
 | 
				
			||||||
 | 
					    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
				
			||||||
 | 
					    This file is part of SleekXMPP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the file LICENSE for copying permission.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp import Iq
 | 
				
			||||||
 | 
					from sleekxmpp.plugins import BasePlugin
 | 
				
			||||||
 | 
					from sleekxmpp.xmlstream.handler import Callback
 | 
				
			||||||
 | 
					from sleekxmpp.xmlstream.matcher import StanzaPath
 | 
				
			||||||
 | 
					from sleekxmpp.xmlstream import register_stanza_plugin, JID
 | 
				
			||||||
 | 
					from sleekxmpp.plugins.xep_0191 import stanza, Block, Unblock, BlockList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					log = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class XEP_0191(BasePlugin):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = 'xep_0191'
 | 
				
			||||||
 | 
					    description = 'XEP-0191: Blocking Command'
 | 
				
			||||||
 | 
					    dependencies = set(['xep_0030'])
 | 
				
			||||||
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_init(self):
 | 
				
			||||||
 | 
					        register_stanza_plugin(Iq, BlockList)
 | 
				
			||||||
 | 
					        register_stanza_plugin(Iq, Block)
 | 
				
			||||||
 | 
					        register_stanza_plugin(Iq, Unblock)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.xmpp.register_handler(
 | 
				
			||||||
 | 
					                Callback('Blocked Contact',
 | 
				
			||||||
 | 
					                    StanzaPath('iq@type=set/block'),
 | 
				
			||||||
 | 
					                    self._handle_blocked))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.xmpp.register_handler(
 | 
				
			||||||
 | 
					                Callback('Unblocked Contact',
 | 
				
			||||||
 | 
					                    StanzaPath('iq@type=set/unblock'),
 | 
				
			||||||
 | 
					                    self._handle_unblocked))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Blocked Contact')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Unblocked Contact')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_blocked(self, ifrom=None, block=True, timeout=None, callback=None):
 | 
				
			||||||
 | 
					        iq = self.xmpp.Iq()
 | 
				
			||||||
 | 
					        iq['type'] = 'get'
 | 
				
			||||||
 | 
					        iq['from'] = 'ifrom'
 | 
				
			||||||
 | 
					        iq.enable('blocklist')
 | 
				
			||||||
 | 
					        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def block(self, jids, ifrom=None, block=True, timeout=None, callback=None):
 | 
				
			||||||
 | 
					        iq = self.xmpp.Iq()
 | 
				
			||||||
 | 
					        iq['type'] = 'set'
 | 
				
			||||||
 | 
					        iq['from'] = ifrom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not isinstance(jids, (set, list)):
 | 
				
			||||||
 | 
					            jids = [jids]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        iq['block']['items'] = jids
 | 
				
			||||||
 | 
					        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def unblock(self, jids=None, ifrom=None, block=True, timeout=None, callback=None):
 | 
				
			||||||
 | 
					        iq = self.xmpp.Iq()
 | 
				
			||||||
 | 
					        iq['type'] = 'set'
 | 
				
			||||||
 | 
					        iq['from'] = ifrom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if jids is None:
 | 
				
			||||||
 | 
					            jids = []
 | 
				
			||||||
 | 
					        if not isinstance(jids, (set, list)):
 | 
				
			||||||
 | 
					            jids = [jids]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        iq['unblock']['items'] = jids
 | 
				
			||||||
 | 
					        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _handle_blocked(self, iq):
 | 
				
			||||||
 | 
					        self.xmpp.event('blocked', iq)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _handle_unblocked(self, iq):
 | 
				
			||||||
 | 
					        self.xmpp.event('unblocked', iq)
 | 
				
			||||||
							
								
								
									
										50
									
								
								sleekxmpp/plugins/xep_0191/stanza.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								sleekxmpp/plugins/xep_0191/stanza.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					    SleekXMPP: The Sleek XMPP Library
 | 
				
			||||||
 | 
					    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
				
			||||||
 | 
					    This file is part of SleekXMPP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the file LICENSE for copying permission.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp.xmlstream import ET, ElementBase, JID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BlockList(ElementBase):
 | 
				
			||||||
 | 
					    name = 'blocklist'
 | 
				
			||||||
 | 
					    namespace = 'urn:xmpp:blocking'
 | 
				
			||||||
 | 
					    plugin_attrib = 'blocklist'
 | 
				
			||||||
 | 
					    interfaces = set(['items'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_items(self):
 | 
				
			||||||
 | 
					        result = set()
 | 
				
			||||||
 | 
					        items = self.xml.findall('{%s}item' % self.namespace)
 | 
				
			||||||
 | 
					        if items is not None:
 | 
				
			||||||
 | 
					            for item in items:
 | 
				
			||||||
 | 
					                jid = JID(item.attrib.get('jid', ''))
 | 
				
			||||||
 | 
					                if jid:
 | 
				
			||||||
 | 
					                    result.add(jid)
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_items(self, values):
 | 
				
			||||||
 | 
					        self.del_items()
 | 
				
			||||||
 | 
					        for jid in values:
 | 
				
			||||||
 | 
					            if jid:
 | 
				
			||||||
 | 
					                item = ET.Element('{%s}item' % self.namespace)
 | 
				
			||||||
 | 
					                item.attrib['jid'] = JID(jid).full
 | 
				
			||||||
 | 
					                self.xml.append(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def del_items(self):
 | 
				
			||||||
 | 
					        items = self.xml.findall('{%s}item' % self.namespace)
 | 
				
			||||||
 | 
					        if items is not None:
 | 
				
			||||||
 | 
					            for item in items:
 | 
				
			||||||
 | 
					                self.xml.remove(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Block(BlockList):
 | 
				
			||||||
 | 
					    name = 'block'
 | 
				
			||||||
 | 
					    plugin_attrib = 'block'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Unblock(BlockList):
 | 
				
			||||||
 | 
					    name = 'unblock'
 | 
				
			||||||
 | 
					    plugin_attrib = 'unblock'
 | 
				
			||||||
@@ -133,6 +133,27 @@ class XEP_0198(BasePlugin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.xmpp.add_event_handler('session_end', self.session_end)
 | 
					        self.xmpp.add_event_handler('session_end', self.session_end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        if self.xmpp.is_component:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.xmpp.unregister_feature('sm', self.config.get('order', 10100))
 | 
				
			||||||
 | 
					        self.xmpp.unregister_feature('sm', self.config.get('resume_order', 9000))
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('session_end', self.session_end)
 | 
				
			||||||
 | 
					        self.xmpp.del_filter('in', self._handle_incoming)
 | 
				
			||||||
 | 
					        self.xmpp.del_filter('out_sync', self._handle_outgoing)
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Stream Management Enabled')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Stream Management Resumed')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Stream Management Failed')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Stream Management Ack')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Stream Management Request Ack')
 | 
				
			||||||
 | 
					        self.xmpp.remove_stanza(stanza.Enable)
 | 
				
			||||||
 | 
					        self.xmpp.remove_stanza(stanza.Enabled)
 | 
				
			||||||
 | 
					        self.xmpp.remove_stanza(stanza.Resume)
 | 
				
			||||||
 | 
					        self.xmpp.remove_stanza(stanza.Resumed)
 | 
				
			||||||
 | 
					        self.xmpp.remove_stanza(stanza.Ack)
 | 
				
			||||||
 | 
					        self.xmpp.remove_stanza(stanza.RequestAck)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def session_end(self, event):
 | 
					    def session_end(self, event):
 | 
				
			||||||
        """Reset stream management state."""
 | 
					        """Reset stream management state."""
 | 
				
			||||||
        self.enabled.clear()
 | 
					        self.enabled.clear()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,6 +74,16 @@ class XEP_0199(BasePlugin):
 | 
				
			|||||||
            self.xmpp.add_event_handler('session_end',
 | 
					            self.xmpp.add_event_handler('session_end',
 | 
				
			||||||
                                        self._handle_session_end)
 | 
					                                        self._handle_session_end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=Ping.namespace)
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Ping')
 | 
				
			||||||
 | 
					        if self.keepalive:
 | 
				
			||||||
 | 
					            self.xmpp.del_event_handler('session_start',
 | 
				
			||||||
 | 
					                                        self._handle_keepalive)
 | 
				
			||||||
 | 
					            self.xmpp.del_event_handler('session_end',
 | 
				
			||||||
 | 
					                                        self._handle_session_end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(Ping.namespace)
 | 
					        self.xmpp['xep_0030'].add_feature(Ping.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_keepalive(self, event):
 | 
					    def _handle_keepalive(self, event):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,11 @@ class XEP_0202(BasePlugin):
 | 
				
			|||||||
                 self._handle_time_request))
 | 
					                 self._handle_time_request))
 | 
				
			||||||
        register_stanza_plugin(Iq, stanza.EntityTime)
 | 
					        register_stanza_plugin(Iq, stanza.EntityTime)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature='urn:xmpp:time')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Entity Time')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature('urn:xmpp:time')
 | 
					        self.xmpp['xep_0030'].add_feature('urn:xmpp:time')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_time_request(self, iq):
 | 
					    def _handle_time_request(self, iq):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,11 @@ class XEP_0224(BasePlugin):
 | 
				
			|||||||
                    StanzaPath('message/attention'),
 | 
					                    StanzaPath('message/attention'),
 | 
				
			||||||
                    self._handle_attention))
 | 
					                    self._handle_attention))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=stanza.Attention.namespace)
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Attention')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(stanza.Attention.namespace)
 | 
					        self.xmpp['xep_0030'].add_feature(stanza.Attention.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def request_attention(self, to, mfrom=None, mbody=''):
 | 
					    def request_attention(self, to, mfrom=None, mbody=''):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,8 +35,6 @@ class XEP_0231(BasePlugin):
 | 
				
			|||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        self._cids = {}
 | 
					        self._cids = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature('urn:xmpp:bob')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        register_stanza_plugin(Iq, BitsOfBinary)
 | 
					        register_stanza_plugin(Iq, BitsOfBinary)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xmpp.register_handler(
 | 
					        self.xmpp.register_handler(
 | 
				
			||||||
@@ -58,6 +56,15 @@ class XEP_0231(BasePlugin):
 | 
				
			|||||||
        self.api.register(self._set_bob, 'set_bob', default=True)
 | 
					        self.api.register(self._set_bob, 'set_bob', default=True)
 | 
				
			||||||
        self.api.register(self._del_bob, 'del_bob', default=True)
 | 
					        self.api.register(self._del_bob, 'del_bob', default=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature='urn:xmpp:bob')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Bits of Binary - Iq')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Bits of Binary - Message')
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Bits of Binary - Presence')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].add_feature('urn:xmpp:bob')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_bob(self, data, mtype, cid=None, max_age=None):
 | 
					    def set_bob(self, data, mtype, cid=None, max_age=None):
 | 
				
			||||||
        if cid is None:
 | 
					        if cid is None:
 | 
				
			||||||
            cid = 'sha1+%s@bob.xmpp.org' % hashlib.sha1(data).hexdigest()
 | 
					            cid = 'sha1+%s@bob.xmpp.org' % hashlib.sha1(data).hexdigest()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,11 @@ class XEP_0249(BasePlugin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        register_stanza_plugin(Message, Invite)
 | 
					        register_stanza_plugin(Message, Invite)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=Invite.namespace)
 | 
				
			||||||
 | 
					        self.xmpp.remove_handler('Direct MUC Invitations')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(Invite.namespace)
 | 
					        self.xmpp['xep_0030'].add_feature(Invite.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _handle_invite(self, msg):
 | 
					    def _handle_invite(self, msg):
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										72
									
								
								sleekxmpp/plugins/xep_0256.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								sleekxmpp/plugins/xep_0256.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					    SleekXMPP: The Sleek XMPP Library
 | 
				
			||||||
 | 
					    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
				
			||||||
 | 
					    This file is part of SleekXMPP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the file LICENSE for copying permission.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp import Presence
 | 
				
			||||||
 | 
					from sleekxmpp.exceptions import XMPPError
 | 
				
			||||||
 | 
					from sleekxmpp.plugins import BasePlugin, register_plugin
 | 
				
			||||||
 | 
					from sleekxmpp.xmlstream import register_stanza_plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp.plugins.xep_0012 import stanza, LastActivity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					log = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class XEP_0256(BasePlugin):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = 'xep_0256'
 | 
				
			||||||
 | 
					    description = 'XEP-0256: Last Activity in Presence'
 | 
				
			||||||
 | 
					    dependencies = set(['xep_0012'])
 | 
				
			||||||
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_init(self):
 | 
				
			||||||
 | 
					        self.auto_last_activity = self.config.get('auto_last_activity', False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        register_stanza_plugin(Presence, LastActivity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.xmpp.add_filter('out', self._initial_presence_activity)
 | 
				
			||||||
 | 
					        self.xmpp.add_event_handler('connected', self._reset_presence_activity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self._initial_presence = set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp.del_filter('out', self._initial_presence_activity)
 | 
				
			||||||
 | 
					        self.xmpp.del_event_handler('connected', self._reset_presence_activity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _reset_presence_activity(self, e):
 | 
				
			||||||
 | 
					        self._initial_presence = set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _initial_presence_activity(self, stanza):
 | 
				
			||||||
 | 
					        if isinstance(stanza, Presence):
 | 
				
			||||||
 | 
					            use_last_activity = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if self.auto_last_activity and  stanza['show'] in ('xa', 'away'):
 | 
				
			||||||
 | 
					                use_last_activity = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if stanza['from'] not in self._initial_presence:
 | 
				
			||||||
 | 
					                self._initial_presence.add(stanza['from'])
 | 
				
			||||||
 | 
					                use_last_activity = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if use_last_activity:
 | 
				
			||||||
 | 
					                plugin = self.xmpp['xep_0012']
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    result = plugin.api['get_last_activity'](stanza['from'],
 | 
				
			||||||
 | 
					                                                             None,
 | 
				
			||||||
 | 
					                                                             stanza['to'])
 | 
				
			||||||
 | 
					                    seconds = result['last_activity']['seconds']
 | 
				
			||||||
 | 
					                except XMPPError:
 | 
				
			||||||
 | 
					                    seconds = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if seconds is not None:
 | 
				
			||||||
 | 
					                    stanza['last_activity']['seconds'] = seconds
 | 
				
			||||||
 | 
					        return stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					register_plugin(XEP_0256)
 | 
				
			||||||
@@ -25,11 +25,15 @@ class XEP_0258(BasePlugin):
 | 
				
			|||||||
    stanza = stanza
 | 
					    stanza = stanza
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def plugin_init(self):
 | 
					    def plugin_init(self):
 | 
				
			||||||
        self.xmpp['xep_0030'].add_feature(SecurityLabel.namespace)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        register_stanza_plugin(Message, SecurityLabel)
 | 
					        register_stanza_plugin(Message, SecurityLabel)
 | 
				
			||||||
        register_stanza_plugin(Iq, Catalog)
 | 
					        register_stanza_plugin(Iq, Catalog)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def plugin_end(self):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].del_feature(feature=SecurityLabel.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_bind(self, jid):
 | 
				
			||||||
 | 
					        self.xmpp['xep_0030'].add_feature(SecurityLabel.namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_catalog(self, jid, ifrom=None, block=True,
 | 
					    def get_catalog(self, jid, ifrom=None, block=True,
 | 
				
			||||||
                          callback=None, timeout=None):
 | 
					                          callback=None, timeout=None):
 | 
				
			||||||
        iq = self.xmpp.Iq()
 | 
					        iq = self.xmpp.Iq()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								sleekxmpp/plugins/xep_0270.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								sleekxmpp/plugins/xep_0270.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					    SleekXMPP: The Sleek XMPP Library
 | 
				
			||||||
 | 
					    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
				
			||||||
 | 
					    This file is part of SleekXMPP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the file LICENSE for copying permission.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp.plugins import BasePlugin, register_plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class XEP_0270(BasePlugin):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = 'xep_0270'
 | 
				
			||||||
 | 
					    description = 'XEP-0270: XMPP Compliance Suites 2010'
 | 
				
			||||||
 | 
					    dependencies = set(['xep_0030', 'xep_0115', 'xep_0054',
 | 
				
			||||||
 | 
					                        'xep_0163', 'xep_0045', 'xep_0085'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					register_plugin(XEP_0270)
 | 
				
			||||||
							
								
								
									
										21
									
								
								sleekxmpp/plugins/xep_0302.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								sleekxmpp/plugins/xep_0302.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					    SleekXMPP: The Sleek XMPP Library
 | 
				
			||||||
 | 
					    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
				
			||||||
 | 
					    This file is part of SleekXMPP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the file LICENSE for copying permission.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp.plugins import BasePlugin, register_plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class XEP_0302(BasePlugin):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = 'xep_0302'
 | 
				
			||||||
 | 
					    description = 'XEP-0302: XMPP Compliance Suites 2012'
 | 
				
			||||||
 | 
					    dependencies = set(['xep_0030', 'xep_0115', 'xep_0054',
 | 
				
			||||||
 | 
					                        'xep_0163', 'xep_0045', 'xep_0085',
 | 
				
			||||||
 | 
					                        'xep_0184', 'xep_0198'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					register_plugin(XEP_0302)
 | 
				
			||||||
@@ -94,10 +94,12 @@ class Roster(object):
 | 
				
			|||||||
        Arguments:
 | 
					        Arguments:
 | 
				
			||||||
            key -- Return the roster for this JID.
 | 
					            key -- Return the roster for this JID.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if isinstance(key, JID):
 | 
					 | 
				
			||||||
            key = key.bare
 | 
					 | 
				
			||||||
        if key is None:
 | 
					        if key is None:
 | 
				
			||||||
            key = self.xmpp.boundjid.bare
 | 
					            key = self.xmpp.boundjid
 | 
				
			||||||
 | 
					        if not isinstance(key, JID):
 | 
				
			||||||
 | 
					            key = JID(key)
 | 
				
			||||||
 | 
					        key = key.bare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if key not in self._rosters:
 | 
					        if key not in self._rosters:
 | 
				
			||||||
            self.add(key)
 | 
					            self.add(key)
 | 
				
			||||||
            self._rosters[key].auto_authorize = self.auto_authorize
 | 
					            self._rosters[key].auto_authorize = self.auto_authorize
 | 
				
			||||||
@@ -119,8 +121,10 @@ class Roster(object):
 | 
				
			|||||||
        Arguments:
 | 
					        Arguments:
 | 
				
			||||||
            node -- The JID for the new roster node.
 | 
					            node -- The JID for the new roster node.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if isinstance(node, JID):
 | 
					        if not isinstance(node, JID):
 | 
				
			||||||
            node = node.bare
 | 
					            node = JID(node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        node = node.bare
 | 
				
			||||||
        if node not in self._rosters:
 | 
					        if node not in self._rosters:
 | 
				
			||||||
            self._rosters[node] = RosterNode(self.xmpp, node, self.db)
 | 
					            self._rosters[node] = RosterNode(self.xmpp, node, self.db)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,8 +89,11 @@ class RosterNode(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        A new item entry will be created if one does not already exist.
 | 
					        A new item entry will be created if one does not already exist.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if isinstance(key, JID):
 | 
					        if key is None:
 | 
				
			||||||
            key = key.bare
 | 
					            key = JID('')
 | 
				
			||||||
 | 
					        if not isinstance(key, JID):
 | 
				
			||||||
 | 
					            key = JID(key)
 | 
				
			||||||
 | 
					        key = key.bare
 | 
				
			||||||
        if key not in self._jids:
 | 
					        if key not in self._jids:
 | 
				
			||||||
            self.add(key, save=True)
 | 
					            self.add(key, save=True)
 | 
				
			||||||
        return self._jids[key]
 | 
					        return self._jids[key]
 | 
				
			||||||
@@ -101,8 +104,11 @@ class RosterNode(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        To remove an item from the server, use the remove() method.
 | 
					        To remove an item from the server, use the remove() method.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if isinstance(key, JID):
 | 
					        if key is None:
 | 
				
			||||||
            key = key.bare
 | 
					            key = JID('')
 | 
				
			||||||
 | 
					        if not isinstance(key, JID):
 | 
				
			||||||
 | 
					            key = JID(key)
 | 
				
			||||||
 | 
					        key = key.bare
 | 
				
			||||||
        if key in self._jids:
 | 
					        if key in self._jids:
 | 
				
			||||||
            del self._jids[key]
 | 
					            del self._jids[key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from sleekxmpp.stanza.rootstanza import RootStanza
 | 
					from sleekxmpp.stanza.rootstanza import RootStanza
 | 
				
			||||||
from sleekxmpp.xmlstream import StanzaBase
 | 
					from sleekxmpp.xmlstream import StanzaBase, ET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Message(RootStanza):
 | 
					class Message(RootStanza):
 | 
				
			||||||
@@ -54,13 +54,14 @@ class Message(RootStanza):
 | 
				
			|||||||
        del_mucnick -- Dummy method to prevent deletion.
 | 
					        del_mucnick -- Dummy method to prevent deletion.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    namespace = 'jabber:client'
 | 
					 | 
				
			||||||
    name = 'message'
 | 
					    name = 'message'
 | 
				
			||||||
    interfaces = set(('type', 'to', 'from', 'id', 'body', 'subject',
 | 
					    namespace = 'jabber:client'
 | 
				
			||||||
                      'mucroom', 'mucnick'))
 | 
					 | 
				
			||||||
    sub_interfaces = set(('body', 'subject'))
 | 
					 | 
				
			||||||
    plugin_attrib = name
 | 
					    plugin_attrib = name
 | 
				
			||||||
    types = set((None, 'normal', 'chat', 'headline', 'error', 'groupchat'))
 | 
					    interfaces = set(['type', 'to', 'from', 'id', 'body', 'subject',
 | 
				
			||||||
 | 
					                      'thread', 'parent_thread', 'mucroom', 'mucnick'])
 | 
				
			||||||
 | 
					    sub_interfaces = set(['body', 'subject', 'thread'])
 | 
				
			||||||
 | 
					    lang_interfaces = sub_interfaces
 | 
				
			||||||
 | 
					    types = set(['normal', 'chat', 'headline', 'error', 'groupchat'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_type(self):
 | 
					    def get_type(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -72,6 +73,31 @@ class Message(RootStanza):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        return self._get_attr('type', 'normal')
 | 
					        return self._get_attr('type', 'normal')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_parent_thread(self):
 | 
				
			||||||
 | 
					        """Return the message thread's parent thread."""
 | 
				
			||||||
 | 
					        thread = self.xml.find('{%s}thread' % self.namespace)
 | 
				
			||||||
 | 
					        if thread is not None:
 | 
				
			||||||
 | 
					            return thread.attrib.get('parent', '')
 | 
				
			||||||
 | 
					        return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_parent_thread(self, value):
 | 
				
			||||||
 | 
					        """Add or change the message thread's parent thread."""
 | 
				
			||||||
 | 
					        thread = self.xml.find('{%s}thread' % self.namespace)
 | 
				
			||||||
 | 
					        if value:
 | 
				
			||||||
 | 
					            if thread is None:
 | 
				
			||||||
 | 
					                thread = ET.Element('{%s}thread' % self.namespace)
 | 
				
			||||||
 | 
					                self.xml.append(thread)
 | 
				
			||||||
 | 
					            thread.attrib['parent'] = value
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            if thread is not None and 'parent' in thread.attrib:
 | 
				
			||||||
 | 
					                del thread.attrib['parent']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def del_parent_thread(self):
 | 
				
			||||||
 | 
					        """Delete the message thread's parent reference."""
 | 
				
			||||||
 | 
					        thread = self.xml.find('{%s}thread' % self.namespace)
 | 
				
			||||||
 | 
					        if thread is not None and 'parent' in thread.attrib:
 | 
				
			||||||
 | 
					            del thread.attrib['parent']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def chat(self):
 | 
					    def chat(self):
 | 
				
			||||||
        """Set the message type to 'chat'."""
 | 
					        """Set the message type to 'chat'."""
 | 
				
			||||||
        self['type'] = 'chat'
 | 
					        self['type'] = 'chat'
 | 
				
			||||||
@@ -96,10 +122,16 @@ class Message(RootStanza):
 | 
				
			|||||||
            clear -- Indicates if existing content should be removed
 | 
					            clear -- Indicates if existing content should be removed
 | 
				
			||||||
                     before replying. Defaults to True.
 | 
					                     before replying. Defaults to True.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					        thread = self['thread']
 | 
				
			||||||
 | 
					        parent = self['parent_thread']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        StanzaBase.reply(self, clear)
 | 
					        StanzaBase.reply(self, clear)
 | 
				
			||||||
        if self['type'] == 'groupchat':
 | 
					        if self['type'] == 'groupchat':
 | 
				
			||||||
            self['to'] = self['to'].bare
 | 
					            self['to'] = self['to'].bare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self['thread'] = thread
 | 
				
			||||||
 | 
					        self['parent_thread'] = parent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        del self['id']
 | 
					        del self['id']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if body is not None:
 | 
					        if body is not None:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,16 +60,17 @@ class Presence(RootStanza):
 | 
				
			|||||||
        set_priority -- Set the value of the <priority> element.
 | 
					        set_priority -- Set the value of the <priority> element.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    namespace = 'jabber:client'
 | 
					 | 
				
			||||||
    name = 'presence'
 | 
					    name = 'presence'
 | 
				
			||||||
    interfaces = set(('type', 'to', 'from', 'id', 'show',
 | 
					    namespace = 'jabber:client'
 | 
				
			||||||
                      'status', 'priority'))
 | 
					 | 
				
			||||||
    sub_interfaces = set(('show', 'status', 'priority'))
 | 
					 | 
				
			||||||
    plugin_attrib = name
 | 
					    plugin_attrib = name
 | 
				
			||||||
 | 
					    interfaces = set(['type', 'to', 'from', 'id', 'show',
 | 
				
			||||||
 | 
					                      'status', 'priority'])
 | 
				
			||||||
 | 
					    sub_interfaces = set(['show', 'status', 'priority'])
 | 
				
			||||||
 | 
					    lang_interfaces = set(['status'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    types = set(('available', 'unavailable', 'error', 'probe', 'subscribe',
 | 
					    types = set(['available', 'unavailable', 'error', 'probe', 'subscribe',
 | 
				
			||||||
                 'subscribed', 'unsubscribe', 'unsubscribed'))
 | 
					                 'subscribed', 'unsubscribe', 'unsubscribed'])
 | 
				
			||||||
    showtypes = set(('dnd', 'chat', 'xa', 'away'))
 | 
					    showtypes = set(['dnd', 'chat', 'xa', 'away'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def exception(self, e):
 | 
					    def exception(self, e):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								sleekxmpp/thirdparty/suelta/util.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								sleekxmpp/thirdparty/suelta/util.py
									
									
									
									
										vendored
									
									
								
							@@ -15,6 +15,9 @@ def bytes(text):
 | 
				
			|||||||
    :param text: Unicode text to convert to bytes
 | 
					    :param text: Unicode text to convert to bytes
 | 
				
			||||||
    :rtype: bytes (Python3), str (Python2.6+)
 | 
					    :rtype: bytes (Python3), str (Python2.6+)
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    if text is None:
 | 
				
			||||||
 | 
					        return b''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if sys.version_info < (3, 0):
 | 
					    if sys.version_info < (3, 0):
 | 
				
			||||||
        import __builtin__
 | 
					        import __builtin__
 | 
				
			||||||
        return __builtin__.bytes(text)
 | 
					        return __builtin__.bytes(text)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,5 +9,5 @@
 | 
				
			|||||||
# We don't want to have to import the entire library
 | 
					# We don't want to have to import the entire library
 | 
				
			||||||
# just to get the version info for setup.py
 | 
					# just to get the version info for setup.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = '1.1.7'
 | 
					__version__ = '1.1.9'
 | 
				
			||||||
__version_info__ = (1, 1, 7, '', 0)
 | 
					__version_info__ = (1, 1, 9, '', 0)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,3 +143,6 @@ class JID(object):
 | 
				
			|||||||
    def __hash__(self):
 | 
					    def __hash__(self):
 | 
				
			||||||
        """Hash a JID based on the string version of its full JID."""
 | 
					        """Hash a JID based on the string version of its full JID."""
 | 
				
			||||||
        return hash(self.full)
 | 
					        return hash(self.full)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __copy__(self):
 | 
				
			||||||
 | 
					        return JID(self.jid)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -254,6 +254,7 @@ def get_SRV(host, port, service, proto='tcp', resolver=None):
 | 
				
			|||||||
             by SRV priorities and weights.
 | 
					             by SRV priorities and weights.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    if resolver is None:
 | 
					    if resolver is None:
 | 
				
			||||||
 | 
					        log.warning("DNS: dnspython not found. Can not use SRV lookup.")
 | 
				
			||||||
        return [(host, port)]
 | 
					        return [(host, port)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    log.debug("DNS: Querying SRV records for %s" % host)
 | 
					    log.debug("DNS: Querying SRV records for %s" % host)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,7 +172,8 @@ class Scheduler(object):
 | 
				
			|||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    updated = True
 | 
					                    updated = True
 | 
				
			||||||
                    self.schedule_lock.acquire()
 | 
					                    self.schedule_lock.acquire()
 | 
				
			||||||
                    self.schedule.append(newtask)
 | 
					                    if newtask is not None:
 | 
				
			||||||
 | 
					                        self.schedule.append(newtask)
 | 
				
			||||||
                finally:
 | 
					                finally:
 | 
				
			||||||
                    if updated:
 | 
					                    if updated:
 | 
				
			||||||
                        self.schedule = sorted(self.schedule,
 | 
					                        self.schedule = sorted(self.schedule,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -421,12 +421,6 @@ class ElementBase(object):
 | 
				
			|||||||
        #: ``'{namespace}elementname'``.
 | 
					        #: ``'{namespace}elementname'``.
 | 
				
			||||||
        self.tag = self.tag_name()
 | 
					        self.tag = self.tag_name()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if 'lang' not in self.interfaces:
 | 
					 | 
				
			||||||
            if isinstance(self.interfaces, tuple):
 | 
					 | 
				
			||||||
                self.interfaces += ('lang',)
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                self.interfaces.add('lang')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #: A :class:`weakref.weakref` to the parent stanza, if there is one.
 | 
					        #: A :class:`weakref.weakref` to the parent stanza, if there is one.
 | 
				
			||||||
        #: If not, then :attr:`parent` is ``None``.
 | 
					        #: If not, then :attr:`parent` is ``None``.
 | 
				
			||||||
        self.parent = None
 | 
					        self.parent = None
 | 
				
			||||||
@@ -574,6 +568,7 @@ class ElementBase(object):
 | 
				
			|||||||
        .. versionadded:: 1.0-Beta1
 | 
					        .. versionadded:: 1.0-Beta1
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        values = {}
 | 
					        values = {}
 | 
				
			||||||
 | 
					        values['lang'] = self['lang']
 | 
				
			||||||
        for interface in self.interfaces:
 | 
					        for interface in self.interfaces:
 | 
				
			||||||
            values[interface] = self[interface]
 | 
					            values[interface] = self[interface]
 | 
				
			||||||
            if interface in self.lang_interfaces:
 | 
					            if interface in self.lang_interfaces:
 | 
				
			||||||
@@ -629,6 +624,8 @@ class ElementBase(object):
 | 
				
			|||||||
                                sub.values = subdict
 | 
					                                sub.values = subdict
 | 
				
			||||||
                                self.iterables.append(sub)
 | 
					                                self.iterables.append(sub)
 | 
				
			||||||
                                break
 | 
					                                break
 | 
				
			||||||
 | 
					            elif interface == 'lang':
 | 
				
			||||||
 | 
					                self[interface] = value
 | 
				
			||||||
            elif interface in self.interfaces:
 | 
					            elif interface in self.interfaces:
 | 
				
			||||||
                self[full_interface] = value
 | 
					                self[full_interface] = value
 | 
				
			||||||
            elif interface in self.plugin_attrib_map:
 | 
					            elif interface in self.plugin_attrib_map:
 | 
				
			||||||
@@ -678,7 +675,7 @@ class ElementBase(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if attrib == 'substanzas':
 | 
					        if attrib == 'substanzas':
 | 
				
			||||||
            return self.iterables
 | 
					            return self.iterables
 | 
				
			||||||
        elif attrib in self.interfaces:
 | 
					        elif attrib in self.interfaces or attrib == 'lang':
 | 
				
			||||||
            get_method = "get_%s" % attrib.lower()
 | 
					            get_method = "get_%s" % attrib.lower()
 | 
				
			||||||
            get_method2 = "get%s" % attrib.title()
 | 
					            get_method2 = "get%s" % attrib.title()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -752,7 +749,7 @@ class ElementBase(object):
 | 
				
			|||||||
        if lang and attrib in self.lang_interfaces:
 | 
					        if lang and attrib in self.lang_interfaces:
 | 
				
			||||||
            kwargs['lang'] = lang
 | 
					            kwargs['lang'] = lang
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if attrib in self.interfaces:
 | 
					        if attrib in self.interfaces or attrib == 'lang':
 | 
				
			||||||
            if value is not None:
 | 
					            if value is not None:
 | 
				
			||||||
                set_method = "set_%s" % attrib.lower()
 | 
					                set_method = "set_%s" % attrib.lower()
 | 
				
			||||||
                set_method2 = "set%s" % attrib.title()
 | 
					                set_method2 = "set%s" % attrib.title()
 | 
				
			||||||
@@ -838,7 +835,7 @@ class ElementBase(object):
 | 
				
			|||||||
        if lang and attrib in self.lang_interfaces:
 | 
					        if lang and attrib in self.lang_interfaces:
 | 
				
			||||||
            kwargs['lang'] = lang
 | 
					            kwargs['lang'] = lang
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if attrib in self.interfaces:
 | 
					        if attrib in self.interfaces or attrib == 'lang':
 | 
				
			||||||
            del_method = "del_%s" % attrib.lower()
 | 
					            del_method = "del_%s" % attrib.lower()
 | 
				
			||||||
            del_method2 = "del%s" % attrib.title()
 | 
					            del_method2 = "del%s" % attrib.title()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -973,10 +970,6 @@ class ElementBase(object):
 | 
				
			|||||||
        :param keep: Indicates if the element should be kept if its text is
 | 
					        :param keep: Indicates if the element should be kept if its text is
 | 
				
			||||||
                     removed. Defaults to False.
 | 
					                     removed. Defaults to False.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        path = self._fix_ns(name, split=True)
 | 
					 | 
				
			||||||
        element = self.xml.find(name)
 | 
					 | 
				
			||||||
        parent = self.xml
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        default_lang = self.get_lang()
 | 
					        default_lang = self.get_lang()
 | 
				
			||||||
        if lang is None:
 | 
					        if lang is None:
 | 
				
			||||||
            lang = default_lang
 | 
					            lang = default_lang
 | 
				
			||||||
@@ -984,32 +977,51 @@ class ElementBase(object):
 | 
				
			|||||||
        if not text and not keep:
 | 
					        if not text and not keep:
 | 
				
			||||||
            return self._del_sub(name, lang=lang)
 | 
					            return self._del_sub(name, lang=lang)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if element is None:
 | 
					        path = self._fix_ns(name, split=True)
 | 
				
			||||||
            # We need to add the element. If the provided name was
 | 
					        name = path[-1]
 | 
				
			||||||
            # an XPath expression, some of the intermediate elements
 | 
					        parent = self.xml
 | 
				
			||||||
            # may already exist. If so, we want to use those instead
 | 
					 | 
				
			||||||
            # of generating new elements.
 | 
					 | 
				
			||||||
            last_xml = self.xml
 | 
					 | 
				
			||||||
            walked = []
 | 
					 | 
				
			||||||
            for ename in path:
 | 
					 | 
				
			||||||
                walked.append(ename)
 | 
					 | 
				
			||||||
                element = self.xml.find("/".join(walked))
 | 
					 | 
				
			||||||
                if element is None:
 | 
					 | 
				
			||||||
                    element = ET.Element(ename)
 | 
					 | 
				
			||||||
                    if lang:
 | 
					 | 
				
			||||||
                        element.attrib['{%s}lang' % XML_NS] = lang
 | 
					 | 
				
			||||||
                    last_xml.append(element)
 | 
					 | 
				
			||||||
                parent = last_xml
 | 
					 | 
				
			||||||
                last_xml = element
 | 
					 | 
				
			||||||
            element = last_xml
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if lang:
 | 
					        # The first goal is to find the parent of the subelement, or, if
 | 
				
			||||||
            if element.attrib.get('{%s}lang' % XML_NS, default_lang) != lang:
 | 
					        # we can't find that, the closest grandparent element.
 | 
				
			||||||
                element = ET.Element(ename)
 | 
					        missing_path = []
 | 
				
			||||||
                element.attrib['{%s}lang' % XML_NS] = lang
 | 
					        search_order = path[:-1]
 | 
				
			||||||
                parent.append(element)
 | 
					        while search_order:
 | 
				
			||||||
 | 
					            parent = self.xml.find('/'.join(search_order))
 | 
				
			||||||
 | 
					            ename = search_order.pop()
 | 
				
			||||||
 | 
					            if parent is not None:
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                missing_path.append(ename)
 | 
				
			||||||
 | 
					        missing_path.reverse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Find all existing elements that match the desired
 | 
				
			||||||
 | 
					        # element path (there may be multiples due to different
 | 
				
			||||||
 | 
					        # languages values).
 | 
				
			||||||
 | 
					        if parent is not None:
 | 
				
			||||||
 | 
					            elements = self.xml.findall('/'.join(path))
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            parent = self.xml
 | 
				
			||||||
 | 
					            elements = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Insert the remaining grandparent elements that don't exist yet.
 | 
				
			||||||
 | 
					        for ename in missing_path:
 | 
				
			||||||
 | 
					            element = ET.Element(ename)
 | 
				
			||||||
 | 
					            parent.append(element)
 | 
				
			||||||
 | 
					            parent = element
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Re-use an existing element with the proper language, if one exists.
 | 
				
			||||||
 | 
					        for element in elements:
 | 
				
			||||||
 | 
					            elang = element.attrib.get('{%s}lang' % XML_NS, default_lang)
 | 
				
			||||||
 | 
					            if not lang and elang == default_lang or lang and lang == elang:
 | 
				
			||||||
 | 
					                element.text = text
 | 
				
			||||||
 | 
					                return element
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # No useable element exists, so create a new one.
 | 
				
			||||||
 | 
					        element = ET.Element(name)
 | 
				
			||||||
        element.text = text
 | 
					        element.text = text
 | 
				
			||||||
 | 
					        if lang and lang != default_lang:
 | 
				
			||||||
 | 
					            element.attrib['{%s}lang' % XML_NS] = lang
 | 
				
			||||||
 | 
					        parent.append(element)
 | 
				
			||||||
        return element
 | 
					        return element
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _set_all_sub_text(self, name, values, keep=False, lang=None):
 | 
					    def _set_all_sub_text(self, name, values, keep=False, lang=None):
 | 
				
			||||||
@@ -1184,6 +1196,7 @@ class ElementBase(object):
 | 
				
			|||||||
        out = []
 | 
					        out = []
 | 
				
			||||||
        out += [x for x in self.interfaces]
 | 
					        out += [x for x in self.interfaces]
 | 
				
			||||||
        out += [x for x in self.loaded_plugins]
 | 
					        out += [x for x in self.loaded_plugins]
 | 
				
			||||||
 | 
					        out.append('lang')
 | 
				
			||||||
        if self.iterables:
 | 
					        if self.iterables:
 | 
				
			||||||
            out.append('substanzas')
 | 
					            out.append('substanzas')
 | 
				
			||||||
        return out
 | 
					        return out
 | 
				
			||||||
@@ -1263,7 +1276,7 @@ class ElementBase(object):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        return "{%s}%s" % (cls.namespace, cls.name)
 | 
					        return "{%s}%s" % (cls.namespace, cls.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_lang(self):
 | 
					    def get_lang(self, lang=None):
 | 
				
			||||||
        result = self.xml.attrib.get('{%s}lang' % XML_NS, '')
 | 
					        result = self.xml.attrib.get('{%s}lang' % XML_NS, '')
 | 
				
			||||||
        if not result and self.parent and self.parent():
 | 
					        if not result and self.parent and self.parent():
 | 
				
			||||||
            return self.parent()['lang']
 | 
					            return self.parent()['lang']
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -537,8 +537,8 @@ class XMLStream(object):
 | 
				
			|||||||
                    try:
 | 
					                    try:
 | 
				
			||||||
                        cert.verify(self._expected_server_name, self._der_cert)
 | 
					                        cert.verify(self._expected_server_name, self._der_cert)
 | 
				
			||||||
                    except cert.CertificateError as err:
 | 
					                    except cert.CertificateError as err:
 | 
				
			||||||
                        log.error(err.message)
 | 
					 | 
				
			||||||
                        if not self.event_handled('ssl_invalid_cert'):
 | 
					                        if not self.event_handled('ssl_invalid_cert'):
 | 
				
			||||||
 | 
					                            log.error(err.message)
 | 
				
			||||||
                            self.disconnect(send_close=False)
 | 
					                            self.disconnect(send_close=False)
 | 
				
			||||||
                        else:
 | 
					                        else:
 | 
				
			||||||
                            self.event('ssl_invalid_cert',
 | 
					                            self.event('ssl_invalid_cert',
 | 
				
			||||||
@@ -828,8 +828,8 @@ class XMLStream(object):
 | 
				
			|||||||
            try:
 | 
					            try:
 | 
				
			||||||
                cert.verify(self._expected_server_name, self._der_cert)
 | 
					                cert.verify(self._expected_server_name, self._der_cert)
 | 
				
			||||||
            except cert.CertificateError as err:
 | 
					            except cert.CertificateError as err:
 | 
				
			||||||
                log.error(err.message)
 | 
					 | 
				
			||||||
                if not self.event_handled('ssl_invalid_cert'):
 | 
					                if not self.event_handled('ssl_invalid_cert'):
 | 
				
			||||||
 | 
					                    log.error(err.message)
 | 
				
			||||||
                    self.disconnect(self.auto_reconnect, send_close=False)
 | 
					                    self.disconnect(self.auto_reconnect, send_close=False)
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    self.event('ssl_invalid_cert', pem_cert, direct=True)
 | 
					                    self.event('ssl_invalid_cert', pem_cert, direct=True)
 | 
				
			||||||
@@ -954,6 +954,10 @@ class XMLStream(object):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.__filters[mode].append(handler)
 | 
					            self.__filters[mode].append(handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def del_filter(self, mode, handler):
 | 
				
			||||||
 | 
					        """Remove an incoming or outgoing filter."""
 | 
				
			||||||
 | 
					        self.__filters[mode].remove(handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_handler(self, mask, pointer, name=None, disposable=False,
 | 
					    def add_handler(self, mask, pointer, name=None, disposable=False,
 | 
				
			||||||
                    threaded=False, filter=False, instream=False):
 | 
					                    threaded=False, filter=False, instream=False):
 | 
				
			||||||
        """A shortcut method for registering a handler using XML masks.
 | 
					        """A shortcut method for registering a handler using XML masks.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
from sleekxmpp.test import *
 | 
					from sleekxmpp.test import *
 | 
				
			||||||
from sleekxmpp.xmlstream.stanzabase import ElementBase
 | 
					from sleekxmpp.xmlstream.stanzabase import ElementBase
 | 
				
			||||||
 | 
					from sleekxmpp.thirdparty import OrderedDict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestElementBase(SleekTest):
 | 
					class TestElementBase(SleekTest):
 | 
				
			||||||
@@ -760,7 +761,7 @@ class TestElementBase(SleekTest):
 | 
				
			|||||||
          <foo xmlns="foo" />
 | 
					          <foo xmlns="foo" />
 | 
				
			||||||
        """)
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertFalse(stanza['bar'], 
 | 
					        self.assertFalse(stanza['bar'],
 | 
				
			||||||
                "Returned True for missing bool interface element.")
 | 
					                "Returned True for missing bool interface element.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        stanza['bar'] = True
 | 
					        stanza['bar'] = True
 | 
				
			||||||
@@ -797,7 +798,7 @@ class TestElementBase(SleekTest):
 | 
				
			|||||||
            namespace = 'baz'
 | 
					            namespace = 'baz'
 | 
				
			||||||
            plugin_attrib = name
 | 
					            plugin_attrib = name
 | 
				
			||||||
            plugin_multi_attrib = 'bazs'
 | 
					            plugin_multi_attrib = 'bazs'
 | 
				
			||||||
           
 | 
					
 | 
				
			||||||
        register_stanza_plugin(TestStanza, TestMultiStanza1, iterable=True)
 | 
					        register_stanza_plugin(TestStanza, TestMultiStanza1, iterable=True)
 | 
				
			||||||
        register_stanza_plugin(TestStanza, TestMultiStanza2, iterable=True)
 | 
					        register_stanza_plugin(TestStanza, TestMultiStanza2, iterable=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -829,9 +830,9 @@ class TestElementBase(SleekTest):
 | 
				
			|||||||
              <baz xmlns="baz" />
 | 
					              <baz xmlns="baz" />
 | 
				
			||||||
            """)
 | 
					            """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(len(bars), 2, 
 | 
					        self.assertEqual(len(bars), 2,
 | 
				
			||||||
                "Wrong number of <bar /> stanzas: %s" % len(bars))
 | 
					                "Wrong number of <bar /> stanzas: %s" % len(bars))
 | 
				
			||||||
        self.assertEqual(len(bazs), 2, 
 | 
					        self.assertEqual(len(bazs), 2,
 | 
				
			||||||
                "Wrong number of <baz /> stanzas: %s" % len(bazs))
 | 
					                "Wrong number of <baz /> stanzas: %s" % len(bazs))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def testSetMultiAttrib(self):
 | 
					    def testSetMultiAttrib(self):
 | 
				
			||||||
@@ -853,7 +854,7 @@ class TestElementBase(SleekTest):
 | 
				
			|||||||
            namespace = 'baz'
 | 
					            namespace = 'baz'
 | 
				
			||||||
            plugin_attrib = name
 | 
					            plugin_attrib = name
 | 
				
			||||||
            plugin_multi_attrib = 'bazs'
 | 
					            plugin_multi_attrib = 'bazs'
 | 
				
			||||||
           
 | 
					
 | 
				
			||||||
        register_stanza_plugin(TestStanza, TestMultiStanza1, iterable=True)
 | 
					        register_stanza_plugin(TestStanza, TestMultiStanza1, iterable=True)
 | 
				
			||||||
        register_stanza_plugin(TestStanza, TestMultiStanza2, iterable=True)
 | 
					        register_stanza_plugin(TestStanza, TestMultiStanza2, iterable=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -906,7 +907,7 @@ class TestElementBase(SleekTest):
 | 
				
			|||||||
            namespace = 'baz'
 | 
					            namespace = 'baz'
 | 
				
			||||||
            plugin_attrib = name
 | 
					            plugin_attrib = name
 | 
				
			||||||
            plugin_multi_attrib = 'bazs'
 | 
					            plugin_multi_attrib = 'bazs'
 | 
				
			||||||
           
 | 
					
 | 
				
			||||||
        register_stanza_plugin(TestStanza, TestMultiStanza1, iterable=True)
 | 
					        register_stanza_plugin(TestStanza, TestMultiStanza1, iterable=True)
 | 
				
			||||||
        register_stanza_plugin(TestStanza, TestMultiStanza2, iterable=True)
 | 
					        register_stanza_plugin(TestStanza, TestMultiStanza2, iterable=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -938,5 +939,313 @@ class TestElementBase(SleekTest):
 | 
				
			|||||||
        self.assertEqual(len(stanza['substanzas']), 2,
 | 
					        self.assertEqual(len(stanza['substanzas']), 2,
 | 
				
			||||||
            "Wrong number of substanzas: %s" % len(stanza['substanzas']))
 | 
					            "Wrong number of substanzas: %s" % len(stanza['substanzas']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testDefaultLang(self):
 | 
				
			||||||
 | 
					        """Test setting a normal subinterface when a default language is set"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['lang'] = 'sv'
 | 
				
			||||||
 | 
					        stanza['test'] = 'hej'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="sv">
 | 
				
			||||||
 | 
					            <test>hej</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test'], 'hej',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|sv'], 'hej',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|sv'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testSpecifyLangWithDefault(self):
 | 
				
			||||||
 | 
					        """Test specifying various languages."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['lang'] = 'sv'
 | 
				
			||||||
 | 
					        stanza['test'] = 'hej'
 | 
				
			||||||
 | 
					        stanza['test|en'] = 'hi'
 | 
				
			||||||
 | 
					        stanza['test|es'] = 'hola'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="sv">
 | 
				
			||||||
 | 
					            <test>hej</test>
 | 
				
			||||||
 | 
					            <test xml:lang="en">hi</test>
 | 
				
			||||||
 | 
					            <test xml:lang="es">hola</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test'], 'hej',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|sv'], 'hej',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|sv'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|en'], 'hi',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|en'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|es'], 'hola',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|es'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testSpecifyLangWithNoDefault(self):
 | 
				
			||||||
 | 
					        """Test specifying various languages."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['test'] = 'hej'
 | 
				
			||||||
 | 
					        stanza['test|en'] = 'hi'
 | 
				
			||||||
 | 
					        stanza['test|es'] = 'hola'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test">
 | 
				
			||||||
 | 
					            <test>hej</test>
 | 
				
			||||||
 | 
					            <test xml:lang="en">hi</test>
 | 
				
			||||||
 | 
					            <test xml:lang="es">hola</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test'], 'hej',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|en'], 'hi',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|en'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|es'], 'hola',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|es'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testModifyLangInterfaceWithDefault(self):
 | 
				
			||||||
 | 
					        """Test resetting an interface when a default lang is used."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['lang'] = 'es'
 | 
				
			||||||
 | 
					        stanza['test'] = 'hola'
 | 
				
			||||||
 | 
					        stanza['test|en'] = 'hi'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="es">
 | 
				
			||||||
 | 
					            <test>hola</test>
 | 
				
			||||||
 | 
					            <test xml:lang="en">hi</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza['test'] = 'adios'
 | 
				
			||||||
 | 
					        stanza['test|en'] = 'bye'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="es">
 | 
				
			||||||
 | 
					            <test>adios</test>
 | 
				
			||||||
 | 
					            <test xml:lang="en">bye</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test'], 'adios',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|es'], 'adios',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|es'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|en'], 'bye',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|en'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza['test|es'] = 'hola'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="es">
 | 
				
			||||||
 | 
					            <test>hola</test>
 | 
				
			||||||
 | 
					            <test xml:lang="en">bye</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test'], 'hola',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|es'], 'hola',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|es'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testModifyLangInterfaceWithNoDefault(self):
 | 
				
			||||||
 | 
					        """Test resetting an interface when no default lang is used."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['test'] = 'hola'
 | 
				
			||||||
 | 
					        stanza['test|en'] = 'hi'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test">
 | 
				
			||||||
 | 
					            <test>hola</test>
 | 
				
			||||||
 | 
					            <test xml:lang="en">hi</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza['test'] = 'adios'
 | 
				
			||||||
 | 
					        stanza['test|en'] = 'bye'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test">
 | 
				
			||||||
 | 
					            <test>adios</test>
 | 
				
			||||||
 | 
					            <test xml:lang="en">bye</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test'], 'adios',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test'], 'adios',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|es'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(stanza['test|en'], 'bye',
 | 
				
			||||||
 | 
					                "Incorrect subinterface value: %s" % stanza['test|en'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testDelInterfacesWithDefaultLang(self):
 | 
				
			||||||
 | 
					        """Test deleting interfaces with a default lang set."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['lang'] = 'en'
 | 
				
			||||||
 | 
					        stanza['test'] = 'hi'
 | 
				
			||||||
 | 
					        stanza['test|no'] = 'hej'
 | 
				
			||||||
 | 
					        stanza['test|fr'] = 'bonjour'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="en">
 | 
				
			||||||
 | 
					            <test>hi</test>
 | 
				
			||||||
 | 
					            <test xml:lang="no">hej</test>
 | 
				
			||||||
 | 
					            <test xml:lang="fr">bonjour</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        del stanza['test']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="en">
 | 
				
			||||||
 | 
					            <test xml:lang="no">hej</test>
 | 
				
			||||||
 | 
					            <test xml:lang="fr">bonjour</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        del stanza['test|no']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" xml:lang="en">
 | 
				
			||||||
 | 
					            <test xml:lang="fr">bonjour</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testDelInterfacesWithNoDefaultLang(self):
 | 
				
			||||||
 | 
					        """Test deleting interfaces with no default lang set."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['test'] = 'hi'
 | 
				
			||||||
 | 
					        stanza['test|no'] = 'hej'
 | 
				
			||||||
 | 
					        stanza['test|fr'] = 'bonjour'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test">
 | 
				
			||||||
 | 
					            <test>hi</test>
 | 
				
			||||||
 | 
					            <test xml:lang="no">hej</test>
 | 
				
			||||||
 | 
					            <test xml:lang="fr">bonjour</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        del stanza['test']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test">
 | 
				
			||||||
 | 
					            <test xml:lang="no">hej</test>
 | 
				
			||||||
 | 
					            <test xml:lang="fr">bonjour</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        del stanza['test|no']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test">
 | 
				
			||||||
 | 
					            <test xml:lang="fr">bonjour</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testStarLang(self):
 | 
				
			||||||
 | 
					        """Test using interface|*."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestStanza(ElementBase):
 | 
				
			||||||
 | 
					            name = 'foo'
 | 
				
			||||||
 | 
					            namespace = 'test'
 | 
				
			||||||
 | 
					            interfaces = set(['test'])
 | 
				
			||||||
 | 
					            sub_interfaces = interfaces
 | 
				
			||||||
 | 
					            lang_interfaces = interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data = OrderedDict()
 | 
				
			||||||
 | 
					        data['en'] = 'hi'
 | 
				
			||||||
 | 
					        data['fr'] = 'bonjour'
 | 
				
			||||||
 | 
					        data['no'] = 'hej'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stanza = TestStanza()
 | 
				
			||||||
 | 
					        stanza['test|*'] = data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test">
 | 
				
			||||||
 | 
					            <test xml:lang="en">hi</test>
 | 
				
			||||||
 | 
					            <test xml:lang="fr">bonjour</test>
 | 
				
			||||||
 | 
					            <test xml:lang="no">hej</test>
 | 
				
			||||||
 | 
					          </foo>
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data2 = stanza['test|*']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(data, data2,
 | 
				
			||||||
 | 
					                "Did not extract expected language data: %s" % data2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        del stanza['test|*']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.check(stanza, """
 | 
				
			||||||
 | 
					          <foo xmlns="test" />
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestElementBase)
 | 
					suite = unittest.TestLoader().loadTestsFromTestCase(TestElementBase)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user