X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=util%2Fstanza.lua;h=526bb2f0f5c45e892fbfd886e2e0ee2ff83301fe;hb=a80f2d734aaf6cf54728a7d9e4a68335f91af8f9;hp=df0d43ff7f3ac163bf4a3f5f9b99a7ae0965a381;hpb=6d9f97378cd7d73cc22ac102e546c52799bb8615;p=prosody.git diff --git a/util/stanza.lua b/util/stanza.lua index df0d43ff..526bb2f0 100644 --- a/util/stanza.lua +++ b/util/stanza.lua @@ -1,16 +1,29 @@ +-- Prosody IM v0.4 +-- Copyright (C) 2008-2009 Matthew Wild +-- Copyright (C) 2008-2009 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + + local t_insert = table.insert; +local t_concat = table.concat; local t_remove = table.remove; +local t_concat = table.concat; local s_format = string.format; +local s_match = string.match; local tostring = tostring; local setmetatable = setmetatable; +local getmetatable = getmetatable; local pairs = pairs; local ipairs = ipairs; local type = type; local next = next; -local print = print; +local print = print; local unpack = unpack; local s_gsub = string.gsub; -local os = os; +local os = os; local do_pretty_printing = not os.getenv("WINDIR"); local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring; @@ -52,6 +65,14 @@ function stanza_mt:up() return self; end +function stanza_mt:reset() + local last_add = self.last_add; + for i = 1,#last_add do + last_add[i] = nil; + end + return self; +end + function stanza_mt:add_direct_child(child) if type(child) == "table" then t_insert(self.tags, child); @@ -65,11 +86,17 @@ function stanza_mt:add_child(child) end function stanza_mt:child_with_name(name) - for _, child in ipairs(self) do + for _, child in ipairs(self.tags) do if child.name == name then return child; end end end +function stanza_mt:child_with_ns(ns) + for _, child in ipairs(self.tags) do + if child.attr.xmlns == ns then return child; end + end +end + function stanza_mt:children() local i = 0; return function (a) @@ -96,23 +123,47 @@ end local xml_escape = xml_escape; -function stanza_mt.__tostring(t) - local children_text = ""; +local function dostring(t, buf, self, xml_escape) + local nsid, ns, attrk = 0; + t_insert(buf, "<"); + t_insert(buf, t.name); + for k, v in pairs(t.attr) do if type(k) == "string" then + t_insert(buf, " "); + ns, attrk = s_match(k, "^([^|]+)|(.+)$"); + if ns then + nsid = (nsid or -1) + 1; + t_insert(buf, "xmlns:ns"..nsid); + t_insert(buf, "='"); + t_insert(buf, (xml_escape(tostring(ns)))); + t_insert(buf, "' "); + t_insert(buf, "ns"..nsid..":"..attrk); + else + t_insert(buf, k); + end + t_insert(buf, "='"); + t_insert(buf, (xml_escape(tostring(v)))); + t_insert(buf, "'"); + end end + t_insert(buf, ">"); for n, child in ipairs(t) do - if type(child) == "string" then - children_text = children_text .. xml_escape(child); + if child.name then + self(child, buf, self, xml_escape); else - children_text = children_text .. tostring(child); + t_insert(buf, (xml_escape(child))); end end + t_insert(buf, ""); +end - local attr_string = ""; - if t.attr then - for k, v in pairs(t.attr) do if type(k) == "string" then attr_string = attr_string .. s_format(" %s='%s'", k, xml_escape(tostring(v))); end end - end - return s_format("<%s%s>%s", t.name, attr_string, children_text, t.name); +function stanza_mt.__tostring(t) + local buf = {}; + dostring(t, buf, dostring, xml_escape); + return t_concat(buf); end + function stanza_mt.top_tag(t) local attr_string = ""; if t.attr then @@ -164,12 +215,33 @@ function deserialize(stanza) end end stanza.tags = tags; + if not stanza.last_add then + stanza.last_add = {}; + end end end return stanza; end +function clone(stanza) + local lookup_table = {}; + local function _copy(object) + if type(object) ~= "table" then + return object; + elseif lookup_table[object] then + return lookup_table[object]; + end + local new_table = {}; + lookup_table[object] = new_table; + for index, value in pairs(object) do + new_table[_copy(index)] = _copy(value); + end + return setmetatable(new_table, getmetatable(object)); + end + return _copy(stanza) +end + function message(attr, body) if not body then return stanza("message", attr); @@ -186,10 +258,9 @@ function reply(orig) 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) }); end -function error_reply(orig, type, condition, message, clone) +function error_reply(orig, type, condition, message) local t = reply(orig); t.attr.type = "error"; - -- TODO use clone t:tag("error", {type = type}) :tag(condition, {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):up(); if (message) then t:tag("text"):text(message):up(); end