comparison mod_http_upload_external/mod_http_upload_external.lua @ 2978:ac99a04231b1

mod_http_upload_external: Add newer 'v2' protocol (and share_v2.php) which supports content-type preservation
author Matthew Wild <mwild1@gmail.com>
date Mon, 02 Apr 2018 10:57:17 +0100
parents 280305c043b0
children 7af4776a5dea
comparison
equal deleted inserted replaced
2977:7036e82f83f5 2978:ac99a04231b1
12 local dataform = require "util.dataforms".new; 12 local dataform = require "util.dataforms".new;
13 local HMAC = require "util.hashes".hmac_sha256; 13 local HMAC = require "util.hashes".hmac_sha256;
14 14
15 -- config 15 -- config
16 local file_size_limit = module:get_option_number(module.name .. "_file_size_limit", 100 * 1024 * 1024); -- 100 MB 16 local file_size_limit = module:get_option_number(module.name .. "_file_size_limit", 100 * 1024 * 1024); -- 100 MB
17 local base_url = assert(module:get_option_string(module.name .. "_base_url"), module.name .. "_base_url is a required option"); 17 local base_url = assert(module:get_option_string(module.name .. "_base_url"),
18 local secret = assert(module:get_option_string(module.name .. "_secret"), module.name .. "_secret is a required option"); 18 module.name .. "_base_url is a required option");
19 local secret = assert(module:get_option_string(module.name .. "_secret"),
20 module.name .. "_secret is a required option");
21
22 local token_protocol = module:get_option_string(module.name .. "_protocol", "v1");
19 23
20 -- depends 24 -- depends
21 module:depends("disco"); 25 module:depends("disco");
22 26
23 -- namespace 27 -- namespace
37 module:add_extension(dataform { 41 module:add_extension(dataform {
38 { name = "FORM_TYPE", type = "hidden", value = legacy_namespace }, 42 { name = "FORM_TYPE", type = "hidden", value = legacy_namespace },
39 { name = "max-file-size", type = "text-single" }, 43 { name = "max-file-size", type = "text-single" },
40 }:form({ ["max-file-size"] = tostring(file_size_limit) }, "result")); 44 }:form({ ["max-file-size"] = tostring(file_size_limit) }, "result"));
41 45
42 local function magic_crypto_dust(random, filename, filesize) 46 local function magic_crypto_dust(random, filename, filesize, filetype)
43 local message = string.format("%s/%s %d", random, filename, filesize); 47 local param, message;
48 if token_protocol == "v1" then
49 param, message = "v", string.format("%s/%s %d", random, filename, filesize);
50 else
51 param, message = "v2", string.format("%s/%s\0%d\0%s", random, filename, filesize, filetype);
52 end
44 local digest = HMAC(secret, message, true); 53 local digest = HMAC(secret, message, true);
45 random, filename = http.urlencode(random), http.urlencode(filename); 54 random, filename = http.urlencode(random), http.urlencode(filename);
46 return base_url .. random .. "/" .. filename, "?v=" .. digest; 55 return base_url .. random .. "/" .. filename, "?"..param.."=" .. digest;
47 end 56 end
48 57
49 local function handle_request(origin, stanza, xmlns, filename, filesize) 58 local function handle_request(origin, stanza, xmlns, filename, filesize, filetype)
50 -- local clients only 59 -- local clients only
51 if origin.type ~= "c2s" then 60 if origin.type ~= "c2s" then
52 module:log("debug", "Request for upload slot from a %s", origin.type); 61 module:log("debug", "Request for upload slot from a %s", origin.type);
53 origin.send(st.error_reply(stanza, "cancel", "not-authorized")); 62 origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
54 return nil, nil; 63 return nil, nil;
69 st.stanza("file-too-large", {xmlns=xmlns}) 78 st.stanza("file-too-large", {xmlns=xmlns})
70 :tag("max-size"):text(tostring(file_size_limit)))); 79 :tag("max-size"):text(tostring(file_size_limit))));
71 return nil, nil; 80 return nil, nil;
72 end 81 end
73 local random = uuid(); 82 local random = uuid();
74 local get_url, verify = magic_crypto_dust(random, filename, filesize); 83 local get_url, verify = magic_crypto_dust(random, filename, filesize, filetype);
75 local put_url = get_url .. verify; 84 local put_url = get_url .. verify;
76 85
77 module:log("info", "Handing out upload slot %s to %s@%s", get_url, origin.username, origin.host); 86 module:log("info", "Handing out upload slot %s to %s@%s", get_url, origin.username, origin.host);
78 87
79 return get_url, put_url; 88 return get_url, put_url;
83 module:hook("iq/host/"..legacy_namespace..":request", function (event) 92 module:hook("iq/host/"..legacy_namespace..":request", function (event)
84 local stanza, origin = event.stanza, event.origin; 93 local stanza, origin = event.stanza, event.origin;
85 local request = stanza.tags[1]; 94 local request = stanza.tags[1];
86 local filename = request:get_child_text("filename"); 95 local filename = request:get_child_text("filename");
87 local filesize = tonumber(request:get_child_text("size")); 96 local filesize = tonumber(request:get_child_text("size"));
97 local filetype = request.attr["content-type"] or "application/octet-stream";
88 98
89 local get_url, put_url = handle_request( 99 local get_url, put_url = handle_request(
90 origin, stanza, legacy_namespace, filename, filesize); 100 origin, stanza, legacy_namespace, filename, filesize, filetype);
91 101
92 if not get_url then 102 if not get_url then
93 -- error was already sent 103 -- error was already sent
94 return true; 104 return true;
95 end 105 end
106 module:hook("iq/host/"..namespace..":request", function (event) 116 module:hook("iq/host/"..namespace..":request", function (event)
107 local stanza, origin = event.stanza, event.origin; 117 local stanza, origin = event.stanza, event.origin;
108 local request = stanza.tags[1]; 118 local request = stanza.tags[1];
109 local filename = request.attr.filename; 119 local filename = request.attr.filename;
110 local filesize = tonumber(request.attr.size); 120 local filesize = tonumber(request.attr.size);
121 local filetype = request.attr["content-type"] or "application/octet-stream";
122
111 local get_url, put_url = handle_request( 123 local get_url, put_url = handle_request(
112 origin, stanza, namespace, filename, filesize); 124 origin, stanza, namespace, filename, filesize, filetype);
113 125
114 if not get_url then 126 if not get_url then
115 -- error was already sent 127 -- error was already sent
116 return true; 128 return true;
117 end 129 end