1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """Iq XMPP stanza handling
19
20 Normative reference:
21 - `RFC 3920 <http://www.ietf.org/rfc/rfc3920.txt>`__
22 """
23
24 __revision__="$Id: iq.py 651 2006-08-27 19:26:45Z jajcus $"
25 __docformat__="restructuredtext en"
26
27 import libxml2
28
29 from pyxmpp.xmlextra import get_node_ns_uri
30 from pyxmpp.stanza import Stanza, gen_id
31
33 """Wraper object for <iq /> stanzas."""
34 stanza_type="iq"
35 - def __init__(self, xmlnode = None, from_jid = None, to_jid = None, stanza_type = None,
36 stanza_id = None, error = None, error_cond=None, stream = None):
37 """Initialize an `Iq` object.
38
39 :Parameters:
40 - `xmlnode`: XML node to_jid be wrapped into the `Iq` object
41 or other Iq object to be copied. If not given then new
42 presence stanza is created using following parameters.
43 - `from_jid`: sender JID.
44 - `to_jid`: recipient JID.
45 - `stanza_type`: staza type: one of: "get", "set", "result" or "error".
46 - `stanza_id`: stanza id -- value of stanza's "id" attribute. If not
47 given, then unique for the session value is generated.
48 - `error_cond`: error condition name. Ignored if `stanza_type` is not "error".
49 :Types:
50 - `xmlnode`: `unicode` or `libxml2.xmlNode` or `Iq`
51 - `from_jid`: `JID`
52 - `to_jid`: `JID`
53 - `stanza_type`: `unicode`
54 - `stanza_id`: `unicode`
55 - `error_cond`: `unicode`"""
56 self.xmlnode=None
57 if isinstance(xmlnode,Iq):
58 pass
59 elif isinstance(xmlnode,Stanza):
60 raise TypeError,"Couldn't make Iq from other Stanza"
61 elif isinstance(xmlnode,libxml2.xmlNode):
62 pass
63 elif xmlnode is not None:
64 raise TypeError,"Couldn't make Iq from %r" % (type(xmlnode),)
65 elif not stanza_type:
66 raise ValueError, "type is required for Iq"
67 else:
68 if not stanza_id and stanza_type in ("get", "set"):
69 stanza_id=gen_id()
70
71 if not xmlnode and stanza_type not in ("get","set","result","error"):
72 raise ValueError, "Invalid Iq type: %r" % (stanza_type,)
73
74 if xmlnode is None:
75 xmlnode="iq"
76
77 Stanza.__init__(self, xmlnode, from_jid = from_jid, to_jid = to_jid,
78 stanza_type = stanza_type, stanza_id = stanza_id, error = error,
79 error_cond = error_cond, stream = stream)
80
82 """Create a deep copy of the iq stanza.
83
84 :returntype: `Iq`"""
85 return Iq(self)
86
88 """Create error response for the a "get" or "set" iq stanza.
89
90 :Parameters:
91 - `cond`: error condition name, as defined in XMPP specification.
92
93 :return: new `Iq` object with the same "id" as self, "from" and "to"
94 attributes swapped, type="error" and containing <error /> element
95 plus payload of `self`.
96 :returntype: `Iq`"""
97
98 if self.get_type() in ("result", "error"):
99 raise ValueError, "Errors may not be generated for 'result' and 'error' iq"
100
101 iq=Iq(stanza_type="error",from_jid=self.get_to(),to_jid=self.get_from(),
102 stanza_id=self.get_id(),error_cond=cond)
103 n=self.get_query()
104 if n:
105 n=n.copyNode(1)
106 iq.xmlnode.children.addPrevSibling(n)
107 return iq
108
110 """Create result response for the a "get" or "set" iq stanza.
111
112 :return: new `Iq` object with the same "id" as self, "from" and "to"
113 attributes replaced and type="result".
114 :returntype: `Iq`"""
115
116 if self.get_type() not in ("set","get"):
117 raise ValueError, "Results may only be generated for 'set' or 'get' iq"
118
119 iq=Iq(stanza_type="result", from_jid=self.get_to(),
120 to_jid=self.get_from(), stanza_id=self.get_id())
121
122 return iq
123
125 """Create new payload element for the stanza.
126
127 :Parameters:
128 - `ns_uri`: namespace URI of the element.
129 - `name`: element name.
130 :Types:
131 - `ns_uri`: `str`
132 - `name`: `unicode`
133
134 :return: the new payload node.
135 :returntype: `libxml2.xmlNode`"""
136 return self.set_new_content(ns_uri,name)
137
139 """Get the payload element of the stanza.
140
141 :return: the payload element or None if there is no payload.
142 :returntype: `libxml2.xmlNode`"""
143 c = self.xmlnode.children
144 while c:
145 try:
146 if c.ns():
147 return c
148 except libxml2.treeError:
149 pass
150 c = c.next
151 return None
152
154 """Get a namespace of the stanza payload.
155
156 :return: XML namespace URI of the payload or None if there is no
157 payload.
158 :returntype: `str`"""
159 q=self.get_query()
160 if q:
161 return get_node_ns_uri(q)
162 else:
163 return None
164
165
166