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); |