mod_post_msg/mod_post_msg.lua
changeset 231 b78009874ce5
parent 216 ac5289d5ac8c
child 320 8d4f3cd41f82
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);