Software / code / prosody
Comparison
util/xmlrpc.lua @ 874:a554bf5057a0
Added util/xmlrpc.lua - functions for converting between XML-RPC stanzas and Lua objects
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Wed, 04 Mar 2009 22:10:27 +0500 |
| child | 888:1059230969c3 |
comparison
equal
deleted
inserted
replaced
| 872:24018ba2f7c0 | 874:a554bf5057a0 |
|---|---|
| 1 -- Prosody IM v0.3 | |
| 2 -- Copyright (C) 2008-2009 Matthew Wild | |
| 3 -- Copyright (C) 2008-2009 Waqas Hussain | |
| 4 -- | |
| 5 -- This project is MIT/X11 licensed. Please see the | |
| 6 -- COPYING file in the source package for more information. | |
| 7 -- | |
| 8 | |
| 9 | |
| 10 local pairs = pairs; | |
| 11 local type = type; | |
| 12 local error = error; | |
| 13 local t_concat = table.concat; | |
| 14 local t_insert = table.insert; | |
| 15 local tostring = tostring; | |
| 16 local tonumber = tonumber; | |
| 17 local st = require "util.stanza"; | |
| 18 | |
| 19 module "xmlrpc" | |
| 20 | |
| 21 local _lua_to_xmlrpc; | |
| 22 local map = { | |
| 23 table=function(stanza, object) | |
| 24 stanza:tag("struct"); | |
| 25 for name, value in pairs(object) do | |
| 26 stanza:tag("member"); | |
| 27 stanza:tag("name"):text(tostring(name)):up(); | |
| 28 stanza:tag("value"); | |
| 29 _lua_to_xmlrpc(stanza, value); | |
| 30 stanza:up(); | |
| 31 stanza:up(); | |
| 32 end | |
| 33 stanza:up(); | |
| 34 end; | |
| 35 boolean=function(stanza, object) | |
| 36 stanza:tag("boolean"):text(object and "1" or "0"):up(); | |
| 37 end; | |
| 38 string=function(stanza, object) | |
| 39 stanza:tag("string"):text(object):up(); | |
| 40 end; | |
| 41 number=function(stanza, object) | |
| 42 stanza:tag("int"):text(tostring(object)):up(); | |
| 43 end; | |
| 44 }; | |
| 45 _lua_to_xmlrpc = function(stanza, object) | |
| 46 local h = map[type(object)]; | |
| 47 if h then | |
| 48 h(stanza, object); | |
| 49 else | |
| 50 error("Type not supported by XML-RPC: " .. type(object)); | |
| 51 end | |
| 52 end | |
| 53 function create_response(object) | |
| 54 local stanza = st.stanza("methodResponse"):tag("params"):tag("param"):tag("value"); | |
| 55 _lua_to_xmlrpc(stanza, object); | |
| 56 stanza:up():up():up(); | |
| 57 return stanza; | |
| 58 end | |
| 59 function create_error_response(faultCode, faultString) | |
| 60 local stanza = st.stanza("methodResponse"):tag("fault"):tag("value"); | |
| 61 _lua_to_xmlrpc(stanza, {faultCode=faultCode, faultString=faultString}); | |
| 62 stanza:up():up(); | |
| 63 return stanza; | |
| 64 end | |
| 65 | |
| 66 | |
| 67 local _xmlrpc_to_lua; | |
| 68 local int_parse = function(stanza) | |
| 69 if #stanza.tags ~= 0 or #stanza == 0 then error("<"..stanza.name.."> must have a single text child"); end | |
| 70 local n = tonumber(t_concat(stanza)); | |
| 71 if n then return n; end | |
| 72 error("Failed to parse content of <"..stanza.name..">"); | |
| 73 end | |
| 74 local rmap = { | |
| 75 methodCall=function(stanza) | |
| 76 if #stanza.tags ~= 2 then error("<methodCall> must have exactly two subtags"); end -- FIXME <params> is optional | |
| 77 if stanza.tags[1].name ~= "methodName" then error("First <methodCall> child tag must be <methodName>") end | |
| 78 if stanza.tags[2].name ~= "params" then error("Second <methodCall> child tag must be <params>") end | |
| 79 return _xmlrpc_to_lua(stanza.tags[1]), _xmlrpc_to_lua(stanza.tags[2]); | |
| 80 end; | |
| 81 methodName=function(stanza) | |
| 82 if #stanza.tags ~= 0 then error("<methodName> must not have any subtags"); end | |
| 83 if #stanza == 0 then error("<methodName> must have text content"); end | |
| 84 return t_concat(stanza); | |
| 85 end; | |
| 86 params=function(stanza) | |
| 87 local t = {}; | |
| 88 for _, child in pairs(stanza.tags) do | |
| 89 if child.name ~= "param" then error("<params> can only have <param> children"); end; | |
| 90 t_insert(t, _xmlrpc_to_lua(child)); | |
| 91 end | |
| 92 return t; | |
| 93 end; | |
| 94 param=function(stanza) | |
| 95 if not(#stanza.tags == 1 and stanza.tags[1].name == "value") then error("<param> must have exactly one <value> child"); end | |
| 96 return _xmlrpc_to_lua(stanza.tags[1]); | |
| 97 end; | |
| 98 value=function(stanza) | |
| 99 if #stanza.tags == 0 then return t_concat(stanza); end | |
| 100 if #stanza.tags ~= 1 then error("<value> must have a single child"); end | |
| 101 return _xmlrpc_to_lua(stanza.tags[1]); | |
| 102 end; | |
| 103 int=int_parse; | |
| 104 i4=int_parse; | |
| 105 double=int_parse; | |
| 106 boolean=function(stanza) | |
| 107 if #stanza.tags ~= 0 or #stanza == 0 then error("<boolean> must have a single text child"); end | |
| 108 local b = t_concat(stanza); | |
| 109 if b ~= "1" and b ~= "0" then error("Failed to parse content of <boolean>"); end | |
| 110 return b == "1" and true or false; | |
| 111 end; | |
| 112 string=function(stanza) | |
| 113 if #stanza.tags ~= 0 then error("<string> must have a single text child"); end | |
| 114 return t_concat(stanza); | |
| 115 end; | |
| 116 array=function(stanza) | |
| 117 if #stanza.tags ~= 1 then error("<array> must have a single <data> child"); end | |
| 118 return _xmlrpc_to_lua(stanza.tags[1]); | |
| 119 end; | |
| 120 data=function(stanza) | |
| 121 local t = {}; | |
| 122 for _,child in pairs(stanza.tags) do | |
| 123 if child.name ~= "value" then error("<data> can only have <value> children"); end | |
| 124 t_insert(t, _xmlrpc_to_lua(child)); | |
| 125 end | |
| 126 return t; | |
| 127 end; | |
| 128 struct=function(stanza) | |
| 129 local t = {}; | |
| 130 for _,child in pairs(stanza.tags) do | |
| 131 if child.name ~= "member" then error("<struct> can only have <member> children"); end | |
| 132 local name, value = _xmlrpc_to_lua(child); | |
| 133 t[name] = value; | |
| 134 end | |
| 135 return t; | |
| 136 end; | |
| 137 member=function(stanza) | |
| 138 if #stanza.tags ~= 2 then error("<member> must have exactly two subtags"); end -- FIXME <params> is optional | |
| 139 if stanza.tags[1].name ~= "name" then error("First <member> child tag must be <name>") end | |
| 140 if stanza.tags[2].name ~= "value" then error("Second <member> child tag must be <value>") end | |
| 141 return _xmlrpc_to_lua(stanza.tags[1]), _xmlrpc_to_lua(stanza.tags[2]); | |
| 142 end; | |
| 143 name=function(stanza) | |
| 144 if #stanza.tags ~= 0 then error("<name> must have a single text child"); end | |
| 145 local n = t_concat(stanza) | |
| 146 if tostring(tonumber(n)) == n then n = tonumber(n); end | |
| 147 return n; | |
| 148 end; | |
| 149 } | |
| 150 _xmlrpc_to_lua = function(stanza) | |
| 151 local h = rmap[stanza.name]; | |
| 152 if h then | |
| 153 return h(stanza); | |
| 154 else | |
| 155 error("Unknown element: "..stanza.name); | |
| 156 end | |
| 157 end | |
| 158 function translate_request(stanza) | |
| 159 if stanza.name ~= "methodCall" then error("XML-RPC requests must have <methodCall> as root element"); end | |
| 160 return _xmlrpc_to_lua(stanza); | |
| 161 end | |
| 162 | |
| 163 return _M; |