33 end |
33 end |
34 end |
34 end |
35 |
35 |
36 local xmlns_stanzas = "urn:ietf:params:xml:ns:xmpp-stanzas"; |
36 local xmlns_stanzas = "urn:ietf:params:xml:ns:xmpp-stanzas"; |
37 |
37 |
38 module "stanza" |
38 local _ENV = nil; |
39 |
39 |
40 stanza_mt = { __type = "stanza" }; |
40 local stanza_mt = { __type = "stanza" }; |
41 stanza_mt.__index = stanza_mt; |
41 stanza_mt.__index = stanza_mt; |
42 local stanza_mt = stanza_mt; |
42 |
43 |
43 local function stanza(name, attr) |
44 function stanza(name, attr) |
|
45 local stanza = { name = name, attr = attr or {}, tags = {} }; |
44 local stanza = { name = name, attr = attr or {}, tags = {} }; |
46 return setmetatable(stanza, stanza_mt); |
45 return setmetatable(stanza, stanza_mt); |
47 end |
46 end |
48 local stanza = stanza; |
47 local stanza = stanza; |
49 |
48 |
198 self = self:get_child(name, xmlns); |
197 self = self:get_child(name, xmlns); |
199 until not self |
198 until not self |
200 end |
199 end |
201 |
200 |
202 |
201 |
203 local xml_escape |
202 local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; |
204 do |
203 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end |
205 local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; |
|
206 function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end |
|
207 _M.xml_escape = xml_escape; |
|
208 end |
|
209 |
204 |
210 local function _dostring(t, buf, self, xml_escape, parentns) |
205 local function _dostring(t, buf, self, xml_escape, parentns) |
211 local nsid = 0; |
206 local nsid = 0; |
212 local name = t.name |
207 local name = t.name |
213 t_insert(buf, "<"..name); |
208 t_insert(buf, "<"..name); |
278 end |
273 end |
279 end |
274 end |
280 return type, condition or "undefined-condition", text; |
275 return type, condition or "undefined-condition", text; |
281 end |
276 end |
282 |
277 |
283 do |
278 local id = 0; |
284 local id = 0; |
279 local function new_id() |
285 function new_id() |
280 id = id + 1; |
286 id = id + 1; |
281 return "lx"..id; |
287 return "lx"..id; |
282 end |
288 end |
283 |
289 end |
284 local function preserialize(stanza) |
290 |
|
291 function preserialize(stanza) |
|
292 local s = { name = stanza.name, attr = stanza.attr }; |
285 local s = { name = stanza.name, attr = stanza.attr }; |
293 for _, child in ipairs(stanza) do |
286 for _, child in ipairs(stanza) do |
294 if type(child) == "table" then |
287 if type(child) == "table" then |
295 t_insert(s, preserialize(child)); |
288 t_insert(s, preserialize(child)); |
296 else |
289 else |
335 end |
328 end |
336 |
329 |
337 return stanza; |
330 return stanza; |
338 end |
331 end |
339 |
332 |
340 local function _clone(stanza) |
333 local function clone(stanza) |
341 local attr, tags = {}, {}; |
334 local attr, tags = {}, {}; |
342 for k,v in pairs(stanza.attr) do attr[k] = v; end |
335 for k,v in pairs(stanza.attr) do attr[k] = v; end |
343 local new = { name = stanza.name, attr = attr, tags = tags }; |
336 local new = { name = stanza.name, attr = attr, tags = tags }; |
344 for i=1,#stanza do |
337 for i=1,#stanza do |
345 local child = stanza[i]; |
338 local child = stanza[i]; |
346 if child.name then |
339 if child.name then |
347 child = _clone(child); |
340 child = clone(child); |
348 t_insert(tags, child); |
341 t_insert(tags, child); |
349 end |
342 end |
350 t_insert(new, child); |
343 t_insert(new, child); |
351 end |
344 end |
352 return setmetatable(new, stanza_mt); |
345 return setmetatable(new, stanza_mt); |
353 end |
346 end |
354 clone = _clone; |
347 |
355 |
348 local function message(attr, body) |
356 function message(attr, body) |
|
357 if not body then |
349 if not body then |
358 return stanza("message", attr); |
350 return stanza("message", attr); |
359 else |
351 else |
360 return stanza("message", attr):tag("body"):text(body):up(); |
352 return stanza("message", attr):tag("body"):text(body):up(); |
361 end |
353 end |
362 end |
354 end |
363 function iq(attr) |
355 local function iq(attr) |
364 if attr and not attr.id then attr.id = new_id(); end |
356 if attr and not attr.id then attr.id = new_id(); end |
365 return stanza("iq", attr or { id = new_id() }); |
357 return stanza("iq", attr or { id = new_id() }); |
366 end |
358 end |
367 |
359 |
368 function reply(orig) |
360 local function reply(orig) |
369 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) }); |
361 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) }); |
370 end |
362 end |
371 |
363 |
372 do |
364 local xmpp_stanzas_attr = { xmlns = xmlns_stanzas }; |
373 local xmpp_stanzas_attr = { xmlns = xmlns_stanzas }; |
365 local function error_reply(orig, type, condition, message) |
374 function error_reply(orig, type, condition, message) |
366 local t = reply(orig); |
375 local t = reply(orig); |
367 t.attr.type = "error"; |
376 t.attr.type = "error"; |
368 t:tag("error", {type = type}) --COMPAT: Some day xmlns:stanzas goes here |
377 t:tag("error", {type = type}) --COMPAT: Some day xmlns:stanzas goes here |
369 :tag(condition, xmpp_stanzas_attr):up(); |
378 :tag(condition, xmpp_stanzas_attr):up(); |
370 if (message) then t:tag("text", xmpp_stanzas_attr):text(message):up(); end |
379 if (message) then t:tag("text", xmpp_stanzas_attr):text(message):up(); end |
371 return t; -- stanza ready for adding app-specific errors |
380 return t; -- stanza ready for adding app-specific errors |
372 end |
381 end |
373 |
382 end |
374 local function presence(attr) |
383 |
|
384 function presence(attr) |
|
385 return stanza("presence", attr); |
375 return stanza("presence", attr); |
386 end |
376 end |
387 |
377 |
388 if do_pretty_printing then |
378 if do_pretty_printing then |
389 local style_attrk = getstyle("yellow"); |
379 local style_attrk = getstyle("yellow"); |