diff options
Diffstat (limited to 'sleekxmpp/stanza')
-rw-r--r-- | sleekxmpp/stanza/__init__.py | 15 | ||||
-rw-r--r-- | sleekxmpp/stanza/atom.py | 43 | ||||
-rw-r--r-- | sleekxmpp/stanza/error.py | 174 | ||||
-rw-r--r-- | sleekxmpp/stanza/htmlim.py | 21 | ||||
-rw-r--r-- | sleekxmpp/stanza/iq.py | 281 | ||||
-rw-r--r-- | sleekxmpp/stanza/message.py | 199 | ||||
-rw-r--r-- | sleekxmpp/stanza/nick.py | 23 | ||||
-rw-r--r-- | sleekxmpp/stanza/presence.py | 191 | ||||
-rw-r--r-- | sleekxmpp/stanza/rootstanza.py | 90 | ||||
-rw-r--r-- | sleekxmpp/stanza/roster.py | 158 | ||||
-rw-r--r-- | sleekxmpp/stanza/stream_error.py | 83 | ||||
-rw-r--r-- | sleekxmpp/stanza/stream_features.py | 57 |
12 files changed, 0 insertions, 1335 deletions
diff --git a/sleekxmpp/stanza/__init__.py b/sleekxmpp/stanza/__init__.py deleted file mode 100644 index 4bd37dc5..00000000 --- a/sleekxmpp/stanza/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - - -from sleekxmpp.stanza.error import Error -from sleekxmpp.stanza.iq import Iq -from sleekxmpp.stanza.message import Message -from sleekxmpp.stanza.presence import Presence -from sleekxmpp.stanza.stream_features import StreamFeatures -from sleekxmpp.stanza.stream_error import StreamError diff --git a/sleekxmpp/stanza/atom.py b/sleekxmpp/stanza/atom.py deleted file mode 100644 index 4e9591a5..00000000 --- a/sleekxmpp/stanza/atom.py +++ /dev/null @@ -1,43 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.xmlstream import register_stanza_plugin, ElementBase - -class AtomEntry(ElementBase): - - """ - A simple Atom feed entry. - - Stanza Interface: - title -- The title of the Atom feed entry. - summary -- The summary of the Atom feed entry. - """ - - namespace = 'http://www.w3.org/2005/Atom' - name = 'entry' - plugin_attrib = 'entry' - interfaces = set(('title', 'summary', 'id', 'published', 'updated')) - sub_interfaces = set(('title', 'summary', 'id', 'published', - 'updated')) - -class AtomAuthor(ElementBase): - - """ - An Atom author. - - Stanza Interface: - name -- The printable author name - uri -- The bare jid of the author - """ - - name = 'author' - plugin_attrib = 'author' - interfaces = set(('name', 'uri')) - sub_interfaces = set(('name', 'uri')) - -register_stanza_plugin(AtomEntry, AtomAuthor) diff --git a/sleekxmpp/stanza/error.py b/sleekxmpp/stanza/error.py deleted file mode 100644 index 56558ba8..00000000 --- a/sleekxmpp/stanza/error.py +++ /dev/null @@ -1,174 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.xmlstream import ElementBase, ET - - -class Error(ElementBase): - - """ - XMPP stanzas of type 'error' should include an <error> stanza that - describes the nature of the error and how it should be handled. - - Use the 'XEP-0086: Error Condition Mappings' plugin to include error - codes used in older XMPP versions. - - Example error stanza: - <error type="cancel" code="404"> - <item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" /> - <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"> - The item was not found. - </text> - </error> - - Stanza Interface: - code -- The error code used in older XMPP versions. - condition -- The name of the condition element. - text -- Human readable description of the error. - type -- Error type indicating how the error should be handled. - - Attributes: - conditions -- The set of allowable error condition elements. - condition_ns -- The namespace for the condition element. - types -- A set of values indicating how the error - should be treated. - - Methods: - setup -- Overrides ElementBase.setup. - get_condition -- Retrieve the name of the condition element. - set_condition -- Add a condition element. - del_condition -- Remove the condition element. - get_text -- Retrieve the contents of the <text> element. - set_text -- Set the contents of the <text> element. - del_text -- Remove the <text> element. - """ - - namespace = 'jabber:client' - name = 'error' - plugin_attrib = 'error' - interfaces = set(('code', 'condition', 'text', 'type', - 'gone', 'redirect', 'by')) - sub_interfaces = set(('text',)) - plugin_attrib_map = {} - plugin_tag_map = {} - conditions = set(('bad-request', 'conflict', 'feature-not-implemented', - 'forbidden', 'gone', 'internal-server-error', - 'item-not-found', 'jid-malformed', 'not-acceptable', - 'not-allowed', 'not-authorized', 'payment-required', - 'recipient-unavailable', 'redirect', - 'registration-required', 'remote-server-not-found', - 'remote-server-timeout', 'resource-constraint', - 'service-unavailable', 'subscription-required', - 'undefined-condition', 'unexpected-request')) - condition_ns = 'urn:ietf:params:xml:ns:xmpp-stanzas' - types = set(('cancel', 'continue', 'modify', 'auth', 'wait')) - - def setup(self, xml=None): - """ - Populate the stanza object using an optional XML object. - - Overrides ElementBase.setup. - - Sets a default error type and condition, and changes the - parent stanza's type to 'error'. - - Arguments: - xml -- Use an existing XML object for the stanza's values. - """ - if ElementBase.setup(self, xml): - #If we had to generate XML then set default values. - self['type'] = 'cancel' - self['condition'] = 'feature-not-implemented' - if self.parent is not None: - self.parent()['type'] = 'error' - - def get_condition(self): - """Return the condition element's name.""" - for child in self.xml: - if "{%s}" % self.condition_ns in child.tag: - cond = child.tag.split('}', 1)[-1] - if cond in self.conditions: - return cond - return '' - - def set_condition(self, value): - """ - Set the tag name of the condition element. - - Arguments: - value -- The tag name of the condition element. - """ - if value in self.conditions: - del self['condition'] - self.xml.append(ET.Element("{%s}%s" % (self.condition_ns, value))) - return self - - def del_condition(self): - """Remove the condition element.""" - for child in self.xml: - if "{%s}" % self.condition_ns in child.tag: - tag = child.tag.split('}', 1)[-1] - if tag in self.conditions: - self.xml.remove(child) - return self - - def get_text(self): - """Retrieve the contents of the <text> element.""" - return self._get_sub_text('{%s}text' % self.condition_ns) - - def set_text(self, value): - """ - Set the contents of the <text> element. - - Arguments: - value -- The new contents for the <text> element. - """ - self._set_sub_text('{%s}text' % self.condition_ns, text=value) - return self - - def del_text(self): - """Remove the <text> element.""" - self._del_sub('{%s}text' % self.condition_ns) - return self - - def get_gone(self): - return self._get_sub_text('{%s}gone' % self.condition_ns, '') - - def get_redirect(self): - return self._get_sub_text('{%s}redirect' % self.condition_ns, '') - - def set_gone(self, value): - if value: - del self['condition'] - return self._set_sub_text('{%s}gone' % self.condition_ns, value) - elif self['condition'] == 'gone': - del self['condition'] - - def set_redirect(self, value): - if value: - del self['condition'] - ns = self.condition_ns - return self._set_sub_text('{%s}redirect' % ns, value) - elif self['condition'] == 'redirect': - del self['condition'] - - def del_gone(self): - self._del_sub('{%s}gone' % self.condition_ns) - - def del_redirect(self): - self._del_sub('{%s}redirect' % self.condition_ns) - - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -Error.getCondition = Error.get_condition -Error.setCondition = Error.set_condition -Error.delCondition = Error.del_condition -Error.getText = Error.get_text -Error.setText = Error.set_text -Error.delText = Error.del_text diff --git a/sleekxmpp/stanza/htmlim.py b/sleekxmpp/stanza/htmlim.py deleted file mode 100644 index c43178f2..00000000 --- a/sleekxmpp/stanza/htmlim.py +++ /dev/null @@ -1,21 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.stanza import Message -from sleekxmpp.xmlstream import register_stanza_plugin -from sleekxmpp.plugins.xep_0071 import XHTML_IM as HTMLIM - - -register_stanza_plugin(Message, HTMLIM) - - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -HTMLIM.setBody = HTMLIM.set_body -HTMLIM.getBody = HTMLIM.get_body -HTMLIM.delBody = HTMLIM.del_body diff --git a/sleekxmpp/stanza/iq.py b/sleekxmpp/stanza/iq.py deleted file mode 100644 index 088de4c0..00000000 --- a/sleekxmpp/stanza/iq.py +++ /dev/null @@ -1,281 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.stanza.rootstanza import RootStanza -from sleekxmpp.xmlstream import StanzaBase, ET -from sleekxmpp.xmlstream.handler import Waiter, Callback -from sleekxmpp.xmlstream.matcher import MatchIDSender, MatcherId -from sleekxmpp.exceptions import IqTimeout, IqError - - -class Iq(RootStanza): - - """ - XMPP <iq> stanzas, or info/query stanzas, are XMPP's method of - requesting and modifying information, similar to HTTP's GET and - POST methods. - - Each <iq> stanza must have an 'id' value which associates the - stanza with the response stanza. XMPP entities must always - be given a response <iq> stanza with a type of 'result' after - sending a stanza of type 'get' or 'set'. - - Most uses cases for <iq> stanzas will involve adding a <query> - element whose namespace indicates the type of information - desired. However, some custom XMPP applications use <iq> stanzas - as a carrier stanza for an application-specific protocol instead. - - Example <iq> Stanzas: - <iq to="user@example.com" type="get" id="314"> - <query xmlns="http://jabber.org/protocol/disco#items" /> - </iq> - - <iq to="user@localhost" type="result" id="17"> - <query xmlns='jabber:iq:roster'> - <item jid='otheruser@example.net' - name='John Doe' - subscription='both'> - <group>Friends</group> - </item> - </query> - </iq> - - Stanza Interface: - query -- The namespace of the <query> element if one exists. - - Attributes: - types -- May be one of: get, set, result, or error. - - Methods: - __init__ -- Overrides StanzaBase.__init__. - unhandled -- Send error if there are no handlers. - set_payload -- Overrides StanzaBase.set_payload. - set_query -- Add or modify a <query> element. - get_query -- Return the namespace of the <query> element. - del_query -- Remove the <query> element. - reply -- Overrides StanzaBase.reply - send -- Overrides StanzaBase.send - """ - - namespace = 'jabber:client' - name = 'iq' - interfaces = set(('type', 'to', 'from', 'id', 'query')) - types = set(('get', 'result', 'set', 'error')) - plugin_attrib = name - - def __init__(self, *args, **kwargs): - """ - Initialize a new <iq> stanza with an 'id' value. - - Overrides StanzaBase.__init__. - """ - StanzaBase.__init__(self, *args, **kwargs) - if self['id'] == '': - if self.stream is not None: - self['id'] = self.stream.new_id() - else: - self['id'] = '0' - - def unhandled(self): - """ - Send a feature-not-implemented error if the stanza is not handled. - - Overrides StanzaBase.unhandled. - """ - if self['type'] in ('get', 'set'): - self.reply() - self['error']['condition'] = 'feature-not-implemented' - self['error']['text'] = 'No handlers registered for this request.' - self.send() - - def set_payload(self, value): - """ - Set the XML contents of the <iq> stanza. - - Arguments: - value -- An XML object to use as the <iq> stanza's contents - """ - self.clear() - StanzaBase.set_payload(self, value) - return self - - def set_query(self, value): - """ - Add or modify a <query> element. - - Query elements are differentiated by their namespace. - - Arguments: - value -- The namespace of the <query> element. - """ - query = self.xml.find("{%s}query" % value) - if query is None and value: - plugin = self.plugin_tag_map.get('{%s}query' % value, None) - if plugin: - self.enable(plugin.plugin_attrib) - else: - self.clear() - query = ET.Element("{%s}query" % value) - self.xml.append(query) - return self - - def get_query(self): - """Return the namespace of the <query> element.""" - for child in self.xml: - if child.tag.endswith('query'): - ns = child.tag.split('}')[0] - if '{' in ns: - ns = ns[1:] - return ns - return '' - - def del_query(self): - """Remove the <query> element.""" - for child in self.xml: - if child.tag.endswith('query'): - self.xml.remove(child) - return self - - def reply(self, clear=True): - """ - Send a reply <iq> stanza. - - Overrides StanzaBase.reply - - Sets the 'type' to 'result' in addition to the default - StanzaBase.reply behavior. - - Arguments: - clear -- Indicates if existing content should be - removed before replying. Defaults to True. - """ - self['type'] = 'result' - StanzaBase.reply(self, clear) - return self - - def send(self, block=True, timeout=None, callback=None, now=False, timeout_callback=None): - """ - Send an <iq> stanza over the XML stream. - - The send call can optionally block until a response is received or - a timeout occurs. Be aware that using blocking in non-threaded event - handlers can drastically impact performance. Otherwise, a callback - handler can be provided that will be executed when the Iq stanza's - result reply is received. Be aware though that that the callback - handler will not be executed in its own thread. - - Using both block and callback is not recommended, and only the - callback argument will be used in that case. - - Overrides StanzaBase.send - - Arguments: - block -- Specify if the send call will block until a response - is received, or a timeout occurs. Defaults to True. - timeout -- The length of time (in seconds) to wait for a response - before exiting the send call if blocking is used. - Defaults to sleekxmpp.xmlstream.RESPONSE_TIMEOUT - callback -- Optional reference to a stream handler function. Will - be executed when a reply stanza is received. - now -- Indicates if the send queue should be skipped and send - the stanza immediately. Used during stream - initialization. Defaults to False. - timeout_callback -- Optional reference to a stream handler function. - Will be executed when the timeout expires before a - response has been received with the originally-sent IQ - stanza. Only called if there is a callback parameter - (and therefore are in async mode). - """ - if timeout is None: - timeout = self.stream.response_timeout - - if self.stream.session_bind_event.is_set(): - matcher = MatchIDSender({ - 'id': self['id'], - 'self': self.stream.boundjid, - 'peer': self['to'] - }) - else: - matcher = MatcherId(self['id']) - - if callback is not None and self['type'] in ('get', 'set'): - handler_name = 'IqCallback_%s' % self['id'] - if timeout_callback: - self.callback = callback - self.timeout_callback = timeout_callback - self.stream.schedule('IqTimeout_%s' % self['id'], - timeout, - self._fire_timeout, - repeat=False) - handler = Callback(handler_name, - matcher, - self._handle_result, - once=True) - else: - handler = Callback(handler_name, - matcher, - callback, - once=True) - self.stream.register_handler(handler) - StanzaBase.send(self, now=now) - return handler_name - elif block and self['type'] in ('get', 'set'): - waitfor = Waiter('IqWait_%s' % self['id'], matcher) - self.stream.register_handler(waitfor) - StanzaBase.send(self, now=now) - result = waitfor.wait(timeout) - if not result: - raise IqTimeout(self) - if result['type'] == 'error': - raise IqError(result) - return result - else: - return StanzaBase.send(self, now=now) - - def _handle_result(self, iq): - # we got the IQ, so don't fire the timeout - self.stream.scheduler.remove('IqTimeout_%s' % self['id']) - self.callback(iq) - - def _fire_timeout(self): - # don't fire the handler for the IQ, if it finally does come in - self.stream.remove_handler('IqCallback_%s' % self['id']) - self.timeout_callback(self) - - def _set_stanza_values(self, values): - """ - Set multiple stanza interface values using a dictionary. - - Stanza plugin values may be set usind nested dictionaries. - - If the interface 'query' is given, then it will be set - last to avoid duplication of the <query /> element. - - Overrides ElementBase._set_stanza_values. - - Arguments: - values -- A dictionary mapping stanza interface with values. - Plugin interfaces may accept a nested dictionary that - will be used recursively. - """ - query = values.get('query', '') - if query: - del values['query'] - StanzaBase._set_stanza_values(self, values) - self['query'] = query - else: - StanzaBase._set_stanza_values(self, values) - return self - - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -Iq.setPayload = Iq.set_payload -Iq.getQuery = Iq.get_query -Iq.setQuery = Iq.set_query -Iq.delQuery = Iq.del_query diff --git a/sleekxmpp/stanza/message.py b/sleekxmpp/stanza/message.py deleted file mode 100644 index 0bb6e587..00000000 --- a/sleekxmpp/stanza/message.py +++ /dev/null @@ -1,199 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.stanza.rootstanza import RootStanza -from sleekxmpp.xmlstream import StanzaBase, ET - - -class Message(RootStanza): - - """ - XMPP's <message> stanzas are a "push" mechanism to send information - to other XMPP entities without requiring a response. - - Chat clients will typically use <message> stanzas that have a type - of either "chat" or "groupchat". - - When handling a message event, be sure to check if the message is - an error response. - - Example <message> stanzas: - <message to="user1@example.com" from="user2@example.com"> - <body>Hi!</body> - </message> - - <message type="groupchat" to="room@conference.example.com"> - <body>Hi everyone!</body> - </message> - - Stanza Interface: - body -- The main contents of the message. - subject -- An optional description of the message's contents. - mucroom -- (Read-only) The name of the MUC room that sent the message. - mucnick -- (Read-only) The MUC nickname of message's sender. - - Attributes: - types -- May be one of: normal, chat, headline, groupchat, or error. - - Methods: - setup -- Overrides StanzaBase.setup. - chat -- Set the message type to 'chat'. - normal -- Set the message type to 'normal'. - reply -- Overrides StanzaBase.reply - get_type -- Overrides StanzaBase interface - get_mucroom -- Return the name of the MUC room of the message. - set_mucroom -- Dummy method to prevent assignment. - del_mucroom -- Dummy method to prevent deletion. - get_mucnick -- Return the MUC nickname of the message's sender. - set_mucnick -- Dummy method to prevent assignment. - del_mucnick -- Dummy method to prevent deletion. - """ - - name = 'message' - namespace = 'jabber:client' - plugin_attrib = name - 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 __init__(self, *args, **kwargs): - """ - Initialize a new <message /> stanza with an optional 'id' value. - - Overrides StanzaBase.__init__. - """ - StanzaBase.__init__(self, *args, **kwargs) - if self['id'] == '': - if self.stream is not None and self.stream.use_message_ids: - self['id'] = self.stream.new_id() - - def get_type(self): - """ - Return the message type. - - Overrides default stanza interface behavior. - - Returns 'normal' if no type attribute is present. - """ - 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): - """Set the message type to 'chat'.""" - self['type'] = 'chat' - return self - - def normal(self): - """Set the message type to 'normal'.""" - self['type'] = 'normal' - return self - - def reply(self, body=None, clear=True): - """ - Create a message reply. - - Overrides StanzaBase.reply. - - Sets proper 'to' attribute if the message is from a MUC, and - adds a message body if one is given. - - Arguments: - body -- Optional text content for the message. - clear -- Indicates if existing content should be removed - before replying. Defaults to True. - """ - thread = self['thread'] - parent = self['parent_thread'] - - StanzaBase.reply(self, clear) - if self['type'] == 'groupchat': - self['to'] = self['to'].bare - - self['thread'] = thread - self['parent_thread'] = parent - - del self['id'] - - if body is not None: - self['body'] = body - return self - - def get_mucroom(self): - """ - Return the name of the MUC room where the message originated. - - Read-only stanza interface. - """ - if self['type'] == 'groupchat': - return self['from'].bare - else: - return '' - - def get_mucnick(self): - """ - Return the nickname of the MUC user that sent the message. - - Read-only stanza interface. - """ - if self['type'] == 'groupchat': - return self['from'].resource - else: - return '' - - def set_mucroom(self, value): - """Dummy method to prevent modification.""" - pass - - def del_mucroom(self): - """Dummy method to prevent deletion.""" - pass - - def set_mucnick(self, value): - """Dummy method to prevent modification.""" - pass - - def del_mucnick(self): - """Dummy method to prevent deletion.""" - pass - - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -Message.getType = Message.get_type -Message.getMucroom = Message.get_mucroom -Message.setMucroom = Message.set_mucroom -Message.delMucroom = Message.del_mucroom -Message.getMucnick = Message.get_mucnick -Message.setMucnick = Message.set_mucnick -Message.delMucnick = Message.del_mucnick diff --git a/sleekxmpp/stanza/nick.py b/sleekxmpp/stanza/nick.py deleted file mode 100644 index 0e9a5c2b..00000000 --- a/sleekxmpp/stanza/nick.py +++ /dev/null @@ -1,23 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -# The nickname stanza has been moved to its own plugin, but the existing -# references are kept for backwards compatibility. - -from sleekxmpp.stanza import Message, Presence -from sleekxmpp.xmlstream import register_stanza_plugin -from sleekxmpp.plugins.xep_0172 import UserNick as Nick - -register_stanza_plugin(Message, Nick) -register_stanza_plugin(Presence, Nick) - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -Nick.setNick = Nick.set_nick -Nick.getNick = Nick.get_nick -Nick.delNick = Nick.del_nick diff --git a/sleekxmpp/stanza/presence.py b/sleekxmpp/stanza/presence.py deleted file mode 100644 index 84bcd122..00000000 --- a/sleekxmpp/stanza/presence.py +++ /dev/null @@ -1,191 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.stanza.rootstanza import RootStanza -from sleekxmpp.xmlstream import StanzaBase - - -class Presence(RootStanza): - - """ - XMPP's <presence> stanza allows entities to know the status of other - clients and components. Since it is currently the only multi-cast - stanza in XMPP, many extensions add more information to <presence> - stanzas to broadcast to every entry in the roster, such as - capabilities, music choices, or locations (XEP-0115: Entity Capabilities - and XEP-0163: Personal Eventing Protocol). - - Since <presence> stanzas are broadcast when an XMPP entity changes - its status, the bulk of the traffic in an XMPP network will be from - <presence> stanzas. Therefore, do not include more information than - necessary in a status message or within a <presence> stanza in order - to help keep the network running smoothly. - - Example <presence> stanzas: - <presence /> - - <presence from="user@example.com"> - <show>away</show> - <status>Getting lunch.</status> - <priority>5</priority> - </presence> - - <presence type="unavailable" /> - - <presence to="user@otherhost.com" type="subscribe" /> - - Stanza Interface: - priority -- A value used by servers to determine message routing. - show -- The type of status, such as away or available for chat. - status -- Custom, human readable status message. - - Attributes: - types -- One of: available, unavailable, error, probe, - subscribe, subscribed, unsubscribe, - and unsubscribed. - showtypes -- One of: away, chat, dnd, and xa. - - Methods: - setup -- Overrides StanzaBase.setup - reply -- Overrides StanzaBase.reply - set_show -- Set the value of the <show> element. - get_type -- Get the value of the type attribute or <show> element. - set_type -- Set the value of the type attribute or <show> element. - get_priority -- Get the value of the <priority> element. - set_priority -- Set the value of the <priority> element. - """ - - name = 'presence' - namespace = 'jabber:client' - 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', - 'subscribed', 'unsubscribe', 'unsubscribed']) - showtypes = set(['dnd', 'chat', 'xa', 'away']) - - def __init__(self, *args, **kwargs): - """ - Initialize a new <presence /> stanza with an optional 'id' value. - - Overrides StanzaBase.__init__. - """ - StanzaBase.__init__(self, *args, **kwargs) - if self['id'] == '': - if self.stream is not None and self.stream.use_presence_ids: - self['id'] = self.stream.new_id() - - def exception(self, e): - """ - Override exception passback for presence. - """ - pass - - def set_show(self, show): - """ - Set the value of the <show> element. - - Arguments: - show -- Must be one of: away, chat, dnd, or xa. - """ - if show is None: - self._del_sub('show') - elif show in self.showtypes: - self._set_sub_text('show', text=show) - return self - - def get_type(self): - """ - Return the value of the <presence> stanza's type attribute, or - the value of the <show> element. - """ - out = self._get_attr('type') - if not out: - out = self['show'] - if not out or out is None: - out = 'available' - return out - - def set_type(self, value): - """ - Set the type attribute's value, and the <show> element - if applicable. - - Arguments: - value -- Must be in either self.types or self.showtypes. - """ - if value in self.types: - self['show'] = None - if value == 'available': - value = '' - self._set_attr('type', value) - elif value in self.showtypes: - self['show'] = value - return self - - def del_type(self): - """ - Remove both the type attribute and the <show> element. - """ - self._del_attr('type') - self._del_sub('show') - - def set_priority(self, value): - """ - Set the entity's priority value. Some server use priority to - determine message routing behavior. - - Bot clients should typically use a priority of 0 if the same - JID is used elsewhere by a human-interacting client. - - Arguments: - value -- An integer value greater than or equal to 0. - """ - self._set_sub_text('priority', text=str(value)) - - def get_priority(self): - """ - Return the value of the <presence> element as an integer. - """ - p = self._get_sub_text('priority') - if not p: - p = 0 - try: - return int(p) - except ValueError: - # The priority is not a number: we consider it 0 as a default - return 0 - - def reply(self, clear=True): - """ - Set the appropriate presence reply type. - - Overrides StanzaBase.reply. - - Arguments: - clear -- Indicates if the stanza contents should be removed - before replying. Defaults to True. - """ - if self['type'] == 'unsubscribe': - self['type'] = 'unsubscribed' - elif self['type'] == 'subscribe': - self['type'] = 'subscribed' - return StanzaBase.reply(self, clear) - - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -Presence.setShow = Presence.set_show -Presence.getType = Presence.get_type -Presence.setType = Presence.set_type -Presence.delType = Presence.get_type -Presence.getPriority = Presence.get_priority -Presence.setPriority = Presence.set_priority diff --git a/sleekxmpp/stanza/rootstanza.py b/sleekxmpp/stanza/rootstanza.py deleted file mode 100644 index 52b807e5..00000000 --- a/sleekxmpp/stanza/rootstanza.py +++ /dev/null @@ -1,90 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -import logging - -from sleekxmpp.exceptions import XMPPError, IqError, IqTimeout -from sleekxmpp.stanza import Error -from sleekxmpp.xmlstream import ET, StanzaBase, register_stanza_plugin - - -log = logging.getLogger(__name__) - - -class RootStanza(StanzaBase): - - """ - A top-level XMPP stanza in an XMLStream. - - The RootStanza class provides a more XMPP specific exception - handler than provided by the generic StanzaBase class. - - Methods: - exception -- Overrides StanzaBase.exception - """ - - def exception(self, e): - """ - Create and send an error reply. - - Typically called when an event handler raises an exception. - The error's type and text content are based on the exception - object's type and content. - - Overrides StanzaBase.exception. - - Arguments: - e -- Exception object - """ - if isinstance(e, IqError): - # We received an Iq error reply, but it wasn't caught - # locally. Using the condition/text from that error - # response could leak too much information, so we'll - # only use a generic error here. - self.reply() - self['error']['condition'] = 'undefined-condition' - self['error']['text'] = 'External error' - self['error']['type'] = 'cancel' - log.warning('You should catch IqError exceptions') - self.send() - elif isinstance(e, IqTimeout): - self.reply() - self['error']['condition'] = 'remote-server-timeout' - self['error']['type'] = 'wait' - log.warning('You should catch IqTimeout exceptions') - self.send() - elif isinstance(e, XMPPError): - # We raised this deliberately - keep_id = self['id'] - self.reply(clear=e.clear) - self['id'] = keep_id - self['error']['condition'] = e.condition - self['error']['text'] = e.text - self['error']['type'] = e.etype - if e.extension is not None: - # Extended error tag - extxml = ET.Element("{%s}%s" % (e.extension_ns, e.extension), - e.extension_args) - self['error'].append(extxml) - self.send() - else: - # We probably didn't raise this on purpose, so send an error stanza - keep_id = self['id'] - self.reply() - self['id'] = keep_id - self['error']['condition'] = 'undefined-condition' - self['error']['text'] = "SleekXMPP got into trouble." - self['error']['type'] = 'cancel' - self.send() - # log the error - log.exception('Error handling {%s}%s stanza', - self.namespace, self.name) - # Finally raise the exception to a global exception handler - self.stream.exception(e) - -register_stanza_plugin(RootStanza, Error) diff --git a/sleekxmpp/stanza/roster.py b/sleekxmpp/stanza/roster.py deleted file mode 100644 index 681efd4f..00000000 --- a/sleekxmpp/stanza/roster.py +++ /dev/null @@ -1,158 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.stanza import Iq -from sleekxmpp.xmlstream import JID -from sleekxmpp.xmlstream import ET, ElementBase, register_stanza_plugin - - -class Roster(ElementBase): - - """ - Example roster stanzas: - <iq type="set"> - <query xmlns="jabber:iq:roster"> - <item jid="user@example.com" subscription="both" name="User"> - <group>Friends</group> - </item> - </query> - </iq> - - Stanza Inteface: - items -- A dictionary of roster entries contained - in the stanza. - - Methods: - get_items -- Return a dictionary of roster entries. - set_items -- Add <item> elements. - del_items -- Remove all <item> elements. - """ - - namespace = 'jabber:iq:roster' - name = 'query' - plugin_attrib = 'roster' - interfaces = set(('items', 'ver')) - - def get_ver(self): - """ - Ensure handling an empty ver attribute propery. - - The ver attribute is special in that the presence of the - attribute with an empty value is important for boostrapping - roster versioning. - """ - return self.xml.attrib.get('ver', None) - - def set_ver(self, ver): - """ - Ensure handling an empty ver attribute propery. - - The ver attribute is special in that the presence of the - attribute with an empty value is important for boostrapping - roster versioning. - """ - if ver is not None: - self.xml.attrib['ver'] = ver - else: - del self.xml.attrib['ver'] - - def set_items(self, items): - """ - Set the roster entries in the <roster> stanza. - - Uses a dictionary using JIDs as keys, where each entry is itself - a dictionary that contains: - name -- An alias or nickname for the JID. - subscription -- The subscription type. Can be one of 'to', - 'from', 'both', 'none', or 'remove'. - groups -- A list of group names to which the JID - has been assigned. - - Arguments: - items -- A dictionary of roster entries. - """ - self.del_items() - for jid in items: - item = RosterItem() - item.values = items[jid] - item['jid'] = jid - self.append(item) - return self - - def get_items(self): - """ - Return a dictionary of roster entries. - - Each item is keyed using its JID, and contains: - name -- An assigned alias or nickname for the JID. - subscription -- The subscription type. Can be one of 'to', - 'from', 'both', 'none', or 'remove'. - groups -- A list of group names to which the JID has - been assigned. - """ - items = {} - for item in self['substanzas']: - if isinstance(item, RosterItem): - items[item['jid']] = item.values - # Remove extra JID reference to keep everything - # backward compatible - del items[item['jid']]['jid'] - del items[item['jid']]['lang'] - return items - - def del_items(self): - """ - Remove all <item> elements from the roster stanza. - """ - for item in self['substanzas']: - if isinstance(item, RosterItem): - self.xml.remove(item.xml) - - -class RosterItem(ElementBase): - namespace = 'jabber:iq:roster' - name = 'item' - plugin_attrib = 'item' - interfaces = set(('jid', 'name', 'subscription', 'ask', - 'approved', 'groups')) - - def get_jid(self): - return JID(self._get_attr('jid', '')) - - def set_jid(self, jid): - self._set_attr('jid', str(jid)) - - def get_groups(self): - groups = [] - for group in self.xml.findall('{%s}group' % self.namespace): - if group.text: - groups.append(group.text) - else: - groups.append('') - return groups - - def set_groups(self, values): - self.del_groups() - for group in values: - group_xml = ET.Element('{%s}group' % self.namespace) - group_xml.text = group - self.xml.append(group_xml) - - def del_groups(self): - for group in self.xml.findall('{%s}group' % self.namespace): - self.xml.remove(group) - - -register_stanza_plugin(Iq, Roster) -register_stanza_plugin(Roster, RosterItem, iterable=True) - -# To comply with PEP8, method names now use underscores. -# Deprecated method names are re-mapped for backwards compatibility. -Roster.setItems = Roster.set_items -Roster.getItems = Roster.get_items -Roster.delItems = Roster.del_items diff --git a/sleekxmpp/stanza/stream_error.py b/sleekxmpp/stanza/stream_error.py deleted file mode 100644 index ed0078c9..00000000 --- a/sleekxmpp/stanza/stream_error.py +++ /dev/null @@ -1,83 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.stanza.error import Error -from sleekxmpp.xmlstream import StanzaBase - - -class StreamError(Error, StanzaBase): - - """ - XMPP stanzas of type 'error' should include an <error> stanza that - describes the nature of the error and how it should be handled. - - Use the 'XEP-0086: Error Condition Mappings' plugin to include error - codes used in older XMPP versions. - - The stream:error stanza is used to provide more information for - error that occur with the underlying XML stream itself, and not - a particular stanza. - - Note: The StreamError stanza is mostly the same as the normal - Error stanza, but with different namespaces and - condition names. - - Example error stanza: - <stream:error> - <not-well-formed xmlns="urn:ietf:params:xml:ns:xmpp-streams" /> - <text xmlns="urn:ietf:params:xml:ns:xmpp-streams"> - XML was not well-formed. - </text> - </stream:error> - - Stanza Interface: - condition -- The name of the condition element. - text -- Human readable description of the error. - - Attributes: - conditions -- The set of allowable error condition elements. - condition_ns -- The namespace for the condition element. - - Methods: - setup -- Overrides ElementBase.setup. - get_condition -- Retrieve the name of the condition element. - set_condition -- Add a condition element. - del_condition -- Remove the condition element. - get_text -- Retrieve the contents of the <text> element. - set_text -- Set the contents of the <text> element. - del_text -- Remove the <text> element. - """ - - namespace = 'http://etherx.jabber.org/streams' - interfaces = set(('condition', 'text', 'see_other_host')) - conditions = set(( - 'bad-format', 'bad-namespace-prefix', 'conflict', - 'connection-timeout', 'host-gone', 'host-unknown', - 'improper-addressing', 'internal-server-error', 'invalid-from', - 'invalid-namespace', 'invalid-xml', 'not-authorized', - 'not-well-formed', 'policy-violation', 'remote-connection-failed', - 'reset', 'resource-constraint', 'restricted-xml', 'see-other-host', - 'system-shutdown', 'undefined-condition', 'unsupported-encoding', - 'unsupported-feature', 'unsupported-stanza-type', - 'unsupported-version')) - condition_ns = 'urn:ietf:params:xml:ns:xmpp-streams' - - def get_see_other_host(self): - ns = self.condition_ns - return self._get_sub_text('{%s}see-other-host' % ns, '') - - def set_see_other_host(self, value): - if value: - del self['condition'] - ns = self.condition_ns - return self._set_sub_text('{%s}see-other-host' % ns, value) - elif self['condition'] == 'see-other-host': - del self['condition'] - - def del_see_other_host(self): - self._del_sub('{%s}see-other-host' % self.condition_ns) diff --git a/sleekxmpp/stanza/stream_features.py b/sleekxmpp/stanza/stream_features.py deleted file mode 100644 index e487721e..00000000 --- a/sleekxmpp/stanza/stream_features.py +++ /dev/null @@ -1,57 +0,0 @@ -""" - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. - - See the file LICENSE for copying permission. -""" - -from sleekxmpp.thirdparty import OrderedDict -from sleekxmpp.xmlstream import StanzaBase - - -class StreamFeatures(StanzaBase): - - """ - """ - - name = 'features' - namespace = 'http://etherx.jabber.org/streams' - interfaces = set(('features', 'required', 'optional')) - sub_interfaces = interfaces - plugin_tag_map = {} - plugin_attrib_map = {} - - def setup(self, xml): - StanzaBase.setup(self, xml) - self.values = self.values - - def get_features(self): - """ - """ - features = OrderedDict() - for (name, lang), plugin in self.plugins.items(): - features[name] = plugin - return features - - def set_features(self, value): - """ - """ - pass - - def del_features(self): - """ - """ - pass - - def get_required(self): - """ - """ - features = self['features'] - return [f for n, f in features.items() if f['required']] - - def get_optional(self): - """ - """ - features = self['features'] - return [f for n, f in features.items() if not f['required']] |