Comparison

mod_http_upload/mod_http_upload.lua @ 2687:5f0b755b42a3

Backed out changeset e491a15d7621 (closes #888)
author Kim Alvefur <zash@zash.se>
date Sat, 15 Apr 2017 15:35:55 +0200
parent 2684:e491a15d7621
child 2688:ef80c9d0ebff
comparison
equal deleted inserted replaced
2686:39cb2a51e779 2687:5f0b755b42a3
10 -- imports 10 -- imports
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";
16 local array = require "util.array";
15 local t_concat = table.concat; 17 local t_concat = table.concat;
16 local t_insert = table.insert; 18 local t_insert = table.insert;
17 local s_upper = string.upper; 19 local s_upper = string.upper;
18 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+
19 local uuid = require"util.uuid".generate; 21 local uuid = require"util.uuid".generate;
65 { name = "max-file-size", type = "text-single" }, 67 { name = "max-file-size", type = "text-single" },
66 }:form({ ["max-file-size"] = tostring(file_size_limit) }, "result")); 68 }:form({ ["max-file-size"] = tostring(file_size_limit) }, "result"));
67 69
68 -- state 70 -- state
69 local pending_slots = module:shared("upload_slots"); 71 local pending_slots = module:shared("upload_slots");
70 local used_slots = module:open_store();
71 local slot_map = module:open_store(nil, "map");
72 72
73 local storage_path = module:get_option_string(module.name .. "_path", join_path(prosody.paths.data, module.name)); 73 local storage_path = module:get_option_string(module.name .. "_path", join_path(prosody.paths.data, module.name));
74 lfs.mkdir(storage_path); 74 lfs.mkdir(storage_path);
75 75
76 local function k(u, h) return h ~= module.host and u .. "@" .. h or u; end
77
78 local function expire(username, host) 76 local function expire(username, host)
79 if not max_age then return true; end 77 if not max_age then return true; end
80 local uploads, err = used_slots:get(k(username, host)); 78 local uploads, err = datamanager.list_load(username, host, module.name);
81 if not uploads then return true; end 79 if not uploads then return true; end
80 uploads = array(uploads);
82 local expiry = os.time() - max_age; 81 local expiry = os.time() - max_age;
83 local upload_window = os.time() - 900; 82 uploads:filter(function (item)
84 for slot, item in pairs(uploads) do
85 local full_filename = join_path(storage_path, item.dir, item.filename);
86 if item.time < expiry then 83 if item.time < expiry then
87 local deleted, whynot = os.remove(full_filename); 84 local deleted, whynot = os.remove(item.filename);
88 if deleted then 85 if not deleted then
89 module:log("debug", "Deleted expired upload %s", item.filename);
90 else
91 module:log("warn", "Could not delete expired upload %s: %s", item.filename, whynot or "delete failed"); 86 module:log("warn", "Could not delete expired upload %s: %s", item.filename, whynot or "delete failed");
92 end 87 end
93 uploads[slot] = nil; 88 return false;
94 elseif item.time < upload_window and not lfs.attributes(full_filename) then
95 pending_slots[slot] = nil;
96 uploads[slot] = nil;
97 end 89 end
98 end 90 return true;
99 return used_slots:set(k(username, host), uploads); 91 end);
92 return datamanager.list_store(username, host, module.name, uploads);
100 end 93 end
101 94
102 local function check_quota(username, host, does_it_fit) 95 local function check_quota(username, host, does_it_fit)
103 if not quota then return true; end 96 if not quota then return true; end
104 local uploads, err = used_slots:get(k(username, host)); 97 local uploads, err = datamanager.list_load(username, host, module.name);
105 if not uploads then return true; end 98 if not uploads then return true; end
106 local sum = does_it_fit or 0; 99 local sum = does_it_fit or 0;
107 for _, item in pairs(uploads) do 100 for _, item in ipairs(uploads) do
108 sum = sum + item.size; 101 sum = sum + item.size;
109 end 102 end
110 return sum < quota; 103 return sum < quota;
111 end 104 end
112 105
161 local random_dir; 154 local random_dir;
162 repeat random_dir = uuid(); 155 repeat random_dir = uuid();
163 until lfs.mkdir(join_path(storage_path, random_dir)) 156 until lfs.mkdir(join_path(storage_path, random_dir))
164 or not lfs.attributes(join_path(storage_path, random_dir, filename)) 157 or not lfs.attributes(join_path(storage_path, random_dir, filename))
165 158
166 local key = k(origin.username, origin.host); 159 datamanager.list_append(origin.username, origin.host, module.name, {
160 filename = join_path(storage_path, random_dir, filename), size = filesize, time = os.time() });
167 local slot = random_dir.."/"..filename; 161 local slot = random_dir.."/"..filename;
168 local ok = slot_map:set(key, slot, {
169 filename = filename, dir = random_dir, size = filesize, time = os.time()
170 });
171 if not ok then
172 origin.send(st.error_reply(stanza, "wait", "internal-server-failure"));
173 return true;
174 end
175 pending_slots[slot] = origin.full_jid; 162 pending_slots[slot] = origin.full_jid;
176 163
177 module:add_timer(900, function() 164 module:add_timer(900, function()
178 pending_slots[slot] = nil; 165 pending_slots[slot] = nil;
179 if not lfs.attributes(join_path(storage_path, slot)) then
180 slot_map:set(key, slot, nil);
181 end
182 end); 166 end);
183 167
184 local base_url = module:http_url(); 168 local base_url = module:http_url();
185 local slot_url = url.parse(base_url); 169 local slot_url = url.parse(base_url);
186 slot_url.path = url.parse_path(slot_url.path or "/"); 170 slot_url.path = url.parse_path(slot_url.path or "/");
258 return 201; 242 return 201;
259 end 243 end
260 244
261 -- FIXME Duplicated from net.http.server 245 -- FIXME Duplicated from net.http.server
262 246
263 -- luacheck: ignore 431/k
264 local codes = require "net.http.codes"; 247 local codes = require "net.http.codes";
265 local headerfix = setmetatable({}, { 248 local headerfix = setmetatable({}, {
266 __index = function(t, k) 249 __index = function(t, k)
267 local v = "\r\n"..k:gsub("_", "-"):gsub("%f[%w].", s_upper)..": "; 250 local v = "\r\n"..k:gsub("_", "-"):gsub("%f[%w].", s_upper)..": ";
268 t[k] = v; 251 t[k] = v;