Software /
code /
prosody
Comparison
util/stanza.lua @ 7256:9fbb9fbf7e52
Merge 0.10->trunk
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 09 Mar 2016 13:19:38 +0000 |
parent | 6978:30c96a5db360 |
parent | 7253:f4e71242556a |
child | 7758:2b305ec8c146 |
comparison
equal
deleted
inserted
replaced
7255:3da7c334f034 | 7256:9fbb9fbf7e52 |
---|---|
38 local _ENV = nil; | 38 local _ENV = nil; |
39 | 39 |
40 local stanza_mt = { __type = "stanza" }; | 40 local stanza_mt = { __type = "stanza" }; |
41 stanza_mt.__index = stanza_mt; | 41 stanza_mt.__index = stanza_mt; |
42 | 42 |
43 local function stanza(name, attr, namespaces) | 43 local function new_stanza(name, attr, namespaces) |
44 local stanza = { name = name, attr = attr or {}, namespaces = namespaces, tags = {} }; | 44 local stanza = { name = name, attr = attr or {}, namespaces = namespaces, tags = {} }; |
45 return setmetatable(stanza, stanza_mt); | 45 return setmetatable(stanza, stanza_mt); |
46 end | 46 end |
47 local stanza = stanza; | |
48 | 47 |
49 function stanza_mt:query(xmlns) | 48 function stanza_mt:query(xmlns) |
50 return self:tag("query", { xmlns = xmlns }); | 49 return self:tag("query", { xmlns = xmlns }); |
51 end | 50 end |
52 | 51 |
53 function stanza_mt:body(text, attr) | 52 function stanza_mt:body(text, attr) |
54 return self:tag("body", attr):text(text); | 53 return self:tag("body", attr):text(text); |
55 end | 54 end |
56 | 55 |
57 function stanza_mt:tag(name, attr, namespaces) | 56 function stanza_mt:tag(name, attr, namespaces) |
58 local s = stanza(name, attr, namespaces); | 57 local s = new_stanza(name, attr, namespaces); |
59 local last_add = self.last_add; | 58 local last_add = self.last_add; |
60 if not last_add then last_add = {}; self.last_add = last_add; end | 59 if not last_add then last_add = {}; self.last_add = last_add; end |
61 (last_add[#last_add] or self):add_direct_child(s); | 60 (last_add[#last_add] or self):add_direct_child(s); |
62 t_insert(last_add, s); | 61 t_insert(last_add, s); |
63 return self; | 62 return self; |
200 | 199 |
201 | 200 |
202 local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; | 201 local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; |
203 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end | 202 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end |
204 | 203 |
205 local function _dostring(t, buf, self, xml_escape, parentns) | 204 local function _dostring(t, buf, self, _xml_escape, parentns) |
206 local nsid = 0; | 205 local nsid = 0; |
207 local name = t.name | 206 local name = t.name |
208 t_insert(buf, "<"..name); | 207 t_insert(buf, "<"..name); |
209 for k, v in pairs(t.attr) do | 208 for k, v in pairs(t.attr) do |
210 if s_find(k, "\1", 1, true) then | 209 if s_find(k, "\1", 1, true) then |
211 local ns, attrk = s_match(k, "^([^\1]*)\1?(.*)$"); | 210 local ns, attrk = s_match(k, "^([^\1]*)\1?(.*)$"); |
212 nsid = nsid + 1; | 211 nsid = nsid + 1; |
213 t_insert(buf, " xmlns:ns"..nsid.."='"..xml_escape(ns).."' ".."ns"..nsid..":"..attrk.."='"..xml_escape(v).."'"); | 212 t_insert(buf, " xmlns:ns"..nsid.."='".._xml_escape(ns).."' ".."ns"..nsid..":"..attrk.."='".._xml_escape(v).."'"); |
214 elseif not(k == "xmlns" and v == parentns) then | 213 elseif not(k == "xmlns" and v == parentns) then |
215 t_insert(buf, " "..k.."='"..xml_escape(v).."'"); | 214 t_insert(buf, " "..k.."='".._xml_escape(v).."'"); |
216 end | 215 end |
217 end | 216 end |
218 local len = #t; | 217 local len = #t; |
219 if len == 0 then | 218 if len == 0 then |
220 t_insert(buf, "/>"); | 219 t_insert(buf, "/>"); |
221 else | 220 else |
222 t_insert(buf, ">"); | 221 t_insert(buf, ">"); |
223 for n=1,len do | 222 for n=1,len do |
224 local child = t[n]; | 223 local child = t[n]; |
225 if child.name then | 224 if child.name then |
226 self(child, buf, self, xml_escape, t.attr.xmlns); | 225 self(child, buf, self, _xml_escape, t.attr.xmlns); |
227 else | 226 else |
228 t_insert(buf, xml_escape(child)); | 227 t_insert(buf, _xml_escape(child)); |
229 end | 228 end |
230 end | 229 end |
231 t_insert(buf, "</"..name..">"); | 230 t_insert(buf, "</"..name..">"); |
232 end | 231 end |
233 end | 232 end |
250 return t_concat(t); | 249 return t_concat(t); |
251 end | 250 end |
252 end | 251 end |
253 | 252 |
254 function stanza_mt.get_error(stanza) | 253 function stanza_mt.get_error(stanza) |
255 local type, condition, text; | 254 local error_type, condition, text; |
256 | 255 |
257 local error_tag = stanza:get_child("error"); | 256 local error_tag = stanza:get_child("error"); |
258 if not error_tag then | 257 if not error_tag then |
259 return nil, nil, nil; | 258 return nil, nil, nil; |
260 end | 259 end |
261 type = error_tag.attr.type; | 260 error_type = error_tag.attr.type; |
262 | 261 |
263 for _, child in ipairs(error_tag.tags) do | 262 for _, child in ipairs(error_tag.tags) do |
264 if child.attr.xmlns == xmlns_stanzas then | 263 if child.attr.xmlns == xmlns_stanzas then |
265 if not text and child.name == "text" then | 264 if not text and child.name == "text" then |
266 text = child:get_text(); | 265 text = child:get_text(); |
270 if condition and text then | 269 if condition and text then |
271 break; | 270 break; |
272 end | 271 end |
273 end | 272 end |
274 end | 273 end |
275 return type, condition or "undefined-condition", text; | 274 return error_type, condition or "undefined-condition", text; |
276 end | 275 end |
277 | 276 |
278 local id = 0; | 277 local id = 0; |
279 local function new_id() | 278 local function new_id() |
280 id = id + 1; | 279 id = id + 1; |
350 return setmetatable(new, stanza_mt); | 349 return setmetatable(new, stanza_mt); |
351 end | 350 end |
352 | 351 |
353 local function message(attr, body) | 352 local function message(attr, body) |
354 if not body then | 353 if not body then |
355 return stanza("message", attr); | 354 return new_stanza("message", attr); |
356 else | 355 else |
357 return stanza("message", attr):tag("body"):text(body):up(); | 356 return new_stanza("message", attr):tag("body"):text(body):up(); |
358 end | 357 end |
359 end | 358 end |
360 local function iq(attr) | 359 local function iq(attr) |
361 if attr and not attr.id then attr.id = new_id(); end | 360 if attr and not attr.id then attr.id = new_id(); end |
362 return stanza("iq", attr or { id = new_id() }); | 361 return new_stanza("iq", attr or { id = new_id() }); |
363 end | 362 end |
364 | 363 |
365 local function reply(orig) | 364 local function reply(orig) |
366 return stanza(orig.name, orig.attr and { to = orig.attr.from, from = orig.attr.to, id = orig.attr.id, type = ((orig.name == "iq" and "result") or orig.attr.type) }); | 365 return new_stanza(orig.name, orig.attr and { to = orig.attr.from, from = orig.attr.to, id = orig.attr.id, type = ((orig.name == "iq" and "result") or orig.attr.type) }); |
367 end | 366 end |
368 | 367 |
369 local xmpp_stanzas_attr = { xmlns = xmlns_stanzas }; | 368 local xmpp_stanzas_attr = { xmlns = xmlns_stanzas }; |
370 local function error_reply(orig, type, condition, message) | 369 local function error_reply(orig, error_type, condition, error_message) |
371 local t = reply(orig); | 370 local t = reply(orig); |
372 t.attr.type = "error"; | 371 t.attr.type = "error"; |
373 t:tag("error", {type = type}) --COMPAT: Some day xmlns:stanzas goes here | 372 t:tag("error", {type = error_type}) --COMPAT: Some day xmlns:stanzas goes here |
374 :tag(condition, xmpp_stanzas_attr):up(); | 373 :tag(condition, xmpp_stanzas_attr):up(); |
375 if (message) then t:tag("text", xmpp_stanzas_attr):text(message):up(); end | 374 if error_message then t:tag("text", xmpp_stanzas_attr):text(error_message):up(); end |
376 return t; -- stanza ready for adding app-specific errors | 375 return t; -- stanza ready for adding app-specific errors |
377 end | 376 end |
378 | 377 |
379 local function presence(attr) | 378 local function presence(attr) |
380 return stanza("presence", attr); | 379 return new_stanza("presence", attr); |
381 end | 380 end |
382 | 381 |
383 if do_pretty_printing then | 382 if do_pretty_printing then |
384 local style_attrk = getstyle("yellow"); | 383 local style_attrk = getstyle("yellow"); |
385 local style_attrv = getstyle("red"); | 384 local style_attrv = getstyle("red"); |
390 local top_tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, ">"); | 389 local top_tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, ">"); |
391 --local tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, ">").."%s"..getstring(style_punc, "</")..getstring(style_tagname, "%s")..getstring(style_punc, ">"); | 390 --local tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, ">").."%s"..getstring(style_punc, "</")..getstring(style_tagname, "%s")..getstring(style_punc, ">"); |
392 local tag_format = top_tag_format.."%s"..getstring(style_punc, "</")..getstring(style_tagname, "%s")..getstring(style_punc, ">"); | 391 local tag_format = top_tag_format.."%s"..getstring(style_punc, "</")..getstring(style_tagname, "%s")..getstring(style_punc, ">"); |
393 function stanza_mt.pretty_print(t) | 392 function stanza_mt.pretty_print(t) |
394 local children_text = ""; | 393 local children_text = ""; |
395 for n, child in ipairs(t) do | 394 for _, child in ipairs(t) do |
396 if type(child) == "string" then | 395 if type(child) == "string" then |
397 children_text = children_text .. xml_escape(child); | 396 children_text = children_text .. xml_escape(child); |
398 else | 397 else |
399 children_text = children_text .. child:pretty_print(); | 398 children_text = children_text .. child:pretty_print(); |
400 end | 399 end |
420 stanza_mt.pretty_top_tag = stanza_mt.top_tag; | 419 stanza_mt.pretty_top_tag = stanza_mt.top_tag; |
421 end | 420 end |
422 | 421 |
423 return { | 422 return { |
424 stanza_mt = stanza_mt; | 423 stanza_mt = stanza_mt; |
425 stanza = stanza; | 424 stanza = new_stanza; |
426 new_id = new_id; | 425 new_id = new_id; |
427 preserialize = preserialize; | 426 preserialize = preserialize; |
428 deserialize = deserialize; | 427 deserialize = deserialize; |
429 clone = clone; | 428 clone = clone; |
430 message = message; | 429 message = message; |