plugins/mod_xmlrpc.lua

changeset 892
2128891180b7
parent 889
bb959588bbc4
child 894
2c0b9e3c11c3
equal deleted inserted replaced
891:236d1ce9fa99 892:2128891180b7
12 local httpserver = require "net.httpserver"; 12 local httpserver = require "net.httpserver";
13 local st = require "util.stanza"; 13 local st = require "util.stanza";
14 local pcall = pcall; 14 local pcall = pcall;
15 local unpack = unpack; 15 local unpack = unpack;
16 local tostring = tostring; 16 local tostring = tostring;
17 local is_admin = require "core.usermanager".is_admin;
18 local jid_split = require "util.jid".split;
19 local b64_decode = require "util.encodings".base64.decode;
20 local get_method = require "core.objectmanager".get_object;
21 local validate_credentials = require "core.usermanager".validate_credentials;
17 22
18 local translate_request = require "util.xmlrpc".translate_request; 23 local translate_request = require "util.xmlrpc".translate_request;
19 local create_response = require "util.xmlrpc".create_response; 24 local create_response = require "util.xmlrpc".create_response;
20 local create_error_response = require "util.xmlrpc".create_error_response; 25 local create_error_response = require "util.xmlrpc".create_error_response;
21 26
58 end 63 end
59 end 64 end
60 return stanza.tags[1]; 65 return stanza.tags[1];
61 end 66 end
62 67
63 --[[local function get_method(method)
64 return function(...)
65 return {method = method; args = {...}};
66 end
67 end]]
68 local get_method = require "core.objectmanager".get_object;
69
70 local function handle_xmlrpc_request(method, args) 68 local function handle_xmlrpc_request(method, args)
71 method = get_method(method); 69 method = get_method(method);
72 if not method then return create_error_response(404, "method not found"); end 70 if not method then return create_error_response(404, "method not found"); end
73 args = args or {}; 71 args = args or {};
74 local success, result = pcall(method, unpack(args)); 72 local success, result = pcall(method, unpack(args));
84 82
85 local function handle_xmpp_request(origin, stanza) 83 local function handle_xmpp_request(origin, stanza)
86 local query = stanza.tags[1]; 84 local query = stanza.tags[1];
87 if query.name == "query" then 85 if query.name == "query" then
88 if #query.tags == 1 then 86 if #query.tags == 1 then
89 local success, method, args = pcall(translate_request, query.tags[1]); 87 if is_admin(stanza.attr.from) then
90 if success then 88 local success, method, args = pcall(translate_request, query.tags[1]);
91 local result = handle_xmlrpc_request(method, args); 89 if success then
92 origin.send(st.reply(stanza):tag('query', {xmlns='jabber:iq:rpc'}):add_child(result)); 90 local result = handle_xmlrpc_request(method, args);
93 else 91 origin.send(st.reply(stanza):tag('query', {xmlns='jabber:iq:rpc'}):add_child(result));
94 origin.send(st.error_reply(stanza, "modify", "bad-request", method)); 92 else
95 end 93 origin.send(st.error_reply(stanza, "modify", "bad-request", method));
96 else 94 end
97 origin.send(st.error_reply(stanza, "modify", "bad-request", "No content in XML-RPC request")); 95 else origin.send(st.error_reply(stanza, "auth", "forbidden", "No content in XML-RPC request")); end
98 end 96 else origin.send(st.error_reply(stanza, "modify", "bad-request", "No content in XML-RPC request")); end
99 else 97 else origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); end
100 origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
101 end
102 end 98 end
103 module:add_iq_handler({"c2s", "s2sin"}, "jabber:iq:rpc", handle_xmpp_request); 99 module:add_iq_handler({"c2s", "s2sin"}, "jabber:iq:rpc", handle_xmpp_request);
104 module:add_feature("jabber:iq:rpc"); 100 module:add_feature("jabber:iq:rpc");
101 -- TODO add <identity category='automation' type='rpc'/> to disco replies
105 102
106 local default_headers = { ["Content-Type"] = "text/xml" }; 103 local default_headers = { ['Content-Type'] = 'text/xml' };
104 local unauthorized_response = { status = '401 UNAUTHORIZED', headers = {['Content-Type']='text/html', ['WWW-Authenticate']='Basic realm="WallyWorld"'}; body = "<html><body>Authentication required</body></html>"; };
107 local function handle_http_request(method, body, request) 105 local function handle_http_request(method, body, request)
106 -- authenticate user
107 local username, password = b64_decode(request['authorization'] or ''):gmatch('([^:]*):(.*)')(); -- TODO digest auth
108 local node, host = jid_split(username);
109 if not validate_credentials(host, node, password) and is_admin(username) then
110 return unauthorized_response;
111 end
112 -- parse request
108 local stanza = body and parse_xml(body); 113 local stanza = body and parse_xml(body);
109 if (not stanza) or request.method ~= "POST" then 114 if (not stanza) or request.method ~= "POST" then
110 return "<html><body>You really don't look like an XML-RPC client to me... what do you want?</body></html>"; 115 return "<html><body>You really don't look like an XML-RPC client to me... what do you want?</body></html>";
111 end 116 end
117 -- execute request
112 local success, method, args = pcall(translate_request, stanza); 118 local success, method, args = pcall(translate_request, stanza);
113 if success then 119 if success then
114 return { headers = default_headers; body = tostring(handle_xmlrpc_request(method, args)) }; 120 return { headers = default_headers; body = tostring(handle_xmlrpc_request(method, args)) };
115 end 121 end
116 return "<html><body>Error parsing XML-RPC request: "..tostring(method).."</body></html>"; 122 return "<html><body>Error parsing XML-RPC request: "..tostring(method).."</body></html>";

mercurial