Software /
code /
prosody
File
util/xmlrpc.lua @ 2511:a81c710b1708
prosodyctl: Don't display message about failing to start Prosody is daemonizing is disabled (if daemonizing is disabled then Prosody is stopped by the time control returns to prosodyctl, which then can't see Prosody running)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Thu, 28 Jan 2010 15:05:30 +0000 |
parent | 1554:06030af44fad |
child | 2923:b7049746bd29 |
line wrap: on
line source
-- Prosody IM -- 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 pairs = pairs; local type = type; local error = error; local t_concat = table.concat; local t_insert = table.insert; local tostring = tostring; local tonumber = tonumber; local select = select; local st = require "util.stanza"; module "xmlrpc" local _lua_to_xmlrpc; local map = { table=function(stanza, object) stanza:tag("struct"); for name, value in pairs(object) do stanza:tag("member"); stanza:tag("name"):text(tostring(name)):up(); stanza:tag("value"); _lua_to_xmlrpc(stanza, value); stanza:up(); stanza:up(); end stanza:up(); end; boolean=function(stanza, object) stanza:tag("boolean"):text(object and "1" or "0"):up(); end; string=function(stanza, object) stanza:tag("string"):text(object):up(); end; number=function(stanza, object) stanza:tag("int"):text(tostring(object)):up(); end; ["nil"]=function(stanza, object) -- nil extension stanza:tag("nil"):up(); end; }; _lua_to_xmlrpc = function(stanza, object) local h = map[type(object)]; if h then h(stanza, object); else error("Type not supported by XML-RPC: " .. type(object)); end end function create_response(object) local stanza = st.stanza("methodResponse"):tag("params"):tag("param"):tag("value"); _lua_to_xmlrpc(stanza, object); stanza:up():up():up(); return stanza; end function create_error_response(faultCode, faultString) local stanza = st.stanza("methodResponse"):tag("fault"):tag("value"); _lua_to_xmlrpc(stanza, {faultCode=faultCode, faultString=faultString}); stanza:up():up(); return stanza; end function create_request(method_name, ...) local stanza = st.stanza("methodCall") :tag("methodName"):text(method_name):up() :tag("params"); for i=1,select('#', ...) do stanza:tag("param"):tag("value"); _lua_to_xmlrpc(stanza, select(i, ...)); stanza:up():up(); end stanza:up():up():up(); return stanza; end local _xmlrpc_to_lua; local int_parse = function(stanza) if #stanza.tags ~= 0 or #stanza == 0 then error("<"..stanza.name.."> must have a single text child"); end local n = tonumber(t_concat(stanza)); if n then return n; end error("Failed to parse content of <"..stanza.name..">"); end local rmap = { methodCall=function(stanza) if #stanza.tags ~= 2 then error("<methodCall> must have exactly two subtags"); end -- FIXME <params> is optional if stanza.tags[1].name ~= "methodName" then error("First <methodCall> child tag must be <methodName>") end if stanza.tags[2].name ~= "params" then error("Second <methodCall> child tag must be <params>") end return _xmlrpc_to_lua(stanza.tags[1]), _xmlrpc_to_lua(stanza.tags[2]); end; methodName=function(stanza) if #stanza.tags ~= 0 then error("<methodName> must not have any subtags"); end if #stanza == 0 then error("<methodName> must have text content"); end return t_concat(stanza); end; params=function(stanza) local t = {}; for _, child in pairs(stanza.tags) do if child.name ~= "param" then error("<params> can only have <param> children"); end; t_insert(t, _xmlrpc_to_lua(child)); end return t; end; param=function(stanza) if not(#stanza.tags == 1 and stanza.tags[1].name == "value") then error("<param> must have exactly one <value> child"); end return _xmlrpc_to_lua(stanza.tags[1]); end; value=function(stanza) if #stanza.tags == 0 then return t_concat(stanza); end if #stanza.tags ~= 1 then error("<value> must have a single child"); end return _xmlrpc_to_lua(stanza.tags[1]); end; int=int_parse; i4=int_parse; double=int_parse; boolean=function(stanza) if #stanza.tags ~= 0 or #stanza == 0 then error("<boolean> must have a single text child"); end local b = t_concat(stanza); if b ~= "1" and b ~= "0" then error("Failed to parse content of <boolean>"); end return b == "1" and true or false; end; string=function(stanza) if #stanza.tags ~= 0 then error("<string> must have a single text child"); end return t_concat(stanza); end; array=function(stanza) if #stanza.tags ~= 1 then error("<array> must have a single <data> child"); end return _xmlrpc_to_lua(stanza.tags[1]); end; data=function(stanza) local t = {}; for _,child in pairs(stanza.tags) do if child.name ~= "value" then error("<data> can only have <value> children"); end t_insert(t, _xmlrpc_to_lua(child)); end return t; end; struct=function(stanza) local t = {}; for _,child in pairs(stanza.tags) do if child.name ~= "member" then error("<struct> can only have <member> children"); end local name, value = _xmlrpc_to_lua(child); t[name] = value; end return t; end; member=function(stanza) if #stanza.tags ~= 2 then error("<member> must have exactly two subtags"); end -- FIXME <params> is optional if stanza.tags[1].name ~= "name" then error("First <member> child tag must be <name>") end if stanza.tags[2].name ~= "value" then error("Second <member> child tag must be <value>") end return _xmlrpc_to_lua(stanza.tags[1]), _xmlrpc_to_lua(stanza.tags[2]); end; name=function(stanza) if #stanza.tags ~= 0 then error("<name> must have a single text child"); end local n = t_concat(stanza) if tostring(tonumber(n)) == n then n = tonumber(n); end return n; end; ["nil"]=function(stanza) -- nil extension return nil; end; } _xmlrpc_to_lua = function(stanza) local h = rmap[stanza.name]; if h then return h(stanza); else error("Unknown element: "..stanza.name); end end function translate_request(stanza) if stanza.name ~= "methodCall" then error("XML-RPC requests must have <methodCall> as root element"); end return _xmlrpc_to_lua(stanza); end return _M;