Skip to content

Instantly share code, notes, and snippets.

@zeen
Created January 18, 2011 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save zeen/784623 to your computer and use it in GitHub Desktop.
Save zeen/784623 to your computer and use it in GitHub Desktop.
-- Recive a HTTP POST and relay it
-- Author: Waqas Hussain
-- Derived from mod_post_msg by Kim Alvefur <zash@zash.se>
-- Some code borrowed from mod_webpresence
--
-- Example usage:
-- curl http://example.com:5280/presence/user -d "Hello there"
-- or
-- curl http://example.com:5280/presence/user@example.com -d "Hello there"
-- This would set presence of user@example.com with status 'Hello there'
-- another example:
-- curl http://example.com:5280/presence/user@example.com -d "status=Something&show=away&priority=20"
local jid_split = require "util.jid".split;
local jid_prep = require "util.jid".prep;
local msg = require "util.stanza".message;
local st = require "util.stanza";
local test_password = require "core.usermanager".test_password;
local b64_decode = require "util.encodings".base64.decode;
local urldecode = require "net.http".urldecode;
local urlparams = --require "net.http".getQueryParams or whatever MattJ names it
function(s)
if not s:match("=") then return urldecode(s); end
local r = {}
s:gsub("([^=&]*)=([^&]*)", function(k,v)
r[ urldecode(k) ] = urldecode(v);
return nil
end)
return r
end;
local function http_response(code, message, extra_headers)
local response = {
status = code .. " " .. message;
body = message .. "\n"; }
if extra_headers then response.headers = extra_headers; end
return response
end
local function handle_request(method, body, request)
if request.method == "BREW" then return http_response(418, "I'm a teapot"); end
if request.method ~= "POST" then
return http_response(405, "Method Not Allowed", {["Allow"] = "POST"}); end
-- message to?
local path_jid = request.url.path:match("[^/]+$");
if not path_jid or not body then return http_response(400, "Bad Request"); end
local to_user, to_host = jid_split(urldecode(path_jid));
if to_host and not to_user and request.headers.host then
to_user, to_host = to_host, request.headers.host;
if to_host then to_host = to_host:gsub(":%d+$", ""); end
end
if not to_host or not to_user then return http_response(400, "Bad Request"); end
local to_jid = jid_prep(to_user .. "@" .. to_host)
if not to_jid then return http_response(400, "Bad Request"); end
--[[-- message from?
if not request.headers["authorization"] then
return http_response(401, "Unauthorized",
{["WWW-Authenticate"]='Basic realm="WallyWorld"'})
end
local from_jid, password = b64_decode(request.headers.authorization
:match("[^ ]*$") or ""):match("([^:]*):(.*)");
from_jid = jid_prep(from_jid)
if not from_jid or not password then return http_response(400, "Bad Request"); end
local from_user, from_host = jid_split(from_jid)
if not hosts[from_host] then return http_response(401, "Unauthorized"); end
-- auth
module:log("debug", "testing authz %s", from_jid)
if not test_password(from_user, from_host, password) then
return http_response(401, "Unauthorized")
end]]
-- parse body
local message = {}
local body_type = request.headers["content-type"]
if body_type == "text/plain" then
message = {["status"] = body}
elseif body_type == "application/x-www-form-urlencoded" then
message = urlparams(body)
if type(message) == "string" then
message = {["status"] = message}
end
else
return http_response(415, "Unsupported Media Type")
end
-- guess type if not set
--[[if not message["type"] then
if message["body"] then
if message["subject"] then
message["type"] = "normal"
else
message["type"] = "chat"
end
elseif not message["body"] and message["subject"] then
message["type"] = "headline"
end
end]]
-- build stanza
local stanza = st.presence();
if message["status"] then stanza:tag("status"):text(message["status"]):up(); end
if message["show"] then stanza:tag("show"):text(message["show"]):up(); end
if message["priority"] then stanza:tag("priority"):text(message["priority"]):up(); end
-- and finaly post it
--module:log("debug", "message for %s", to_jid)
for full_jid, session in pairs(bare_sessions[to_jid] and bare_sessions[to_jid].sessions or {}) do
stanza.attr.from = full_jid;
core_post_stanza(session, stanza)
end
return http_response(202, "Accepted")
end
local ports = require "core.configmanager".get(module.host, "core", "set_presence_rest_ports") or { 5280 };
require "net.httpserver".new_from_config(ports, "presence", handle_request);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment