Mercurial > prosody-hg
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 |
| parents | 30c96a5db360 f4e71242556a |
| children | 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; |
