Software /
code /
prosody-modules
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 |
parent | 2738:46b29a377bdf |
child | 2800: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]; |