mod_rest/jsonmap.lib.lua
changeset 3957 2c6d5734ae04
parent 3936 8b34222216f4
child 4025 1925d63eec6b
--- a/mod_rest/jsonmap.lib.lua	Sat Mar 21 18:05:22 2020 +0100
+++ b/mod_rest/jsonmap.lib.lua	Mon Mar 23 19:03:04 2020 +0100
@@ -75,7 +75,7 @@
 	disco = {
 		type = "func", xmlns = "http://jabber.org/protocol/disco#info", tagname = "query",
 		st2json = function (s) --> array of features
-			local identities, features = array(), array();
+			local identities, features, extensions = array(), array(), {};
 			for tag in s:childtags() do
 				if tag.name == "identity" and tag.attr.category and tag.attr.type then
 					identities:push({ category = tag.attr.category, type = tag.attr.type, name = tag.attr.name });
@@ -83,7 +83,16 @@
 					features:push(tag.attr.var);
 				end
 			end
-			return { node = s.attr.node, identities = identities, features = features, };
+			for form in s:childtags("x", "jabber:x:data") do
+				local jform = field_mappings.formdata.st2json(form);
+				local form_type = jform["FORM_TYPE"];
+				if jform then
+					jform["FORM_TYPE"] = nil;
+					extensions[form_type] = jform;
+				end
+			end
+			if next(extensions) == nil then extensions = nil; end
+			return { node = s.attr.node, identities = identities, features = features, extensions = extensions };
 		end;
 		json2st = function (s)
 			if type(s) == "table" and s ~= json.null then
@@ -98,6 +107,12 @@
 						disco:tag("feature", { var = feature }):up();
 					end
 				end
+				if s.extensions then
+					for form_type, extension in pairs(s.extensions) do
+						extension["FORM_TYPE"] = form_type;
+						disco:add_child(field_mappings.formdata.json2st(extension));
+					end
+				end
 				return disco;
 			else
 				return st.stanza("query", { xmlns = "http://jabber.org/protocol/disco#info", });
@@ -324,10 +339,28 @@
 
 	-- Simpler mapping of dataform from JSON map
 	formdata = { type = "func", xmlns = "jabber:x:data", tagname = "",
-		st2json = function ()
-			-- Tricky to do in a generic way without each form layout
-			-- In the future, some well-known layouts might be understood
-			return nil, "not-implemented";
+		st2json = function (s)
+			local r = {};
+			for field in s:childtags("field") do
+				if field.attr.var then
+					local values = array();
+					for value in field:childtags("value") do
+						values:push(value:get_text());
+					end
+					if field.attr.type == "list-single" or field.attr.type == "list-multi" then
+						r[field.attr.var] = values;
+					elseif field.attr.type == "text-multi" then
+						r[field.attr.var] = values:concat("\n");
+					elseif field.attr.type == "boolean" then
+						r[field.attr.var] = values[1] == "1" or values[1] == "true";
+					elseif field.attr.type then
+						r[field.attr.var] = values[1] or json.null;
+					else -- type is optional, no way to know if multiple or single value is expected
+						r[field.attr.var] = values;
+					end
+				end
+			end
+			return r;
 		end,
 		json2st = function (s, t)
 			local form = st.stanza("x", { xmlns = "jabber:x:data", type = t });