Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
|
a0a40d4a7c | ||
|
505362164d | ||
|
09c31c78d0 | ||
|
9c709184af | ||
|
5a25c468f2 | ||
|
cad4836fbc | ||
|
732fc99a23 | ||
|
9827ec6d45 | ||
|
edc0dfc9b5 | ||
|
b37c5b525f |
12 changed files with 391 additions and 475 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1 @@
|
|||
config.php
|
||||
.vscode
|
||||
|
|
|
@ -15,81 +15,31 @@ local xmpp_server_key = module:get_option("http_upload_external_server_key");
|
|||
local filetransfer_manager_ui_url = module:get_option("filetransfer_manager_ui_url");
|
||||
|
||||
-- imports
|
||||
prosody.unlock_globals();
|
||||
--require"https";
|
||||
local st = require"util.stanza";
|
||||
local http = (string.len(external_url) >= 5 and string.sub(external_url,1,5) == "https") and require"ssl.https" or require"socket.http";
|
||||
local json = require"util.json";
|
||||
local dataform = require "util.dataforms".new;
|
||||
local ltn12 = require"ltn12";
|
||||
local rsm = require"util.rsm";
|
||||
prosody.lock_globals();
|
||||
|
||||
-- depends
|
||||
module:depends("disco");
|
||||
|
||||
-- namespace
|
||||
local xmlns_filetransfer_http = "urn:xmpp:filetransfer:http";
|
||||
local xmlns_http_upload = "urn:xmpp:http:upload";
|
||||
local xmlns_http_upload_0 = "urn:xmpp:http:upload:0";
|
||||
local xmlns_http_upload = "urn:xmpp:filetransfer:http";
|
||||
|
||||
-- versions
|
||||
spec_version = "v0.4";
|
||||
impl_version = "v0.4-dev";
|
||||
|
||||
module:add_feature(xmlns_filetransfer_http);
|
||||
module:add_feature(xmlns_http_upload);
|
||||
module:add_feature(xmlns_http_upload_0);
|
||||
|
||||
if filetransfer_manager_ui_url then
|
||||
-- add additional disco info to advertise managing UI
|
||||
module:add_extension(dataform {
|
||||
{ name = "FORM_TYPE", type = "hidden", value = xmlns_filetransfer_http },
|
||||
{ name = "FORM_TYPE", type = "hidden", value = xmlns_http_upload },
|
||||
{ name = "filetransfer-manager-ui-url", type = "text-single" },
|
||||
}:form({ ["filetransfer-manager-ui-url"] = filetransfer_manager_ui_url }, "result"));
|
||||
end
|
||||
|
||||
local function buildRequestBody(reqparams)
|
||||
module:log("debug", "param count " .. #reqparams);
|
||||
local params = {};
|
||||
for k,v in pairs(reqparams) do
|
||||
if v ~= nil then
|
||||
params[#params + 1] = k .. "=" .. tostring(v);
|
||||
end
|
||||
end
|
||||
return table.concat(params, "&");
|
||||
end
|
||||
|
||||
local function listfiles(origin, orig_from, stanza, request)
|
||||
local rsmSet = rsm.get(request);
|
||||
local limit = rsmSet and rsmSet.max or -1;
|
||||
local descending = rsmSet and rsmSet.before or nil;
|
||||
local index = rsmSet and rsmSet.index or 0;
|
||||
--local before, after = rsmSet and rsmSet.before, rsmSet and rsmSet.after;
|
||||
--if type(before) ~= "string" then before = nil; end
|
||||
local filter = request.attr.filter or nil;
|
||||
local from = request.attr.from or nil;
|
||||
local to = request.attr.to or nil;
|
||||
local with = request.attr.with or nil;
|
||||
-- build the body
|
||||
local reqparams = {
|
||||
["xmpp_server_key"] = xmpp_server_key,
|
||||
["slot_type"] = "list",
|
||||
["user_jid"] = orig_from,
|
||||
["offset"] = index,
|
||||
["limit"] = limit,
|
||||
["descending"] = descending,
|
||||
["filter"] = filter,
|
||||
["from"] = from,
|
||||
["to"] = to,
|
||||
["with"] = with
|
||||
};
|
||||
|
||||
--local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=list&user_jid=" .. orig_from ..
|
||||
-- "&offset=" .. index .. "&limit=" .. limit .. "&descending=" .. tostring(descending);
|
||||
--reqbody = reqbody .. "&filter=" .. filter .. "&from=" .. from .. "&to=" .. to .. "&with=" .. with;
|
||||
local reqbody = buildRequestBody(reqparams);
|
||||
module:log("debug", "Request body: " .. reqbody);
|
||||
local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=list&user_jid=" .. orig_from;
|
||||
-- the request
|
||||
local respbody, statuscode = http.request(external_url, reqbody);
|
||||
-- respbody is nil in case the server is not reachable
|
||||
|
@ -97,10 +47,8 @@ local function listfiles(origin, orig_from, stanza, request)
|
|||
respbody = string.gsub(respbody, "\\/", "/");
|
||||
end
|
||||
|
||||
local filelistempty = true;
|
||||
local list;
|
||||
local count = 0;
|
||||
local first = {};
|
||||
first.index = index;
|
||||
|
||||
-- check the response
|
||||
if statuscode == 500 then
|
||||
|
@ -127,10 +75,8 @@ local function listfiles(origin, orig_from, stanza, request)
|
|||
return true;
|
||||
else
|
||||
-- process json response
|
||||
if respobj.list then
|
||||
list = respobj.list.files;
|
||||
count = respobj.list.count;
|
||||
end
|
||||
list = respobj.list;
|
||||
filelistempty = list == nil or next(list) == nil;
|
||||
end
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody));
|
||||
|
@ -139,8 +85,8 @@ local function listfiles(origin, orig_from, stanza, request)
|
|||
|
||||
local addedfiles = 0;
|
||||
local reply = st.reply(stanza);
|
||||
reply:tag("list", {xmlns=xmlns_filetransfer_http});
|
||||
if count > 0 then
|
||||
reply:tag("list", {xmlns=xmlns_http_upload});
|
||||
if filelistempty == false then
|
||||
for i, file in ipairs(list) do
|
||||
local url = file.url;
|
||||
if url == "" then
|
||||
|
@ -165,10 +111,9 @@ local function listfiles(origin, orig_from, stanza, request)
|
|||
end
|
||||
end
|
||||
end
|
||||
if count == 0 or addedfiles == 0 then
|
||||
if filelistempty or addedfiles == 0 then
|
||||
reply:tag("empty"):up();
|
||||
end
|
||||
reply:add_child(rsm.generate{first = first, count = count})
|
||||
origin.send(reply);
|
||||
return true;
|
||||
end
|
||||
|
@ -180,6 +125,8 @@ local function deletefile(origin, orig_from, stanza, request)
|
|||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid fileurl"));
|
||||
return true;
|
||||
end
|
||||
-- build the body
|
||||
--local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=delete&file_url=" .. fileurl .. "&user_jid=" .. orig_from;
|
||||
-- the request
|
||||
local resp = {};
|
||||
local client, statuscode = http.request{url=fileurl,
|
||||
|
@ -210,7 +157,7 @@ local function deletefile(origin, orig_from, stanza, request)
|
|||
elseif errobj["err_code"] ~= nil and errobj["msg"] ~= nil then
|
||||
if errobj.err_code == 4 then
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg)
|
||||
:tag("missing-parameter", {xmlns=xmlns_filetransfer_http})
|
||||
:tag("missing-parameter", {xmlns=xmlns_http_upload})
|
||||
:text(errobj.parameters.missing_parameter));
|
||||
return true;
|
||||
else
|
||||
|
@ -224,7 +171,7 @@ local function deletefile(origin, orig_from, stanza, request)
|
|||
end
|
||||
elseif statuscode == 204 or statuscode == 404 then
|
||||
local reply = st.reply(stanza);
|
||||
reply:tag("deleted", { xmlns = xmlns_filetransfer_http });
|
||||
reply:tag("deleted", { xmlns = xmlns_http_upload });
|
||||
origin.send(reply);
|
||||
return true;
|
||||
elseif respbody ~= nil then
|
||||
|
@ -237,56 +184,50 @@ local function deletefile(origin, orig_from, stanza, request)
|
|||
end
|
||||
end
|
||||
|
||||
local function version(origin, stanza)
|
||||
local reply = st.reply(stanza);
|
||||
reply:tag("version", { xmlns = xmlns_filetransfer_http });
|
||||
reply:tag("xmpp-fileservice-module", { spec = spec_version, implementation = impl_version }):up();
|
||||
-- the request
|
||||
local respbody, statuscode = http.request(external_url .. "?action=version");
|
||||
-- respbody is nil in case the server is not reachable
|
||||
if respbody ~= nil then
|
||||
respbody = string.gsub(respbody, "\\/", "/");
|
||||
end
|
||||
|
||||
local http_spec_version = nil;
|
||||
local http_impl_version = nil;
|
||||
|
||||
-- check the response
|
||||
if statuscode == 200 then
|
||||
local respobj, pos, err = json.decode(respbody);
|
||||
if err then
|
||||
-- do nothing for the moment
|
||||
else
|
||||
if respobj["spec"] ~= nil and respobj["impl"] ~= nil then
|
||||
http_spec_version = respobj.spec;
|
||||
http_impl_version = respobj.impl;
|
||||
reply:tag("http-fileservice-module", { spec = http_spec_version, implementation = http_impl_version }):up();
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
origin.send(reply);
|
||||
return true;
|
||||
end
|
||||
|
||||
local function create_upload_slot_with_childs(origin, orig_from, stanza, request, namespace, recipient)
|
||||
-- validate
|
||||
local filename = request:get_child_text("filename");
|
||||
if not filename then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename"));
|
||||
-- hooks
|
||||
module:hook("iq/host/"..xmlns_http_upload..":request", function (event)
|
||||
local stanza, origin = event.stanza, event.origin;
|
||||
local orig_from = stanza.attr.from;
|
||||
local request = stanza.tags[1];
|
||||
-- local clients only
|
||||
if origin.type ~= "c2s" then
|
||||
origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
|
||||
return true;
|
||||
end
|
||||
local filesize = tonumber(request:get_child_text("size"));
|
||||
if not filesize then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size"));
|
||||
-- check configuration
|
||||
if not external_url or not xmpp_server_key then
|
||||
module:log("debug", "missing configuration options: http_upload_external_url and/or http_upload_external_server_key");
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error"));
|
||||
return true;
|
||||
end
|
||||
local slot_type = request.attr.type;
|
||||
if slot_type then
|
||||
module:log("debug", "incoming request is of type " .. slot_type);
|
||||
else
|
||||
module:log("debug", "incoming request has no type - using default type 'upload'");
|
||||
end
|
||||
|
||||
if not slot_type or slot_type == "upload" then
|
||||
-- validate
|
||||
local filename = request:get_child_text("filename");
|
||||
if not filename then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename"));
|
||||
return true;
|
||||
end
|
||||
local filesize = tonumber(request:get_child_text("size"));
|
||||
if not filesize then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local content_type = request:get_child_text("content-type");
|
||||
return create_upload_slot(origin, orig_from, stanza, namespace, recipient, filename, filesize, content_type);
|
||||
end
|
||||
local recipient = request.attr.recipient;
|
||||
if not recipient then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid recipient"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local function create_upload_slot(origin, orig_from, stanza, namespace, recipient, filename, filesize, content_type)
|
||||
local content_type = request:get_child_text("content-type");
|
||||
|
||||
-- build the body
|
||||
local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=upload&size=" .. filesize .. "&filename=" .. filename .. "&user_jid=" .. orig_from .. "&recipient_jid=" .. recipient;
|
||||
if content_type then
|
||||
|
@ -319,17 +260,17 @@ local function create_upload_slot(origin, orig_from, stanza, namespace, recipien
|
|||
return true;
|
||||
elseif errobj.err_code == 2 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg)
|
||||
:tag("file-too-large", {xmlns=namespace})
|
||||
:tag("file-too-large", {xmlns=xmlns_http_upload})
|
||||
:tag("max-size"):text(errobj.parameters.max_file_size));
|
||||
return true;
|
||||
elseif errobj.err_code == 3 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg)
|
||||
:tag("invalid-character", {xmlns=namespace})
|
||||
:tag("invalid-character", {xmlns=xmlns_http_upload})
|
||||
:text(errobj.parameters.invalid_character));
|
||||
return true;
|
||||
elseif errobj.err_code == 4 then
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg)
|
||||
:tag("missing-parameter", {xmlns=namespace})
|
||||
:tag("missing-parameter", {xmlns=xmlns_http_upload})
|
||||
:text(errobj.parameters.missing_parameter));
|
||||
return true;
|
||||
else
|
||||
|
@ -368,120 +309,17 @@ local function create_upload_slot(origin, orig_from, stanza, namespace, recipien
|
|||
end
|
||||
|
||||
local reply = st.reply(stanza);
|
||||
reply:tag("slot", { xmlns = namespace });
|
||||
if namespace == xmlns_http_upload_0 then
|
||||
reply:tag("put", { url = put_url }):up();
|
||||
reply:tag("get", { url = get_url }):up();
|
||||
else
|
||||
reply:tag("get"):text(get_url):up();
|
||||
reply:tag("put"):text(put_url):up();
|
||||
end
|
||||
|
||||
reply:tag("slot", { xmlns = xmlns_http_upload });
|
||||
reply:tag("get"):text(get_url):up();
|
||||
reply:tag("put"):text(put_url):up();
|
||||
origin.send(reply);
|
||||
return true;
|
||||
end
|
||||
|
||||
-- hooks
|
||||
module:hook("iq/host/"..xmlns_filetransfer_http..":request", function (event)
|
||||
local stanza, origin = event.stanza, event.origin;
|
||||
local orig_from = stanza.attr.from;
|
||||
local request = stanza.tags[1];
|
||||
-- local clients only
|
||||
if origin.type ~= "c2s" then
|
||||
origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
|
||||
return true;
|
||||
end
|
||||
-- check configuration
|
||||
if not external_url or not xmpp_server_key then
|
||||
module:log("debug", "missing configuration options: http_upload_external_url and/or http_upload_external_server_key");
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error"));
|
||||
return true;
|
||||
end
|
||||
local slot_type = request.attr.type;
|
||||
if slot_type then
|
||||
module:log("debug", "incoming request is of type " .. slot_type);
|
||||
else
|
||||
module:log("debug", "incoming request has no type - using default type 'upload'");
|
||||
end
|
||||
|
||||
if not slot_type or slot_type == "upload" then
|
||||
local recipient = request.attr.recipient;
|
||||
if not recipient then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid recipient"));
|
||||
return true;
|
||||
end
|
||||
return create_upload_slot(origin, orig_from, stanza, request, xmlns_filetransfer_http, recipient);
|
||||
elseif slot_type == "delete" then
|
||||
return deletefile(origin, orig_from, stanza, request);
|
||||
elseif slot_type == "list" then
|
||||
return listfiles(origin, orig_from, stanza, request);
|
||||
elseif slot_type == "version" then
|
||||
return version(origin, stanza);
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody));
|
||||
return true;
|
||||
end
|
||||
end);
|
||||
|
||||
module:hook("iq/host/"..xmlns_http_upload..":request", function (event)
|
||||
local stanza, origin = event.stanza, event.origin;
|
||||
local orig_from = stanza.attr.from;
|
||||
local request = stanza.tags[1];
|
||||
-- local clients only
|
||||
if origin.type ~= "c2s" then
|
||||
origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
|
||||
return true;
|
||||
end
|
||||
-- check configuration
|
||||
if not external_url or not xmpp_server_key then
|
||||
module:log("debug", "missing configuration options: http_upload_external_url and/or http_upload_external_server_key");
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error"));
|
||||
return true;
|
||||
end
|
||||
local slot_type = request.attr.type;
|
||||
if slot_type then
|
||||
module:log("debug", "incoming request is of type " .. slot_type);
|
||||
else
|
||||
module:log("debug", "incoming request has no type - using default type 'upload'");
|
||||
end
|
||||
|
||||
return create_upload_slot_with_childs(origin, orig_from, stanza, request, xmlns_http_upload, "Unknown");
|
||||
end);
|
||||
|
||||
module:hook("iq/host/"..xmlns_http_upload_0..":request", function (event)
|
||||
local stanza, origin = event.stanza, event.origin;
|
||||
local orig_from = stanza.attr.from;
|
||||
local request = stanza.tags[1];
|
||||
-- local clients only
|
||||
if origin.type ~= "c2s" then
|
||||
origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
|
||||
return true;
|
||||
end
|
||||
-- check configuration
|
||||
if not external_url or not xmpp_server_key then
|
||||
module:log("debug", "missing configuration options: http_upload_external_url and/or http_upload_external_server_key");
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error"));
|
||||
return true;
|
||||
end
|
||||
local slot_type = request.attr.type;
|
||||
if slot_type then
|
||||
module:log("debug", "incoming request is of type " .. slot_type);
|
||||
else
|
||||
module:log("debug", "incoming request has no type - using default type 'upload'");
|
||||
end
|
||||
|
||||
local filename = request.attr.filename;
|
||||
if not filename then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename"));
|
||||
return true;
|
||||
end
|
||||
local filesize = tonumber(request.attr.size);
|
||||
if not filesize then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local content_type = request.attr["content-type"] or "application/octet-stream";
|
||||
|
||||
return create_upload_slot(origin, orig_from, stanza, xmlns_http_upload_0, "Unknown", filename, filesize, content_type);
|
||||
end);
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
-- mod_http_upload_external
|
||||
--
|
||||
-- Copyright (C) 2016 Sebastian Luksch
|
||||
--
|
||||
-- This file is MIT/X11 licensed.
|
||||
--
|
||||
-- Implementation of HTTP Upload file transfer mechanism used by Conversations
|
||||
--
|
||||
-- Query external HTTP server to retrieve URLs
|
||||
--
|
||||
|
||||
-- configuration
|
||||
local external_url = module:get_option("http_upload_external_url");
|
||||
local xmpp_server_key = module:get_option("http_upload_external_server_key");
|
||||
|
||||
-- imports
|
||||
local st = require"util.stanza";
|
||||
local http = (string.len(external_url) >= 5 and string.sub(external_url,1,5) == "https") and require"ssl.https" or require"socket.http";
|
||||
local json = require"util.json";
|
||||
|
||||
-- namespace
|
||||
--local xmlns_http_upload = "urn:xmpp:http:upload";
|
||||
local xmlns_http_upload = "de:thedevstack:conversationsplus:http:upload";
|
||||
|
||||
-- depends
|
||||
module:depends("disco");
|
||||
--module:add_identity("store", "file", "HTTP File Upload");
|
||||
module:add_feature(xmlns_http_upload);
|
||||
|
||||
-- hooks
|
||||
module:hook("iq/host/"..xmlns_http_upload..":request", function (event)
|
||||
module:log("info", "HTTPUPLOAD: request");
|
||||
local stanza, origin = event.stanza, event.origin;
|
||||
local orig_from = stanza.attr.from;
|
||||
local request = stanza.tags[1];
|
||||
-- local clients only
|
||||
if origin.type ~= "c2s" then
|
||||
origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
|
||||
return true;
|
||||
end
|
||||
-- check configuration
|
||||
if not external_url or not xmpp_server_key then
|
||||
module:log("debug", "missing configuration options: http_upload_external_url and/or http_upload_external_server_key");
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error"));
|
||||
return true;
|
||||
end
|
||||
-- validate
|
||||
local filename = request:get_child_text("filename");
|
||||
if not filename then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename"));
|
||||
return true;
|
||||
end
|
||||
local filesize = tonumber(request:get_child_text("size"));
|
||||
if not filesize then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local content_type = request:get_child_text("content-type");
|
||||
|
||||
-- build the body
|
||||
local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&size=" .. filesize .. "&filename=" .. filename .. "&user_jid=" .. orig_from;
|
||||
if content_type then
|
||||
reqbody = reqbody .. "&content_type=" .. content_type;
|
||||
end
|
||||
|
||||
-- the request
|
||||
local respbody, statuscode = http.request(external_url, reqbody);
|
||||
respbody = string.gsub(respbody, "\\/", "/")
|
||||
module:log("info", "HTTPUPLOAD: resp " .. respbody);
|
||||
|
||||
local get_url = nil;
|
||||
local put_url = nil;
|
||||
|
||||
-- check the response
|
||||
if statuscode == 500 then
|
||||
origin.send(st.error_reply(stanza, "cancel", "service-unavailable", respbody));
|
||||
elseif statuscode == 406 or statuscode == 400 or statuscode == 403 then
|
||||
local errobj, pos, err = json.decode(respbody);
|
||||
if err then
|
||||
origin.send(st.error_reply(stanza, "wait", "internal-server-error", err));
|
||||
return true;
|
||||
else
|
||||
if errobj["err_code"] ~= nil and errobj["msg"] ~= nil then
|
||||
if errobj.err_code == 1 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg));
|
||||
return true;
|
||||
elseif errobj.err_code == 2 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg,
|
||||
st.stanza("file-too-large", {xmlns=xmlns_http_upload})
|
||||
:tag("max-size"):text(errobj.parameters.max_file_size)));
|
||||
return true;
|
||||
elseif errobj.err_code == 3 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg,
|
||||
st.stanza("invalid-character", {xmlns=xmlns_http_upload})
|
||||
:text(errobj.parameters.invalid_character)));
|
||||
return true;
|
||||
elseif errobj.err_code == 4 then
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg,
|
||||
st.stanza("missing-parameter", {xmlns=xmlns_http_upload})
|
||||
:text(errobj.parameters.missing_parameter)));
|
||||
return true;
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "unknown err_code"));
|
||||
return true;
|
||||
end
|
||||
elseif statuscode == 403 and errobj["msg"] ~= nil then
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg));
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "msg or err_code not found"));
|
||||
return true;
|
||||
end
|
||||
end
|
||||
elseif statuscode == 200 then
|
||||
local respobj, pos, err = json.decode(respbody);
|
||||
if err then
|
||||
origin.send(st.error_reply(stanza, "wait", "internal-server-error", err));
|
||||
return true;
|
||||
else
|
||||
if respobj["get"] ~= nil and respobj["put"] ~= nil then
|
||||
get_url = respobj.get;
|
||||
put_url = respobj.put;
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "get or put not found"));
|
||||
return true;
|
||||
end
|
||||
end
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody));
|
||||
return true;
|
||||
end
|
||||
|
||||
local reply = st.reply(stanza);
|
||||
reply:tag("slot", { xmlns = xmlns_http_upload });
|
||||
reply:tag("get"):text(get_url):up();
|
||||
reply:tag("put"):text(put_url):up();
|
||||
module:log("info", "HTTPUPLOAD: get " .. get_url);
|
||||
module:log("info", "HTTPUPLOAD: put " .. put_url);
|
||||
origin.send(reply);
|
||||
return true;
|
||||
end);
|
|
@ -0,0 +1,139 @@
|
|||
-- mod_http_upload_external
|
||||
--
|
||||
-- Copyright (C) 2016 Sebastian Luksch
|
||||
--
|
||||
-- This file is MIT/X11 licensed.
|
||||
--
|
||||
-- Implementation of HTTP Upload file transfer mechanism used by Conversations
|
||||
--
|
||||
-- Query external HTTP server to retrieve URLs
|
||||
--
|
||||
|
||||
-- configuration
|
||||
local external_url = module:get_option("http_upload_external_url");
|
||||
local xmpp_server_key = module:get_option("http_upload_external_server_key");
|
||||
|
||||
-- imports
|
||||
local st = require"util.stanza";
|
||||
local http = (string.len(external_url) >= 5 and string.sub(external_url,1,5) == "https") and require"ssl.https" or require"socket.http";
|
||||
local json = require"util.json";
|
||||
|
||||
-- namespace
|
||||
local xmlns_http_upload = "urn:xmpp:http:upload";
|
||||
|
||||
-- depends
|
||||
module:depends("disco");
|
||||
--module:add_identity("store", "file", "HTTP File Upload");
|
||||
module:add_feature(xmlns_http_upload);
|
||||
|
||||
-- hooks
|
||||
module:hook("iq/host/"..xmlns_http_upload..":request", function (event)
|
||||
module:log("info", "HTTPUPLOAD: request");
|
||||
local stanza, origin = event.stanza, event.origin;
|
||||
local orig_from = stanza.attr.from;
|
||||
local request = stanza.tags[1];
|
||||
-- local clients only
|
||||
if origin.type ~= "c2s" then
|
||||
origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
|
||||
return true;
|
||||
end
|
||||
-- check configuration
|
||||
if not external_url or not xmpp_server_key then
|
||||
module:log("debug", "missing configuration options: http_upload_external_url and/or http_upload_external_server_key");
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error"));
|
||||
return true;
|
||||
end
|
||||
-- validate
|
||||
local filename = request:get_child_text("filename");
|
||||
if not filename then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename"));
|
||||
return true;
|
||||
end
|
||||
local filesize = tonumber(request:get_child_text("size"));
|
||||
if not filesize then
|
||||
origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local content_type = request:get_child_text("content-type");
|
||||
|
||||
-- build the body
|
||||
local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&size=" .. filesize .. "&filename=" .. filename .. "&user_jid=" .. orig_from;
|
||||
if content_type then
|
||||
reqbody = reqbody .. "&content_type=" .. content_type;
|
||||
end
|
||||
|
||||
-- the request
|
||||
local respbody, statuscode = http.request(external_url, reqbody);
|
||||
respbody = string.gsub(respbody, "\\/", "/")
|
||||
|
||||
local get_url = nil;
|
||||
local put_url = nil;
|
||||
|
||||
-- check the response
|
||||
if statuscode == 500 then
|
||||
origin.send(st.error_reply(stanza, "cancel", "service-unavailable", respbody));
|
||||
elseif statuscode == 406 or statuscode == 400 or statuscode == 403 then
|
||||
local errobj, pos, err = json.decode(respbody);
|
||||
if err then
|
||||
origin.send(st.error_reply(stanza, "wait", "internal-server-error", err));
|
||||
return true;
|
||||
else
|
||||
if errobj["err_code"] ~= nil and errobj["msg"] ~= nil then
|
||||
if errobj.err_code == 1 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg));
|
||||
return true;
|
||||
elseif errobj.err_code == 2 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg,
|
||||
st.stanza("file-too-large", {xmlns=xmlns_http_upload})
|
||||
:tag("max-size"):text(errobj.parameters.max_file_size)));
|
||||
return true;
|
||||
elseif errobj.err_code == 3 then
|
||||
origin.send(st.error_reply(stanza, "modify", "not-acceptable", errobj.msg,
|
||||
st.stanza("invalid-character", {xmlns=xmlns_http_upload})
|
||||
:text(errobj.parameters.invalid_character)));
|
||||
return true;
|
||||
elseif errobj.err_code == 4 then
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg,
|
||||
st.stanza("missing-parameter", {xmlns=xmlns_http_upload})
|
||||
:text(errobj.parameters.missing_parameter)));
|
||||
return true;
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "unknown err_code"));
|
||||
return true;
|
||||
end
|
||||
elseif statuscode == 403 and errobj["msg"] ~= nil then
|
||||
origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg));
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "msg or err_code not found"));
|
||||
return true;
|
||||
end
|
||||
end
|
||||
elseif statuscode == 200 then
|
||||
local respobj, pos, err = json.decode(respbody);
|
||||
if err then
|
||||
origin.send(st.error_reply(stanza, "wait", "internal-server-error", err));
|
||||
return true;
|
||||
else
|
||||
if respobj["get"] ~= nil and respobj["put"] ~= nil then
|
||||
get_url = respobj.get;
|
||||
put_url = respobj.put;
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "get or put not found"));
|
||||
return true;
|
||||
end
|
||||
end
|
||||
else
|
||||
origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody));
|
||||
return true;
|
||||
end
|
||||
|
||||
local reply = st.reply(stanza);
|
||||
reply:tag("slot", { xmlns = xmlns_http_upload });
|
||||
reply:tag("get"):text(get_url):up();
|
||||
reply:tag("put"):text(put_url):up();
|
||||
module:log("info", "HTTPUPLOAD: get " .. get_url);
|
||||
module:log("info", "HTTPUPLOAD: put " .. put_url);
|
||||
origin.send(reply);
|
||||
return true;
|
||||
end);
|
|
@ -1,3 +1,3 @@
|
|||
RewriteEngine on
|
||||
RewriteCond %{REQUEST_METHOD} (DELETE|PUT)
|
||||
RewriteRule ^(.*)$ index.php?uri=$1 [B,L,QSA]
|
||||
RewriteRule ^(.*)$ index.php?uri=$1 [L,QSA]
|
||||
|
|
|
@ -14,7 +14,5 @@ return [
|
|||
'delete_token_validity' => 5 * 60,
|
||||
// Flag to whether deletion is only allowed by creator or anybody
|
||||
'delete_only_by_creator' => true,
|
||||
// The default count of items returned when a file list is requested
|
||||
'list_default_limit' => 30,
|
||||
];
|
||||
?>
|
|
@ -67,8 +67,8 @@ switch ($method) {
|
|||
case 'POST':
|
||||
// parse post parameters
|
||||
// check if all parameters are present - return 400 (bad request) if a parameter is missing / empty
|
||||
$xmppServerKey = getMandatoryPost('xmpp_server_key');
|
||||
$userJid = getMandatoryPost('user_jid');
|
||||
$xmppServerKey = getMandatoryPostParameter('xmpp_server_key');
|
||||
$userJid = getMandatoryPostParameter('user_jid');
|
||||
$slotType = getOptionalPostParameter('slot_type', 'upload');
|
||||
|
||||
// Check if xmppServerKey is allowed to request slots
|
||||
|
@ -78,17 +78,14 @@ switch ($method) {
|
|||
|
||||
switch ($slotType) {
|
||||
case 'list':
|
||||
$limit = getOptionalPostParameter('limit', $config['list_default_limit']);
|
||||
$offset = getOptionalPostParameter('offset', 0);
|
||||
$descending = getOptionalPostParameter('descending', 'false') === 'true';
|
||||
$files = listFiles($userJid, $limit, $offset, $descending);
|
||||
$result = ['list' => $files];
|
||||
$slots = readSlots($userJid);
|
||||
$result = ['list' => $slots];
|
||||
break;
|
||||
case 'upload':
|
||||
default:
|
||||
// Check if all parameters needed for an upload are present - return 400 (bad request) if a parameter is missing / empty
|
||||
$filename = rawurlencode(getMandatoryPost('filename'));
|
||||
$filesize = getMandatoryPost('size');
|
||||
$filename = rawurlencode(getMandatoryPostParameter('filename'));
|
||||
$filesize = getMandatoryPostParameter('size');
|
||||
$mimeType = getOptionalPostParameter('content_type');
|
||||
$recipientJid = getOptionalPostParameter('recipient_jid', 'Unknown'); // Optional for backwards compatibility (xep-0363 v0.1)
|
||||
|
||||
|
@ -146,8 +143,7 @@ switch ($method) {
|
|||
sendHttpReturnCodeAndJson(403, "Uploaded file size differs from requested slot size.");
|
||||
}
|
||||
// check actual mime type with registered mime type
|
||||
$uploadedContentType = mime_content_type($uploadFilePath);
|
||||
if (false && !is_null($slotParameters['content_type']) && !empty($slotParameters['content_type']) && $uploadedContentType != $slotParameters['content_type']) {
|
||||
if (!is_null($slotParameters['content_type']) && !empty($slotParameters['content_type']) && mime_content_type($uploadFilePath) != $slotParameters['content_type']) {
|
||||
unlink($uploadFilePath);
|
||||
sendHttpReturnCodeAndJson(403, "Uploaded file content type differs from requested slot content type.");
|
||||
}
|
||||
|
@ -197,17 +193,6 @@ switch ($method) {
|
|||
sendHttpReturnCodeAndJson(500, "Could not delete file.");
|
||||
}
|
||||
break;
|
||||
case 'GET':
|
||||
$actionParameter = getMandatoryGet('action');
|
||||
|
||||
switch ($actionParameter) {
|
||||
case 'version':
|
||||
echo json_encode(require_once(__DIR__.'/lib/version.inc.php'));
|
||||
break;
|
||||
default:
|
||||
sendHttpReturnCodeAndJson(403, "Access not allowed.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sendHttpReturnCodeAndJson(403, "Access not allowed.");
|
||||
break;
|
||||
|
@ -227,12 +212,12 @@ function checkFilenameParameter($filename, $slotParameters) {
|
|||
return $slotParameters['filename'] == $filename;
|
||||
}
|
||||
|
||||
function getMandatoryPost($parameterName) {
|
||||
return getMandatoryPostParameter($parameterName, ['msg' => 'Missing parameter.', 'err_code' => 4, 'parameters' => ['missing_parameter' => $parameterName]], true);
|
||||
}
|
||||
|
||||
function getMandatoryGet($parameterName) {
|
||||
return getMandatoryGetParameter($parameterName, ['msg' => 'Missing parameter.', 'err_code' => 4, 'parameters' => ['missing_parameter' => $parameterName]], true);
|
||||
function getMandatoryPostParameter($parameterName) {
|
||||
$parameter = $_POST[$parameterName];
|
||||
if (!isset($parameter) || is_null($parameter) || empty($parameter)) {
|
||||
sendHttpReturnCodeAndJson(400, ['msg' => 'Missing parameter.', 'err_code' => 4, 'parameters' => ['missing_parameter' => $parameterName]]);
|
||||
}
|
||||
return $parameter;
|
||||
}
|
||||
|
||||
function getUUIDFromUri($uri) {
|
||||
|
|
|
@ -15,50 +15,4 @@ function generate_uuid() {
|
|||
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
|
||||
);
|
||||
}
|
||||
|
||||
function getFromArray($key, $array) {
|
||||
if (array_key_exists($key, $array)
|
||||
&& isset($array[$key])
|
||||
&& !empty($array[$key])) {
|
||||
return $array[$key];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
function format_size($size, $precision = 2) {
|
||||
$sizes = ['bytes', 'Kb', 'Mb', 'Gb', 'Tb'];
|
||||
$i = 0;
|
||||
while (1023 < $size && $i < count($sizes) - 1) {
|
||||
$size /= 1023;
|
||||
++$i;
|
||||
}
|
||||
|
||||
return number_format($size, $precision).' '.$sizes[$i];
|
||||
}
|
||||
|
||||
function startsWith($haystack, $needle) {
|
||||
$length = strlen($needle);
|
||||
return (substr($haystack, 0, $length) === $needle);
|
||||
}
|
||||
|
||||
function endsWith($haystack, $needle) {
|
||||
$length = strlen($needle);
|
||||
|
||||
return $length === 0 || (substr($haystack, -$length) === $needle);
|
||||
}
|
||||
|
||||
function generatePath($parts, $basePath = __DIR__) {
|
||||
$path = $basePath;
|
||||
if (!is_array($parts)) {
|
||||
$parts = [$parts];
|
||||
}
|
||||
foreach ($parts as $part) {
|
||||
$path .= DIRECTORY_SEPARATOR.generatePathName($part);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
function generatePathName($name) {
|
||||
return urlencode($name);
|
||||
}
|
||||
?>
|
|
@ -24,42 +24,7 @@ function loadSlotParameters($slotUUID, $config) {
|
|||
return $slotParameters;
|
||||
}
|
||||
|
||||
function listFiles($jid, $limit = -1, $offset = 0, $descending = false) {
|
||||
// Read complete set of existing slots per jid (unsorted)
|
||||
$slots = readSlots($jid, $limit, $offset);
|
||||
|
||||
if ($descending) {
|
||||
// Sort descending by timestamp
|
||||
usort($slots, function($a, $b) {
|
||||
return $b['sent_time'] - $a['sent_time'];
|
||||
});
|
||||
} else {
|
||||
// Sort ascending by timestamp
|
||||
usort($slots, function($a, $b) {
|
||||
return $a['sent_time'] - $b['sent_time'];
|
||||
});
|
||||
}
|
||||
|
||||
// Select requested slot subset
|
||||
$offsetCounter = 0;
|
||||
$resultSet = array();
|
||||
foreach ($slots as $slot) {
|
||||
if (0 < $offset && $offsetCounter < $offset) {
|
||||
$offsetCounter++;
|
||||
continue;
|
||||
}
|
||||
$resultSet[] = $slot;
|
||||
|
||||
if (0 < $limit && $limit == count($resultSet)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ['count' => count($slots),
|
||||
'hasMore' => $offset + count($resultSet) < count($slots),
|
||||
'files' => $resultSet];
|
||||
}
|
||||
|
||||
function readSlots($jid, $limit = -1, $offset = 0) {
|
||||
function readSlots($jid) {
|
||||
global $config;
|
||||
|
||||
$jid = getBareJid($jid);
|
||||
|
@ -75,7 +40,7 @@ function readSlots($jid, $limit = -1, $offset = 0) {
|
|||
if ($senderBareJid == $jid || $recipientBareJid == $jid) {
|
||||
$filePath = getUploadFilePath($slotUUID, $config, $params['filename']);
|
||||
$file = [];
|
||||
$fileExists = file_exists(rawurldecode($filePath));
|
||||
$fileExists = file_exists($filePath);
|
||||
$file['url'] = "";
|
||||
$file['sent_time'] = $params['creation_time'];
|
||||
if ($fileExists) {
|
||||
|
@ -95,6 +60,5 @@ function readSlots($jid, $limit = -1, $offset = 0) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $slots;
|
||||
}
|
||||
|
|
|
@ -6,156 +6,59 @@
|
|||
*
|
||||
*/
|
||||
|
||||
require_once('functions.common.inc.php');
|
||||
|
||||
/**
|
||||
* Inspired by https://github.com/owncloud/core/blob/master/lib/private/appframework/http/request.php#L523
|
||||
*/
|
||||
function getServerProtocol() {
|
||||
$protocol = getHeaderExtensionValue('FORWARDED_PROTO');
|
||||
if (isset($protocol)) {
|
||||
if (strpos($protocol, ',') !== false) {
|
||||
$parts = explode(',', $protocol);
|
||||
$proto = strtolower(trim($parts[0]));
|
||||
} else {
|
||||
$proto = strtolower($protocol);
|
||||
}
|
||||
// Verify that the protocol is always HTTP or HTTPS
|
||||
// default to http if an invalid value is provided
|
||||
return $proto === 'https' ? 'https' : 'http';
|
||||
}
|
||||
if (isset($_SERVER['HTTPS'])
|
||||
&& $_SERVER['HTTPS'] !== null
|
||||
&& $_SERVER['HTTPS'] !== 'off'
|
||||
&& $_SERVER['HTTPS'] !== '') {
|
||||
return 'https';
|
||||
}
|
||||
return 'http';
|
||||
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
|
||||
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], ',') !== false) {
|
||||
$parts = explode(',', $_SERVER['HTTP_X_FORWARDED_PROTO']);
|
||||
$proto = strtolower(trim($parts[0]));
|
||||
} else {
|
||||
$proto = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']);
|
||||
}
|
||||
// Verify that the protocol is always HTTP or HTTPS
|
||||
// default to http if an invalid value is provided
|
||||
return $proto === 'https' ? 'https' : 'http';
|
||||
}
|
||||
if (isset($_SERVER['HTTPS'])
|
||||
&& $_SERVER['HTTPS'] !== null
|
||||
&& $_SERVER['HTTPS'] !== 'off'
|
||||
&& $_SERVER['HTTPS'] !== '') {
|
||||
return 'https';
|
||||
}
|
||||
return 'http';
|
||||
}
|
||||
|
||||
function getRequestHostname() {
|
||||
$forwardedHost = getHeaderExtensionValue('FORWARDED_HOST');
|
||||
if (isset($forwardedHost)) {
|
||||
return strtolower($forwardedHost);
|
||||
}
|
||||
return strtolower(getHeaderValue('HOST'));
|
||||
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
|
||||
return strtolower($_SERVER['HTTP_X_FORWARDED_HOST']);
|
||||
}
|
||||
return strtolower($_SERVER['HTTP_HOST']);
|
||||
}
|
||||
|
||||
function getRequestUriWithoutFilename() {
|
||||
return strtolower(substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '/') + 1));
|
||||
return strtolower(substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '/') + 1));
|
||||
}
|
||||
|
||||
function sendHttpReturnCodeAndJson($code, $data) {
|
||||
if (!is_array($data)) {
|
||||
$data = ['msg' => $data];
|
||||
}
|
||||
|
||||
setContentType('application/json');
|
||||
|
||||
sendHttpReturnCodeAndMessage($code, json_encode($data));
|
||||
if (!is_array($data)) {
|
||||
$data = ['msg' => $data];
|
||||
}
|
||||
header('Content-Type: application/json');
|
||||
sendHttpReturnCodeAndMessage($code, json_encode($data));
|
||||
}
|
||||
|
||||
function sendHttpReturnCodeAndMessage($code, $text = '') {
|
||||
http_response_code($code);
|
||||
exit($text);
|
||||
}
|
||||
|
||||
function setContentType($contentType) {
|
||||
header('Content-Type: '.$contentType);
|
||||
}
|
||||
|
||||
function getHeaderExtensionValue($headerName) {
|
||||
$headerName = strtoupper($headerName);
|
||||
if (!startsWith($headerName, 'HTTP_X_')) {
|
||||
if (!startsWith($headerName, 'HTTP_')) {
|
||||
$headerName = str_replace('HTTP_', 'HTTP_X_', $headerName);
|
||||
} else {
|
||||
$headerName = 'HTTP_X_'.$headerName;
|
||||
}
|
||||
}
|
||||
|
||||
return getHeaderValue($headerName);
|
||||
}
|
||||
|
||||
function getHeaderValue($headerName) {
|
||||
$headerName = strtoupper($headerName);
|
||||
if (!startsWith($headerName, 'HTTP_')) {
|
||||
$headerName = 'HTTP_'.$headerName;
|
||||
}
|
||||
|
||||
return getFromArray($headerName, $_SERVER);
|
||||
}
|
||||
|
||||
function getFileParameter($parameterName) {
|
||||
return getFromArray($parameterName, $_FILES);
|
||||
}
|
||||
|
||||
function getOptionalFileParameter($parameterName, $default = NULL) {
|
||||
$parameter = getFileParameter($parameterName);
|
||||
|
||||
return handleOptionalParameter($parameter, $default);
|
||||
}
|
||||
|
||||
function getMandatoryFileParameter($parameterName, $message = '', $json = false) {
|
||||
$parameter = getFileParameter($parameterName);
|
||||
|
||||
return handleMandatoryParameter($parameterName, $parameter, $message, $json);
|
||||
}
|
||||
|
||||
function getPostParameter($parameterName) {
|
||||
return getFromArray($parameterName, $_POST);
|
||||
http_response_code($code);
|
||||
exit($text);
|
||||
}
|
||||
|
||||
function getOptionalPostParameter($parameterName, $default = NULL) {
|
||||
$parameter = getPostParameter($parameterName);
|
||||
|
||||
return handleOptionalParameter($parameter, $default);
|
||||
$parameter = $_POST[$parameterName];
|
||||
if (!isset($parameter) || is_null($parameter) || empty($parameter)) {
|
||||
$parameter = $default;
|
||||
}
|
||||
return $parameter;
|
||||
}
|
||||
|
||||
function getMandatoryPostParameter($parameterName, $message = '', $json = false) {
|
||||
$parameter = getPostParameter($parameterName);
|
||||
|
||||
return handleMandatoryParameter($parameterName, $parameter, $message, $json);
|
||||
}
|
||||
|
||||
function getGetParameter($parameterName) {
|
||||
return getFromArray($parameterName, $_GET);
|
||||
}
|
||||
|
||||
function getOptionalGetParameter($parameterName, $default = NULL) {
|
||||
$parameter = getGetParameter($parameterName);
|
||||
|
||||
return handleOptionalParameter($parameter, $default);
|
||||
}
|
||||
|
||||
function getMandatoryGetParameter($parameterName, $message = '', $json = false) {
|
||||
$parameter = getGetParameter($parameterName);
|
||||
|
||||
return handleMandatoryParameter($parameterName, $parameter, $message, $json);
|
||||
}
|
||||
|
||||
function handleOptionalParameter($parameter, $default) {
|
||||
if (!isset($parameter) || is_null($parameter) || empty($parameter)) {
|
||||
$parameter = $default;
|
||||
}
|
||||
return $parameter;
|
||||
}
|
||||
|
||||
function handleMandatoryParameter($parameterName, $parameter, $message, $json) {
|
||||
if (!isset($parameter) || is_null($parameter) || empty($parameter)) {
|
||||
if (empty($message) || is_null($message)) {
|
||||
if ($json) {
|
||||
$message = ['msg' => 'Missing parameter.', 'parameters' => ['missing_parameter' => $parameterName]];
|
||||
} else {
|
||||
$message = 'Missing mandatory parameter "'.$parameterName.'".';
|
||||
}
|
||||
}
|
||||
if (!$json) {
|
||||
sendHttpReturnCodeAndMessage(400, $message);
|
||||
} else {
|
||||
sendHttpReturnCodeAndJson(400, $message);
|
||||
}
|
||||
}
|
||||
return $parameter;
|
||||
}
|
||||
?>
|
||||
?>
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
return [
|
||||
'spec' => '0.3',
|
||||
'impl' => '0.3-dev'
|
||||
];
|
|
@ -13,7 +13,7 @@ function getJidDomain($jid) {
|
|||
|
||||
if ($slashIndex !== false) {
|
||||
if ($slashIndex > $atIndex) {// 'local@domain.foo/resource' and 'local@domain.foo/res@otherres' case
|
||||
return substr($jid, $atIndex + 1, $slashIndex - $atIndex - 1);
|
||||
return substr($jid, $atIndex + 1, $slashIndex - $atIndex + 1);
|
||||
} else {// 'domain.foo/res@otherres' case
|
||||
return substr($jid, 0, $slashIndex);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue