Package pyxmpp :: Module iq

[hide private]

# Source Code for Module pyxmpp.iq

      1  #
      2  # (C) Copyright 2003-2010 Jacek Konieczny <jajcus@jajcus.net>
      3  #
      4  # This program is free software; you can redistribute it and/or modify
      5  # it under the terms of the GNU Lesser General Public License Version
      6  # 2.1 as published by the Free Software Foundation.
      7  #
      8  # This program is distributed in the hope that it will be useful,
      9  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  # GNU Lesser General Public License for more details.
     12  #
     13  # You should have received a copy of the GNU Lesser General Public
     14  # License along with this program; if not, write to the Free Software
     15  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     16  #
     17
     18  """Iq XMPP stanza handling
     19
     20  Normative reference:
     21    - `RFC 3920 <http://www.ietf.org/rfc/rfc3920.txt>`__
     22  """
     23
     24  __docformat__="restructuredtext en"
     25
     26  import libxml2
     27
     28  from pyxmpp.xmlextra import get_node_ns_uri
     29  from pyxmpp.stanza import Stanza, gen_id
     30
     31 -class Iq(Stanza):
     32      """Wraper object for <iq /> stanzas."""
     33      stanza_type="iq"
     34 -    def __init__(self, xmlnode = None, from_jid = None, to_jid = None, stanza_type = None,
     35              stanza_id = None, error = None, error_cond=None, stream = None):
     36          """Initialize an `Iq` object.
     37
     38          :Parameters:
     39              - `xmlnode`: XML node to_jid be wrapped into the `Iq` object
     40                or other Iq object to be copied. If not given then new
     41                presence stanza is created using following parameters.
     42              - `from_jid`: sender JID.
     43              - `to_jid`: recipient JID.
     44              - `stanza_type`: staza type: one of: "get", "set", "result" or "error".
     45              - `stanza_id`: stanza id -- value of stanza's "id" attribute. If not
     46                given, then unique for the session value is generated.
     47              - `error_cond`: error condition name. Ignored if `stanza_type` is not "error".
     48          :Types:
     49              - `xmlnode`: `unicode` or `libxml2.xmlNode` or `Iq`
     50              - `from_jid`: `JID`
     51              - `to_jid`: `JID`
     52              - `stanza_type`: `unicode`
     53              - `stanza_id`: `unicode`
     54              - `error_cond`: `unicode`"""
     55          self.xmlnode=None
     56          if isinstance(xmlnode,Iq):
     57              pass
     58          elif isinstance(xmlnode,Stanza):
     59              raise TypeError,"Couldn't make Iq from other Stanza"
     60          elif isinstance(xmlnode,libxml2.xmlNode):
     61              pass
     62          elif xmlnode is not None:
     63              raise TypeError,"Couldn't make Iq from %r" % (type(xmlnode),)
     64          elif not stanza_type:
     65              raise ValueError, "type is required for Iq"
     66          else:
     67              if not stanza_id and stanza_type in ("get", "set"):
     68                  stanza_id=gen_id()
     69
     70          if not xmlnode and stanza_type not in ("get","set","result","error"):
     71              raise ValueError, "Invalid Iq type: %r" % (stanza_type,)
     72
     73          if xmlnode is None:
     74              xmlnode="iq"
     75
     76          Stanza.__init__(self, xmlnode, from_jid = from_jid, to_jid = to_jid,
     77              stanza_type = stanza_type, stanza_id = stanza_id, error = error,
     78              error_cond = error_cond, stream = stream)
     79
     80 -    def copy(self):
     81          """Create a deep copy of the iq stanza.
     82
     83          :returntype: `Iq`"""
     84          return Iq(self)
     85
     86 -    def make_error_response(self,cond):
     87          """Create error response for the a "get" or "set" iq stanza.
     88
     89          :Parameters:
     90              - `cond`: error condition name, as defined in XMPP specification.
     91
     92          :return: new `Iq` object with the same "id" as self, "from" and "to"
     93              attributes swapped, type="error" and containing <error /> element
     94              plus payload of `self`.
     95          :returntype: `Iq`"""
     96
     97          if self.get_type() in ("result", "error"):
     98              raise ValueError, "Errors may not be generated for 'result' and 'error' iq"
     99
    100          iq=Iq(stanza_type="error",from_jid=self.get_to(),to_jid=self.get_from(),
    101              stanza_id=self.get_id(),error_cond=cond)
    102          n=self.get_query()
    103          if n:
    104              n=n.copyNode(1)
    105              iq.xmlnode.children.addPrevSibling(n)
    106          return iq
    107
    108 -    def make_result_response(self):
    109          """Create result response for the a "get" or "set" iq stanza.
    110
    111          :return: new `Iq` object with the same "id" as self, "from" and "to"
    112              attributes replaced and type="result".
    113          :returntype: `Iq`"""
    114
    115          if self.get_type() not in ("set","get"):
    116              raise ValueError, "Results may only be generated for 'set' or 'get' iq"
    117
    118          iq=Iq(stanza_type="result", from_jid=self.get_to(),
    119                  to_jid=self.get_from(), stanza_id=self.get_id())
    120
    121          return iq
    122
    123 -    def new_query(self,ns_uri,name="query"):
    124          """Create new payload element for the stanza.
    125
    126          :Parameters:
    127              - `ns_uri`: namespace URI of the element.
    128              - `name`: element name.
    129          :Types:
    130              - `ns_uri`: `str`
    131              - `name`: `unicode`
    132
    133          :return: the new payload node.
    134          :returntype: `libxml2.xmlNode`"""
    135          return self.set_new_content(ns_uri,name)
    136
    137 -    def get_query(self):
    138          """Get the payload element of the stanza.
    139
    140          :return: the payload element or None if there is no payload.
    141          :returntype: `libxml2.xmlNode`"""
    142          c = self.xmlnode.children
    143          while c:
    144              try:
    145                  if c.ns():
    146                      return c
    147              except libxml2.treeError:
    148                  pass
    149              c = c.next
    150          return None
    151
    152 -    def get_query_ns(self):
    153          """Get a namespace of the stanza payload.
    154
    155          :return: XML namespace URI of the payload or None if there is no
    156              payload.
    157          :returntype: `str`"""
    158          q=self.get_query()
    159          if q:
    160              return get_node_ns_uri(q)
    161          else:
    162              return None
    163
    164  # vi: sts=4 et sw=4
    165