comparison mod_http_upload/mod_http_upload.lua @ 2767:e1edf643fbb1

mod_http_upload: Send a correct response on namespace :0. Fixes #968.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 19 Sep 2017 22:07:51 +0200
parents 46b29a377bdf
children 8d9aed6d1f87
comparison
equal deleted inserted replaced
2766:314cebb3071e 2767:e1edf643fbb1
112 local function handle_request(origin, stanza, xmlns, filename, filesize) 112 local function handle_request(origin, stanza, xmlns, filename, filesize)
113 local username, host = origin.username, origin.host; 113 local username, host = origin.username, origin.host;
114 -- local clients only 114 -- local clients only
115 if origin.type ~= "c2s" then 115 if origin.type ~= "c2s" then
116 module:log("debug", "Request for upload slot from a %s", origin.type); 116 module:log("debug", "Request for upload slot from a %s", origin.type);
117 origin.send(st.error_reply(stanza, "cancel", "not-authorized")); 117 return nil, st.error_reply(stanza, "cancel", "not-authorized");
118 return true;
119 end 118 end
120 -- validate 119 -- validate
121 if not filename or filename:find("/") then 120 if not filename or filename:find("/") then
122 module:log("debug", "Filename %q not allowed", filename or ""); 121 module:log("debug", "Filename %q not allowed", filename or "");
123 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid filename")); 122 return nil, st.error_reply(stanza, "modify", "bad-request", "Invalid filename");
124 return true;
125 end 123 end
126 expire(username, host); 124 expire(username, host);
127 if not filesize then 125 if not filesize then
128 module:log("debug", "Missing file size"); 126 module:log("debug", "Missing file size");
129 origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size")); 127 return nil, st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size");
130 return true;
131 elseif filesize > file_size_limit then 128 elseif filesize > file_size_limit then
132 module:log("debug", "File too large (%d > %d)", filesize, file_size_limit); 129 module:log("debug", "File too large (%d > %d)", filesize, file_size_limit);
133 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "File too large") 130 return nil, st.error_reply(stanza, "modify", "not-acceptable", "File too large")
134 :tag("file-too-large", {xmlns=xmlns}) 131 :tag("file-too-large", {xmlns=xmlns})
135 :tag("max-file-size"):text(tostring(file_size_limit))); 132 :tag("max-file-size"):text(tostring(file_size_limit));
136 return true;
137 elseif not check_quota(username, host, filesize) then 133 elseif not check_quota(username, host, filesize) then
138 module:log("debug", "Upload of %dB by %s would exceed quota", filesize, origin.full_jid); 134 module:log("debug", "Upload of %dB by %s would exceed quota", filesize, origin.full_jid);
139 origin.send(st.error_reply(stanza, "wait", "resource-constraint", "Quota reached")); 135 return nil, st.error_reply(stanza, "wait", "resource-constraint", "Quota reached");
140 return true; 136 end
141 end
142
143 local reply = st.reply(stanza);
144 reply:tag("slot", { xmlns = xmlns });
145 137
146 local random_dir; 138 local random_dir;
147 repeat random_dir = uuid(); 139 repeat random_dir = uuid();
148 until lfs.mkdir(join_path(storage_path, random_dir)) 140 until lfs.mkdir(join_path(storage_path, random_dir))
149 or not lfs.attributes(join_path(storage_path, random_dir, filename)) 141 or not lfs.attributes(join_path(storage_path, random_dir, filename))
150 142
151 local ok = datamanager.list_append(username, host, module.name, { 143 local ok = datamanager.list_append(username, host, module.name, {
152 filename = filename, dir = random_dir, size = filesize, time = os.time() }); 144 filename = filename, dir = random_dir, size = filesize, time = os.time() });
153 145
154 if not ok then 146 if not ok then
155 origin.send(st.error_reply(stanza, "wait", "internal-server-failure")); 147 return nil, st.error_reply(stanza, "wait", "internal-server-failure");
156 return true;
157 end 148 end
158 149
159 local slot = random_dir.."/"..filename; 150 local slot = random_dir.."/"..filename;
160 pending_slots[slot] = origin.full_jid; 151 pending_slots[slot] = origin.full_jid;
161 152
162 module:add_timer(900, function() 153 module:add_timer(900, function()
163 pending_slots[slot] = nil; 154 pending_slots[slot] = nil;
164 end); 155 end);
156
157 origin.log("debug", "Given upload slot %q", slot);
165 158
166 local base_url = module:http_url(); 159 local base_url = module:http_url();
167 local slot_url = url.parse(base_url); 160 local slot_url = url.parse(base_url);
168 slot_url.path = url.parse_path(slot_url.path or "/"); 161 slot_url.path = url.parse_path(slot_url.path or "/");
169 t_insert(slot_url.path, random_dir); 162 t_insert(slot_url.path, random_dir);
170 t_insert(slot_url.path, filename); 163 t_insert(slot_url.path, filename);
171 slot_url.path.is_directory = false; 164 slot_url.path.is_directory = false;
172 slot_url.path = url.build_path(slot_url.path); 165 slot_url.path = url.build_path(slot_url.path);
173 slot_url = url.build(slot_url); 166 slot_url = url.build(slot_url);
174 reply:tag("get"):text(slot_url):up(); 167 return slot_url;
175 reply:tag("put"):text(slot_url):up();
176 origin.send(reply);
177 origin.log("debug", "Given upload slot %q", slot);
178 return true;
179 end 168 end
180 169
181 -- hooks 170 -- hooks
182 module:hook("iq/host/"..namespace..":request", function (event) 171 module:hook("iq/host/"..namespace..":request", function (event)
183 local stanza, origin = event.stanza, event.origin; 172 local stanza, origin = event.stanza, event.origin;
184 local request = stanza.tags[1]; 173 local request = stanza.tags[1];
185 local filename = request.attr.filename; 174 local filename = request.attr.filename;
186 local filesize = tonumber(request.attr.size); 175 local filesize = tonumber(request.attr.size);
187 return handle_request(origin, stanza, namespace, filename, filesize); 176
177 local slot_url, err = handle_request(origin, stanza, namespace, filename, filesize);
178 if not slot_url then
179 origin.send(err);
180 return true;
181 end
182
183 local reply = st.reply(stanza)
184 :tag("slot", { xmlns = namespace })
185 :tag("get", { url = slot_url }):up()
186 :tag("put", { url = slot_url }):up()
187 :up();
188 origin.send(reply);
189 return true;
188 end); 190 end);
189 191
190 module:hook("iq/host/"..legacy_namespace..":request", function (event) 192 module:hook("iq/host/"..legacy_namespace..":request", function (event)
191 local stanza, origin = event.stanza, event.origin; 193 local stanza, origin = event.stanza, event.origin;
192 local request = stanza.tags[1]; 194 local request = stanza.tags[1];
193 local filename = request:get_child_text("filename"); 195 local filename = request:get_child_text("filename");
194 local filesize = tonumber(request:get_child_text("size")); 196 local filesize = tonumber(request:get_child_text("size"));
195 return handle_request(origin, stanza, legacy_namespace, filename, filesize); 197
198 local slot_url, err = handle_request(origin, stanza, legacy_namespace, filename, filesize);
199 if not slot_url then
200 origin.send(err);
201 return true;
202 end
203
204 local reply = st.reply(stanza)
205 :tag("slot", { xmlns = legacy_namespace })
206 :tag("get"):text(slot_url):up()
207 :tag("put"):text(slot_url):up()
208 :up();
209 origin.send(reply);
210 return true;
196 end); 211 end);
197 212
198 -- http service 213 -- http service
199 local function upload_data(event, path) 214 local function upload_data(event, path)
200 local uploader = pending_slots[path]; 215 local uploader = pending_slots[path];