Mercurial > prosody-modules
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 |