# HG changeset patch # User Kim Alvefur # Date 1584986584 -3600 # Node ID 2c6d5734ae041a2d5e83f5c78bfcd9a2899a71aa # Parent 343dc9dd70dd83c04995d1743df052ad97b89867 mod_rest: Add JSON mapping of XEP-0128: Service Discovery Extensions Example XEP-0157 payload: { "disco" : { "extensions" : { "http://jabber.org/network/serverinfo" : { "abuse-addresses" : [ "mailto:abuse@shakespeare.lit", "xmpp:abuse@shakespeare.lit" ], "admin-addresses" : [ "mailto:admin@shakespeare.lit", "xmpp:admin@shakespeare.lit" ], "feedback-addresses" : [ "http://shakespeare.lit/feedback.php", "mailto:feedback@shakespeare.lit", "xmpp:feedback@shakespeare.lit" ], "sales-addresses" : [ "xmpp:bard@shakespeare.lit" ], "security-addresses" : [ "xmpp:security@shakespeare.lit" ], "support-addresses" : [ "http://shakespeare.lit/support.php", "xmpp:support@shakespeare.lit" ] } } } } diff -r 343dc9dd70dd -r 2c6d5734ae04 mod_rest/README.markdown --- a/mod_rest/README.markdown Sat Mar 21 18:05:22 2020 +0100 +++ b/mod_rest/README.markdown Mon Mar 23 19:03:04 2020 +0100 @@ -375,6 +375,11 @@ items list query. The response contain an array of items like `{"jid":"xmpp.address.here","name":"Description of item"}`. +`extensions` +: Map of extended feature discovery (see [XEP-0128]) data with + `FORM_DATA` fields as the keys pointing at maps with the rest of the + data. + #### Ad-Hoc Commands Used to execute arbitrary commands on supporting entities. diff -r 343dc9dd70dd -r 2c6d5734ae04 mod_rest/jsonmap.lib.lua --- 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 });