comparison mod_http_upload/mod_http_upload.lua @ 2731:d48faff92490

mod_http_upload: Remove MIME type restrictions and checking (fixes #958)
author Kim Alvefur <zash@zash.se>
date Sat, 22 Jul 2017 23:14:13 +0200
parents 785465f8af3d
children b1c5b0c369c2
comparison
equal deleted inserted replaced
2730:cd828b1cb5b9 2731:d48faff92490
29 29
30 -- config 30 -- config
31 local file_size_limit = module:get_option_number(module.name .. "_file_size_limit", 1024 * 1024); -- 1 MB 31 local file_size_limit = module:get_option_number(module.name .. "_file_size_limit", 1024 * 1024); -- 1 MB
32 local quota = module:get_option_number(module.name .. "_quota"); 32 local quota = module:get_option_number(module.name .. "_quota");
33 local max_age = module:get_option_number(module.name .. "_expire_after"); 33 local max_age = module:get_option_number(module.name .. "_expire_after");
34 local allowed_file_types = module:get_option_set(module.name .. "_allowed_file_types");
35 34
36 --- sanity 35 --- sanity
37 local parser_body_limit = module:context("*"):get_option_number("http_max_content_size", 10*1024*1024); 36 local parser_body_limit = module:context("*"):get_option_number("http_max_content_size", 10*1024*1024);
38 if file_size_limit > parser_body_limit then 37 if file_size_limit > parser_body_limit then
39 module:log("warn", "%s_file_size_limit exceeds HTTP parser limit on body size, capping file size to %d B", 38 module:log("warn", "%s_file_size_limit exceeds HTTP parser limit on body size, capping file size to %d B",
44 -- depends 43 -- depends
45 module:depends("http"); 44 module:depends("http");
46 module:depends("disco"); 45 module:depends("disco");
47 46
48 local http_files = module:depends("http_files"); 47 local http_files = module:depends("http_files");
49 local mime_map = module:shared("/*/http_files/mime").types;
50 48
51 -- namespaces 49 -- namespaces
52 local namespace = "urn:xmpp:http:upload:0"; 50 local namespace = "urn:xmpp:http:upload:0";
53 local legacy_namespace = "urn:xmpp:http:upload"; 51 local legacy_namespace = "urn:xmpp:http:upload";
54 52
108 sum = sum + item.size; 106 sum = sum + item.size;
109 end 107 end
110 return sum < quota; 108 return sum < quota;
111 end 109 end
112 110
113 local function handle_request(origin, stanza, xmlns, filename, filesize, mimetype) 111 local function handle_request(origin, stanza, xmlns, filename, filesize)
114 local username, host = origin.username, origin.host; 112 local username, host = origin.username, origin.host;
115 -- local clients only 113 -- local clients only
116 if origin.type ~= "c2s" then 114 if origin.type ~= "c2s" then
117 module:log("debug", "Request for upload slot from a %s", origin.type); 115 module:log("debug", "Request for upload slot from a %s", origin.type);
118 origin.send(st.error_reply(stanza, "cancel", "not-authorized")); 116 origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
137 return true; 135 return true;
138 elseif not check_quota(username, host, filesize) then 136 elseif not check_quota(username, host, filesize) then
139 module:log("debug", "Upload of %dB by %s would exceed quota", filesize, origin.full_jid); 137 module:log("debug", "Upload of %dB by %s would exceed quota", filesize, origin.full_jid);
140 origin.send(st.error_reply(stanza, "wait", "resource-constraint", "Quota reached")); 138 origin.send(st.error_reply(stanza, "wait", "resource-constraint", "Quota reached"));
141 return true; 139 return true;
142 end
143
144 if mime_map then
145 local file_ext = filename:match("%.([^.]+)$");
146 if not mimetype then
147 mimetype = "application/octet-stream";
148 if file_ext then
149 mimetype = mime_map[file_ext] or mimetype;
150 end
151 else
152 if (not file_ext and mimetype ~= "application/octet-stream") or (file_ext and mime_map[file_ext] ~= mimetype) then
153 origin.send(st.error_reply(stanza, "modify", "bad-request", "MIME type does not match file extension"));
154 return true;
155 end
156 end
157 end
158
159 if allowed_file_types then
160 if not (allowed_file_types:contains(mimetype) or allowed_file_types:contains(mimetype:gsub("/.*", "/*"))) then
161 origin.send(st.error_reply(stanza, "cancel", "not-allowed", "File type not allowed"));
162 return true;
163 end
164 end 140 end
165 141
166 local reply = st.reply(stanza); 142 local reply = st.reply(stanza);
167 reply:tag("slot", { xmlns = xmlns }); 143 reply:tag("slot", { xmlns = xmlns });
168 144
205 module:hook("iq/host/"..namespace..":request", function (event) 181 module:hook("iq/host/"..namespace..":request", function (event)
206 local stanza, origin = event.stanza, event.origin; 182 local stanza, origin = event.stanza, event.origin;
207 local request = stanza.tags[1]; 183 local request = stanza.tags[1];
208 local filename = request.attr.filename; 184 local filename = request.attr.filename;
209 local filesize = tonumber(request.attr.size); 185 local filesize = tonumber(request.attr.size);
210 local mimetype = request.attr["content-type"]; 186 return handle_request(origin, stanza, namespace, filename, filesize);
211 return handle_request(origin, stanza, namespace, filename, filesize, mimetype);
212 end); 187 end);
213 188
214 module:hook("iq/host/"..legacy_namespace..":request", function (event) 189 module:hook("iq/host/"..legacy_namespace..":request", function (event)
215 local stanza, origin = event.stanza, event.origin; 190 local stanza, origin = event.stanza, event.origin;
216 local request = stanza.tags[1]; 191 local request = stanza.tags[1];
217 local filename = request:get_child_text("filename"); 192 local filename = request:get_child_text("filename");
218 local filesize = tonumber(request:get_child_text("size")); 193 local filesize = tonumber(request:get_child_text("size"));
219 local mimetype = request:get_child_text("content-type"); 194 return handle_request(origin, stanza, legacy_namespace, filename, filesize);
220 return handle_request(origin, stanza, legacy_namespace, filename, filesize, mimetype);
221 end); 195 end);
222 196
223 -- http service 197 -- http service
224 local function upload_data(event, path) 198 local function upload_data(event, path)
225 local uploader = pending_slots[path]; 199 local uploader = pending_slots[path];