# HG changeset patch # User Jonas Wielicki # Date 1518361877 -3600 # Node ID d6badf56ab5f96b7b193e10ee894dd04dc4686e8 # Parent ea6b5321db500b7f08c670e654de39234c13e6de mod_http_upload_external: add support for XEP-0363 version 0.3 diff -r ea6b5321db50 -r d6badf56ab5f mod_http_upload_external/mod_http_upload_external.lua --- a/mod_http_upload_external/mod_http_upload_external.lua Sun Feb 04 16:05:27 2018 +0100 +++ b/mod_http_upload_external/mod_http_upload_external.lua Sun Feb 11 16:11:17 2018 +0100 @@ -21,14 +21,21 @@ module:depends("disco"); -- namespace -local xmlns_http_upload = "urn:xmpp:http:upload"; +local legacy_namespace = "urn:xmpp:http:upload"; +local namespace = "urn:xmpp:http:upload:0"; -- identity and feature advertising module:add_identity("store", "file", module:get_option_string("name", "HTTP File Upload")) -module:add_feature(xmlns_http_upload); +module:add_feature(namespace); +module:add_feature(legacy_namespace); module:add_extension(dataform { - { name = "FORM_TYPE", type = "hidden", value = xmlns_http_upload }, + { name = "FORM_TYPE", type = "hidden", value = namespace }, + { name = "max-file-size", type = "text-single" }, +}:form({ ["max-file-size"] = tostring(file_size_limit) }, "result")); + +module:add_extension(dataform { + { name = "FORM_TYPE", type = "hidden", value = legacy_namespace }, { name = "max-file-size", type = "text-single" }, }:form({ ["max-file-size"] = tostring(file_size_limit) }, "result")); @@ -39,42 +46,81 @@ return base_url .. random .. "/" .. filename, "?v=" .. digest; end --- hooks -module:hook("iq/host/"..xmlns_http_upload..":request", function (event) - local stanza, origin = event.stanza, event.origin; - local request = stanza.tags[1]; +local function handle_request(origin, stanza, xmlns, filename, filesize) -- local clients only if origin.type ~= "c2s" then module:log("debug", "Request for upload slot from a %s", origin.type); origin.send(st.error_reply(stanza, "cancel", "not-authorized")); - return true; + return nil, nil; end -- validate - local filename = request:get_child_text("filename"); if not filename or filename:find("/") then module:log("debug", "Filename %q not allowed", filename or ""); origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename")); - return true; + return nil, nil; end - local filesize = tonumber(request:get_child_text("size")); if not filesize then module:log("debug", "Missing file size"); origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size")); - return true; + return nil, nil; elseif filesize > file_size_limit then module:log("debug", "File too large (%d > %d)", filesize, file_size_limit); origin.send(st.error_reply(stanza, "modify", "not-acceptable", "File too large", - st.stanza("file-too-large", {xmlns=xmlns_http_upload}) + st.stanza("file-too-large", {xmlns=xmlns}) :tag("max-size"):text(tostring(file_size_limit)))); + return nil, nil; + end + local random = uuid(); + local get_url, verify = magic_crypto_dust(random, filename, filesize); + local put_url = get_url .. verify; + + module:log("info", "Handing out upload slot %s to %s@%s", get_url, origin.username, origin.host); + + return get_url, put_url; +end + +-- hooks +module:hook("iq/host/"..legacy_namespace..":request", function (event) + local stanza, origin = event.stanza, event.origin; + local request = stanza.tags[1]; + local filename = request:get_child_text("filename"); + local filesize = tonumber(request:get_child_text("size")); + + local get_url, put_url = handle_request( + origin, stanza, legacy_namespace, filename, filesize); + + if not get_url then + -- error was already sent return true; end - local reply = st.reply(stanza); - reply:tag("slot", { xmlns = xmlns_http_upload }); - local random = uuid(); - local get_url, verify = magic_crypto_dust(random, filename, filesize); - reply:tag("get"):text(get_url):up(); - reply:tag("put"):text(get_url .. verify):up(); - module:log("info", "Handed out upload slot %s to %s@%s", get_url, origin.username, origin.host); + + local reply = st.reply(stanza) + :tag("slot", { xmlns = legacy_namespace }) + :tag("get"):text(get_url):up() + :tag("put"):text(put_url):up() + :up(); origin.send(reply); return true; end); + +module:hook("iq/host/"..namespace..":request", function (event) + local stanza, origin = event.stanza, event.origin; + local request = stanza.tags[1]; + local filename = request.attr.filename; + local filesize = tonumber(request.attr.size); + local get_url, put_url = handle_request( + origin, stanza, legacy_namespace, filename, filesize); + + if not get_url then + -- error was already sent + return true; + end + + local reply = st.reply(stanza) + :tag("slot", { xmlns = namespace}) + :tag("get", { url = get_url }):up() + :tag("put", { url = put_url }):up() + :up(); + origin.send(reply); + return true; +end);