comparison mod_post_msg/mod_post_msg.lua @ 231:b78009874ce5

mod_post_msg: add support for type, subject and body in application/x-www-form-urlencoded Falls back to old "tread everything as body" if Content-Type says text, or lack of "="
author Kim Alvefur <zash@zash.se>
date Sat, 31 Jul 2010 18:33:56 +0200
parents ac5289d5ac8c
children 8d4f3cd41f82
comparison
equal deleted inserted replaced
229:5689ffaf97df 231:b78009874ce5
11 local jid_prep = require "util.jid".prep; 11 local jid_prep = require "util.jid".prep;
12 local msg = require "util.stanza".message; 12 local msg = require "util.stanza".message;
13 local test_password = require "core.usermanager".test_password; 13 local test_password = require "core.usermanager".test_password;
14 local b64_decode = require "util.encodings".base64.decode; 14 local b64_decode = require "util.encodings".base64.decode;
15 local urldecode = require "net.http".urldecode; 15 local urldecode = require "net.http".urldecode;
16 local urlparams = --require "net.http".getQueryParams or whatever MattJ names it
17 function(s)
18 if not s:match("=") then return urldecode(s); end
19 local r = {}
20 s:gsub("([^=&]*)=([^&]*)", function(k,v)
21 r[ urldecode(k) ] = urldecode(v);
22 return nil
23 end)
24 return r
25 end;
16 26
17 local function http_response(code, message, extra_headers) 27 local function http_response(code, message, extra_headers)
18 local response = { 28 local response = {
19 status = code .. " " .. message; 29 status = code .. " " .. message;
20 body = message .. "\n"; } 30 body = message .. "\n"; }
21 if extra_headers then response.headers = extra_headers; end 31 if extra_headers then response.headers = extra_headers; end
22 return response 32 return response
23 end 33 end
24 34
25 local function handle_request(method, body, request) 35 local function handle_request(method, body, request)
26 if request.method ~= "POST" then return http_response(405, "Method Not Allowed"); end 36 if request.method == "BREW" then return http_response(418, "I'm a teapot"); end
37 if request.method ~= "POST" then
38 return http_response(405, "Method Not Allowed", {["Allow"] = "POST"}); end
27 39
28 -- message to? 40 -- message to?
29 local path_jid = request.url.path:match("[^/]+$"); 41 local path_jid = request.url.path:match("[^/]+$");
30 if not path_jid or not body then return http_response(400, "Bad Request"); end 42 if not path_jid or not body then return http_response(400, "Bad Request"); end
31 local to_user, to_host = jid_split(urldecode(path_jid)); 43 local to_user, to_host = jid_split(urldecode(path_jid));
41 if not request.headers["authorization"] then 53 if not request.headers["authorization"] then
42 return http_response(401, "Unauthorized", 54 return http_response(401, "Unauthorized",
43 {["WWW-Authenticate"]='Basic realm="WallyWorld"'}) 55 {["WWW-Authenticate"]='Basic realm="WallyWorld"'})
44 end 56 end
45 local from_jid, password = b64_decode(request.headers.authorization 57 local from_jid, password = b64_decode(request.headers.authorization
46 :gmatch("[^ ]*$")() or ""):gmatch("([^:]*):(.*)")(); 58 :match("[^ ]*$") or ""):match("([^:]*):(.*)");
47 from_jid = jid_prep(from_jid) 59 from_jid = jid_prep(from_jid)
48 if not from_jid or not password then return http_response(400, "Bad Request"); end 60 if not from_jid or not password then return http_response(400, "Bad Request"); end
49 local from_user, from_host = jid_split(from_jid) 61 local from_user, from_host = jid_split(from_jid)
50 if not hosts[from_host] then return http_response(401, "Unauthorized"); end 62 if not hosts[from_host] then return http_response(401, "Unauthorized"); end
51 63
52 -- auth 64 -- auth
53 module:log("debug", "testing authz %s", from_jid) 65 module:log("debug", "testing authz %s", from_jid)
54 if not test_password(from_user, from_host, password) then 66 if not test_password(from_user, from_host, password) then
55 return http_response(401, "Unauthorized"); end 67 return http_response(401, "Unauthorized")
68 end
56 69
70 -- parse body
71 local message = {}
72 local body_type = request.headers["content-type"]
73 if body_type == "text/plain" then
74 message = {["body"] = body}
75 elseif body_type == "application/x-www-form-urlencoded" then
76 message = urlparams(body)
77 if type(message) == "string" then
78 message = {["body"] = message}
79 end
80 else
81 return http_response(415, "Unsupported Media Type")
82 end
83
84 -- guess type if not set
85 if not message["type"] then
86 if message["body"] then
87 if message["subject"] then
88 message["type"] = "normal"
89 else
90 message["type"] = "chat"
91 end
92 elseif not message["body"] and message["subject"] then
93 message["type"] = "headline"
94 end
95 end
96
97 -- build stanza
98 local stanza = msg({["to"]=to_jid, ["from"]=from_jid, ["type"]=message["type"]})
99 if message["body"] then stanza:tag("body"):text(message["body"]):up(); end
100 if message["subject"] then stanza:tag("subject"):text(message["subject"]):up(); end
101
102 -- and finaly post it
57 module:log("debug", "message for %s", to_jid) 103 module:log("debug", "message for %s", to_jid)
58 core_post_stanza(hosts[module.host], msg({to=to_jid, from=from_jid, type="chat"}) 104 core_post_stanza(hosts[module.host], stanza)
59 :tag("body"):text(body))
60 return http_response(202, "Accepted") 105 return http_response(202, "Accepted")
61 end 106 end
62 107
63 local ports = config.get(module.host, "core", "post_msg_ports") or { 5280 }; 108 local ports = config.get(module.host, "core", "post_msg_ports") or { 5280 };
64 require "net.httpserver".new_from_config(ports, "msg", handle_request); 109 require "net.httpserver".new_from_config(ports, "msg", handle_request);