Merge with 0.5
[prosody.git] / util / stanza.lua
index eb9f392209d78b6ea60c53f95def5026645bbbec..4e833caad35d3f3e3bb771645035752b818bf08e 100644 (file)
@@ -1,4 +1,4 @@
--- Prosody IM v0.4
+-- Prosody IM
 -- Copyright (C) 2008-2009 Matthew Wild
 -- Copyright (C) 2008-2009 Waqas Hussain
 -- 
@@ -6,7 +6,6 @@
 -- COPYING file in the source package for more information.
 --
 
-
 local t_insert      =  table.insert;
 local t_concat      =  table.concat;
 local t_remove      =  table.remove;
@@ -24,16 +23,23 @@ local print         =         print;
 local unpack        =        unpack;
 local s_gsub        =   string.gsub;
 local s_char        =   string.char;
+local s_find        =   string.find;
 local os            =            os;
 
 local do_pretty_printing = not os.getenv("WINDIR");
-local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
-
-local log = require "util.logger".init("stanza");
+local getstyle, getstring;
+if do_pretty_printing then
+       local ok, termcolours = pcall(require, "util.termcolours");
+       if ok then
+               getstyle, getstring = termcolours.getstyle, termcolours.getstring;
+       else
+               do_pretty_printing = nil;
+       end
+end
 
 module "stanza"
 
-stanza_mt = {};
+stanza_mt = { __type = "stanza" };
 stanza_mt.__index = stanza_mt;
 
 function stanza(name, attr)
@@ -117,32 +123,41 @@ function stanza_mt:childtags()
                                            
 end
 
-local xml_escape = (function()
+local xml_escape
+do
        local escape_table = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
-       return function(str) return (s_gsub(str, "['&<>\"]", escape_table)); end
-end)();
+       function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end
+       _M.xml_escape = xml_escape;
+end
+
 local function _dostring(t, buf, self, xml_escape)
-       local nsid, ns, attrk = 0;
-       t_insert(buf, "<"..t.name);
+       local nsid = 0;
+       local name = t.name
+       t_insert(buf, "<"..name);
        for k, v in pairs(t.attr) do
-               ns, attrk = s_match(k, "^([^|]+)|(.+)$");
-               if ns then
+               if s_find(k, "|", 1, true) then
+                       local ns, attrk = s_match(k, "^([^|]+)|(.+)$");
                        nsid = nsid + 1;
                        t_insert(buf, " xmlns:ns"..nsid.."='"..xml_escape(ns).."' ".."ns"..nsid..":"..attrk.."='"..xml_escape(v).."'");
                else
                        t_insert(buf, " "..k.."='"..xml_escape(v).."'");
                end
        end
-       t_insert(buf, ">");
-       for n=1,#t do
-               local child = t[n];
-               if child.name then
-                       self(child, buf, self, xml_escape);
-               else
-                       t_insert(buf, xml_escape(child));
+       local len = #t;
+       if len == 0 then
+               t_insert(buf, "/>");
+       else
+               t_insert(buf, ">");
+               for n=1,len do
+                       local child = t[n];
+                       if child.name then
+                               self(child, buf, self, xml_escape);
+                       else
+                               t_insert(buf, xml_escape(child));
+                       end
                end
+               t_insert(buf, "</"..name..">");
        end
-       t_insert(buf, "</"..t.name..">");
 end
 function stanza_mt.__tostring(t)
        local buf = {};
@@ -170,11 +185,11 @@ end
 
 
 do
-        local id = 0;
-        function new_id()
-                id = id + 1;
-                return "lx"..id;
-        end
+       local id = 0;
+       function new_id()
+               id = id + 1;
+               return "lx"..id;
+       end
 end
 
 function preserialize(stanza)
@@ -219,21 +234,22 @@ function deserialize(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)
+       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)