aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2015-12-08 23:15:42 +0000
committerMatthew Wild <mwild1@gmail.com>2015-12-08 23:15:42 +0000
commitdd37beeff9f229dee36da04d625d5200b69f945c (patch)
tree92b42e2b3bb371b3273c61157e86d553f20700a6
parentbb0ad8d2a9da64ab00fa01b047031e8256554e89 (diff)
downloadprosody-dd37beeff9f229dee36da04d625d5200b69f945c.tar.gz
prosody-dd37beeff9f229dee36da04d625d5200b69f945c.zip
util.stanza, util.xml, util.xmppstream: Add support for tracking defined namespaces and their prefix (stanza.namespaces), knowing/preserving prefix names is required for some applications (thanks daurnimator)
-rw-r--r--util/stanza.lua15
-rw-r--r--util/xml.lua17
-rw-r--r--util/xmppstream.lua23
3 files changed, 49 insertions, 6 deletions
diff --git a/util/stanza.lua b/util/stanza.lua
index 90422a06..c682f833 100644
--- a/util/stanza.lua
+++ b/util/stanza.lua
@@ -40,8 +40,8 @@ local _ENV = nil;
local stanza_mt = { __type = "stanza" };
stanza_mt.__index = stanza_mt;
-local function stanza(name, attr)
- local stanza = { name = name, attr = attr or {}, tags = {} };
+local function stanza(name, attr, namespaces)
+ local stanza = { name = name, attr = attr or {}, namespaces = namespaces, tags = {} };
return setmetatable(stanza, stanza_mt);
end
local stanza = stanza;
@@ -54,8 +54,8 @@ function stanza_mt:body(text, attr)
return self:tag("body", attr):text(text);
end
-function stanza_mt:tag(name, attrs)
- local s = stanza(name, attrs);
+function stanza_mt:tag(name, attr, namespaces)
+ local s = stanza(name, attr, namespaces);
local last_add = self.last_add;
if not last_add then last_add = {}; self.last_add = last_add; end
(last_add[#last_add] or self):add_direct_child(s);
@@ -333,7 +333,12 @@ end
local function clone(stanza)
local attr, tags = {}, {};
for k,v in pairs(stanza.attr) do attr[k] = v; end
- local new = { name = stanza.name, attr = attr, tags = tags };
+ local old_namespaces, namespaces = stanza.namespaces;
+ if old_namespaces then
+ namespaces = {};
+ for k,v in pairs(old_namespaces) do namespaces[k] = v; end
+ end
+ local new = { name = stanza.name, attr = attr, namespaces = namespaces, tags = tags };
for i=1,#stanza do
local child = stanza[i];
if child.name then
diff --git a/util/xml.lua b/util/xml.lua
index 733d821a..9e12f0df 100644
--- a/util/xml.lua
+++ b/util/xml.lua
@@ -14,6 +14,17 @@ local parse_xml = (function()
--luacheck: ignore 212/self
local handler = {};
local stanza = st.stanza("root");
+ local namespaces = {}
+ function handler:StartNamespaceDecl(prefix, url)
+ if prefix ~= nil then
+ namespaces[prefix] = url
+ end
+ end
+ function handler:EndNamespaceDecl(prefix)
+ if prefix ~= nil then
+ namespaces[prefix] = nil
+ end
+ end
function handler:StartElement(tagname, attr)
local curr_ns,name = tagname:match(ns_pattern);
if name == "" then
@@ -34,7 +45,11 @@ local parse_xml = (function()
end
end
end
- stanza:tag(name, attr);
+ local n = {}
+ for prefix, url in pairs(namespaces) do
+ n[prefix] = url
+ end
+ stanza:tag(name, attr, n);
end
function handler:CharacterData(data)
stanza:text(data);
diff --git a/util/xmppstream.lua b/util/xmppstream.lua
index 7be63285..3d97acef 100644
--- a/util/xmppstream.lua
+++ b/util/xmppstream.lua
@@ -196,6 +196,29 @@ local function new_sax_handlers(session, stream_callbacks, cb_handleprogress)
end
end
+ if stream_callbacks.track_namespaces then
+ local namespaces = {}
+ function xml_handlers:StartNamespaceDecl(prefix, url)
+ if prefix ~= nil then
+ namespaces[prefix] = url
+ end
+ end
+ function xml_handlers:EndNamespaceDecl(prefix)
+ if prefix ~= nil then
+ namespaces[prefix] = nil
+ end
+ end
+ local old_startelement = xml_handlers.StartElement
+ function xml_handlers:StartElement(tagname, attr)
+ old_startelement(self, tagname, attr)
+ local n = {}
+ for prefix, url in pairs(namespaces) do
+ n[prefix] = url
+ end
+ stanza.namespaces = n
+ end
+ end
+
local function restricted_handler(parser)
cb_error(session, "parse-error", "restricted-xml", "Restricted XML, see RFC 6120 section 11.1.");
if not parser.stop or not parser:stop() then