diff mod_http_upload_external/mod_http_upload_external.lua @ 2877:d6badf56ab5f

mod_http_upload_external: add support for XEP-0363 version 0.3
author Jonas Wielicki <jonas@wielicki.name>
date Sun, 11 Feb 2018 16:11:17 +0100
parents c2cf5b40b66d
children 280305c043b0
line wrap: on
line diff
--- 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);