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 __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
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
81 """Create a deep copy of the iq stanza.
82
83 :returntype: `Iq`"""
84 return Iq(self)
85
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
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
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
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
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
165