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 = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" }; 201 local escape_table = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
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;