comparison mod_http_upload/mod_http_upload.lua @ 2677:6daaa1ad2559

mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
author Kim Alvefur <zash@zash.se>
date Thu, 13 Apr 2017 16:31:00 +0200
parents 0c7802b95820
children 2dec7cad9218
comparison
equal deleted inserted replaced
2676:1b081c8fc1d9 2677:6daaa1ad2559
1 -- mod_http_upload 1 -- mod_http_upload
2 -- 2 --
3 -- Copyright (C) 2015 Kim Alvefur 3 -- Copyright (C) 2015-2017 Kim Alvefur
4 -- 4 --
5 -- This file is MIT/X11 licensed. 5 -- This file is MIT/X11 licensed.
6 -- 6 --
7 -- Implementation of HTTP Upload file transfer mechanism used by Conversations 7 -- Implementation of HTTP Upload file transfer mechanism used by Conversations
8 -- 8 --
11 local st = require"util.stanza"; 11 local st = require"util.stanza";
12 local lfs = require"lfs"; 12 local lfs = require"lfs";
13 local url = require "socket.url"; 13 local url = require "socket.url";
14 local dataform = require "util.dataforms".new; 14 local dataform = require "util.dataforms".new;
15 local datamanager = require "util.datamanager"; 15 local datamanager = require "util.datamanager";
16 local array = require "util.array";
16 local t_concat = table.concat; 17 local t_concat = table.concat;
17 local t_insert = table.insert; 18 local t_insert = table.insert;
18 local s_upper = string.upper; 19 local s_upper = string.upper;
19 local have_id, id = pcall(require, "util.id"); -- Only available in 0.10+ 20 local have_id, id = pcall(require, "util.id"); -- Only available in 0.10+
20 local uuid = require"util.uuid".generate; 21 local uuid = require"util.uuid".generate;
26 return table.concat({ ... }, package.config:sub(1,1)); 27 return table.concat({ ... }, package.config:sub(1,1));
27 end 28 end
28 29
29 -- config 30 -- config
30 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 max_age = module:get_option_number(module.name .. "_expire_after");
31 33
32 --- sanity 34 --- sanity
33 local parser_body_limit = module:context("*"):get_option_number("http_max_content_size", 10*1024*1024); 35 local parser_body_limit = module:context("*"):get_option_number("http_max_content_size", 10*1024*1024);
34 if file_size_limit > parser_body_limit then 36 if file_size_limit > parser_body_limit then
35 module:log("warn", "%s_file_size_limit exceeds HTTP parser limit on body size, capping file size to %d B", 37 module:log("warn", "%s_file_size_limit exceeds HTTP parser limit on body size, capping file size to %d B",
64 local pending_slots = module:shared("upload_slots"); 66 local pending_slots = module:shared("upload_slots");
65 67
66 local storage_path = module:get_option_string(module.name .. "_path", join_path(prosody.paths.data, module.name)); 68 local storage_path = module:get_option_string(module.name .. "_path", join_path(prosody.paths.data, module.name));
67 lfs.mkdir(storage_path); 69 lfs.mkdir(storage_path);
68 70
71 local function expire(username, host)
72 if not max_age then return true; end
73 local uploads, err = datamanager.list_load(username, host, module.name);
74 if not uploads then return true; end
75 uploads = array(uploads);
76 local expiry = os.time() - max_age;
77 uploads:filter(function (item)
78 if item.time < expiry then
79 local deleted, whynot = os.remove(item.filename);
80 if deleted then
81 return false;
82 else
83 module:log("warn", "Could not delete expired upload %s: %s", item.filename, whynot or "delete failed");
84 end
85 end
86 return true;
87 end);
88 return datamanager.list_store(username, host, module.name, uploads);
89 end
90
69 local function handle_request(origin, stanza, xmlns, filename, filesize) 91 local function handle_request(origin, stanza, xmlns, filename, filesize)
70 -- local clients only 92 -- local clients only
71 if origin.type ~= "c2s" then 93 if origin.type ~= "c2s" then
72 module:log("debug", "Request for upload slot from a %s", origin.type); 94 module:log("debug", "Request for upload slot from a %s", origin.type);
73 origin.send(st.error_reply(stanza, "cancel", "not-authorized")); 95 origin.send(st.error_reply(stanza, "cancel", "not-authorized"));
77 if not filename or filename:find("/") then 99 if not filename or filename:find("/") then
78 module:log("debug", "Filename %q not allowed", filename or ""); 100 module:log("debug", "Filename %q not allowed", filename or "");
79 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename")); 101 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename"));
80 return true; 102 return true;
81 end 103 end
104 expire(origin.username, origin.host);
82 if not filesize then 105 if not filesize then
83 module:log("debug", "Missing file size"); 106 module:log("debug", "Missing file size");
84 origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size")); 107 origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size"));
85 return true; 108 return true;
86 elseif filesize > file_size_limit then 109 elseif filesize > file_size_limit then