mod_http_upload/mod_http_upload.lua
author Matthew Wild <mwild1@gmail.com>
Sat, 24 Sep 2022 09:26:26 +0100
changeset 5063 5f1120c284c5
parent 4980 75b6e5df65f9
permissions -rw-r--r--
mod_cloud_notify_extensions: Add note about dependency Noting here because people might not click through to see it on the mod_cloud_notify_encrypted page.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
-- mod_http_upload
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
--
3015
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
     3
-- Copyright (C) 2015-2018 Kim Alvefur
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
--
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     5
-- This file is MIT/X11 licensed.
2069
624e3fed6f92 mod_http_upload: Trim trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 2057
diff changeset
     6
--
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     7
-- Implementation of HTTP Upload file transfer mechanism used by Conversations
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     8
--
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
4658
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    10
-- depends
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    11
module:depends("http");
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    12
module:depends("disco");
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    13
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    14
if module:http_url():match("^http://") then
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    15
	error("File upload MUST happen with TLS but it isn’t enabled, see https://prosody.im/doc/http for how to fix this issue");
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    16
end
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
    17
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    18
-- imports
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    19
local st = require"util.stanza";
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    20
local lfs = require"lfs";
2290
0a3f526779a1 mod_http_upload: Construct the upload slot URL using the LuaSocket URL library (fixes #717)
Kim Alvefur <zash@zash.se>
parents: 2289
diff changeset
    21
local url = require "socket.url";
2070
cb74e4ab13f0 mod_http_upload: Advertise maximum file size in disco#info (Per XEP-0363 v0.2)
Kim Alvefur <zash@zash.se>
parents: 2069
diff changeset
    22
local dataform = require "util.dataforms".new;
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
    23
local datamanager = require "util.datamanager";
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
    24
local array = require "util.array";
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
    25
local t_concat = table.concat;
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
    26
local t_insert = table.insert;
1918
b01d60dfa405 mod_http_upload: Add missing local of string.upper (Thanks Thilo)
Kim Alvefur <zash@zash.se>
parents: 1916
diff changeset
    27
local s_upper = string.upper;
3717
53fc4b612fb2 mod_http_upload: Skip custom HEAD handling on recent Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3665
diff changeset
    28
local httpserver = require "net.http.server";
2669
cfb7936ff61f mod_http_upload: Use the new util.id if available (in 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2655
diff changeset
    29
local have_id, id = pcall(require, "util.id"); -- Only available in 0.10+
2650
45ef16ebe565 mod_http_upload: Generate shorter directory names (closes #822)
Kim Alvefur <zash@zash.se>
parents: 2645
diff changeset
    30
local uuid = require"util.uuid".generate;
4447
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
    31
local jid = require "util.jid";
2669
cfb7936ff61f mod_http_upload: Use the new util.id if available (in 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2655
diff changeset
    32
if have_id then
2670
99c0b1bacdcd mod_http_upload: Where did those parenthesis come from?
Kim Alvefur <zash@zash.se>
parents: 2669
diff changeset
    33
	uuid = id.medium;
2650
45ef16ebe565 mod_http_upload: Generate shorter directory names (closes #822)
Kim Alvefur <zash@zash.se>
parents: 2645
diff changeset
    34
end
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    35
2650
45ef16ebe565 mod_http_upload: Generate shorter directory names (closes #822)
Kim Alvefur <zash@zash.se>
parents: 2645
diff changeset
    36
local function join_path(...) -- COMPAT util.path was added in 0.10
2480
024a4143baef mod_http_upload: Add missing return statement
Kim Alvefur <zash@zash.se>
parents: 2479
diff changeset
    37
	return table.concat({ ... }, package.config:sub(1,1));
1819
abacf6698d97 mod_http_upload: Include join_path function, should make it work with 0.9.x
Kim Alvefur <zash@zash.se>
parents: 1809
diff changeset
    38
end
abacf6698d97 mod_http_upload: Include join_path function, should make it work with 0.9.x
Kim Alvefur <zash@zash.se>
parents: 1809
diff changeset
    39
1855
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
    40
-- config
2057
40056a27f394 mod_http_upload: Lower default size limit to 1MB
Kim Alvefur <zash@zash.se>
parents: 1971
diff changeset
    41
local file_size_limit = module:get_option_number(module.name .. "_file_size_limit", 1024 * 1024); -- 1 MB
2682
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
    42
local quota = module:get_option_number(module.name .. "_quota");
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
    43
local max_age = module:get_option_number(module.name .. "_expire_after");
4447
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
    44
local access = module:get_option_set(module.name .. "_access", {});
1855
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
    45
2289
f1923bf329a3 mod_http_upload: Warn if upload size limit set higher than body size limit in http parser (applies to 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2235
diff changeset
    46
--- sanity
f1923bf329a3 mod_http_upload: Warn if upload size limit set higher than body size limit in http parser (applies to 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2235
diff changeset
    47
local parser_body_limit = module:context("*"):get_option_number("http_max_content_size", 10*1024*1024);
f1923bf329a3 mod_http_upload: Warn if upload size limit set higher than body size limit in http parser (applies to 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2235
diff changeset
    48
if file_size_limit > parser_body_limit then
2652
4c92e2e897c8 mod_http_upload: Split some long lines [luacheck]
Kim Alvefur <zash@zash.se>
parents: 2651
diff changeset
    49
	module:log("warn", "%s_file_size_limit exceeds HTTP parser limit on body size, capping file size to %d B",
4c92e2e897c8 mod_http_upload: Split some long lines [luacheck]
Kim Alvefur <zash@zash.se>
parents: 2651
diff changeset
    50
		module.name, parser_body_limit);
2289
f1923bf329a3 mod_http_upload: Warn if upload size limit set higher than body size limit in http parser (applies to 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2235
diff changeset
    51
	file_size_limit = parser_body_limit;
f1923bf329a3 mod_http_upload: Warn if upload size limit set higher than body size limit in http parser (applies to 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2235
diff changeset
    52
end
f1923bf329a3 mod_http_upload: Warn if upload size limit set higher than body size limit in http parser (applies to 0.10+)
Kim Alvefur <zash@zash.se>
parents: 2235
diff changeset
    53
4080
f1f796e551f1 mod_http_upload: Log warning when loaded on user host
Matthew Wild <mwild1@gmail.com>
parents: 3966
diff changeset
    54
if prosody.hosts[module.host].type == "local" then
f1f796e551f1 mod_http_upload: Log warning when loaded on user host
Matthew Wild <mwild1@gmail.com>
parents: 3966
diff changeset
    55
	module:log("warn", "mod_%s loaded on a user host, this may be incompatible with some client software, see docs for correct usage", module.name);
f1f796e551f1 mod_http_upload: Log warning when loaded on user host
Matthew Wild <mwild1@gmail.com>
parents: 3966
diff changeset
    56
end
f1f796e551f1 mod_http_upload: Log warning when loaded on user host
Matthew Wild <mwild1@gmail.com>
parents: 3966
diff changeset
    57
3553
b059a3fb2a58 Update modules using mod_http_files to serve files for change in Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3450
diff changeset
    58
local http_files;
b059a3fb2a58 Update modules using mod_http_files to serve files for change in Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3450
diff changeset
    59
4980
75b6e5df65f9 various: Improve error reporting if missing file server module on 0.12
Kim Alvefur <zash@zash.se>
parents: 4658
diff changeset
    60
if prosody.process_type == "prosody" then
3553
b059a3fb2a58 Update modules using mod_http_files to serve files for change in Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3450
diff changeset
    61
	http_files = require "net.http.files";
4980
75b6e5df65f9 various: Improve error reporting if missing file server module on 0.12
Kim Alvefur <zash@zash.se>
parents: 4658
diff changeset
    62
else
3553
b059a3fb2a58 Update modules using mod_http_files to serve files for change in Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3450
diff changeset
    63
	http_files = module:depends"http_files";
b059a3fb2a58 Update modules using mod_http_files to serve files for change in Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3450
diff changeset
    64
end
2684
96bf67f1f960 mod_http_upload: Validate that file extension (used by mod_http_files) matches mime type given by client
Kim Alvefur <zash@zash.se>
parents: 2682
diff changeset
    65
3629
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    66
local mime_map = module:shared("/*/http_files/mime").types;
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    67
if not mime_map then
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    68
	mime_map = {
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    69
		html = "text/html", htm = "text/html",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    70
		xml = "application/xml",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    71
		txt = "text/plain",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    72
		css = "text/css",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    73
		js = "application/javascript",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    74
		png = "image/png",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    75
		gif = "image/gif",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    76
		jpeg = "image/jpeg", jpg = "image/jpeg",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    77
		svg = "image/svg+xml",
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    78
	};
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    79
	module:shared("/*/http_files/mime").types = mime_map;
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    80
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    81
	local mime_types, err = io.open(module:get_option_path("mime_types_file", "/etc/mime.types", "config"), "r");
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    82
	if mime_types then
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    83
		local mime_data = mime_types:read("*a");
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    84
		mime_types:close();
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    85
		setmetatable(mime_map, {
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    86
			__index = function(t, ext)
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    87
				local typ = mime_data:match("\n(%S+)[^\n]*%s"..(ext:lower()).."%s") or "application/octet-stream";
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    88
				t[ext] = typ;
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    89
				return typ;
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    90
			end
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    91
		});
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    92
	end
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    93
end
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
    94
2645
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
    95
-- namespaces
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
    96
local namespace = "urn:xmpp:http:upload:0";
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
    97
local legacy_namespace = "urn:xmpp:http:upload";
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    98
2291
e1a8c2324937 mod_http_upload: Add a comment
Kim Alvefur <zash@zash.se>
parents: 2290
diff changeset
    99
-- identity and feature advertising
2448
3e9f9cef9c0e mod_http_upload: Add missing semicolon
Kim Alvefur <zash@zash.se>
parents: 2447
diff changeset
   100
module:add_identity("store", "file", module:get_option_string("name", "HTTP File Upload"));
2645
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   101
module:add_feature(namespace);
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   102
module:add_feature(legacy_namespace);
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   103
2070
cb74e4ab13f0 mod_http_upload: Advertise maximum file size in disco#info (Per XEP-0363 v0.2)
Kim Alvefur <zash@zash.se>
parents: 2069
diff changeset
   104
module:add_extension(dataform {
2645
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   105
	{ name = "FORM_TYPE", type = "hidden", value = namespace },
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   106
	{ name = "max-file-size", type = "text-single" },
3652
aa12b95a6d36 mod_http_upload: Ensure integer formatting of size limit
Kim Alvefur <zash@zash.se>
parents: 3629
diff changeset
   107
}:form({ ["max-file-size"] = ("%d"):format(file_size_limit) }, "result"));
2645
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   108
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   109
module:add_extension(dataform {
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   110
	{ name = "FORM_TYPE", type = "hidden", value = legacy_namespace },
2070
cb74e4ab13f0 mod_http_upload: Advertise maximum file size in disco#info (Per XEP-0363 v0.2)
Kim Alvefur <zash@zash.se>
parents: 2069
diff changeset
   111
	{ name = "max-file-size", type = "text-single" },
3652
aa12b95a6d36 mod_http_upload: Ensure integer formatting of size limit
Kim Alvefur <zash@zash.se>
parents: 3629
diff changeset
   112
}:form({ ["max-file-size"] = ("%d"):format(file_size_limit) }, "result"));
2070
cb74e4ab13f0 mod_http_upload: Advertise maximum file size in disco#info (Per XEP-0363 v0.2)
Kim Alvefur <zash@zash.se>
parents: 2069
diff changeset
   113
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   114
-- state
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   115
local pending_slots = module:shared("upload_slots");
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   116
1971
2ce2b194d501 mod_http_upload: Make file system path configurable
Kim Alvefur <zash@zash.se>
parents: 1970
diff changeset
   117
local storage_path = module:get_option_string(module.name .. "_path", join_path(prosody.paths.data, module.name));
3665
88d414c916ee mod_http_upload: Back out 3fb0add97cdb - depends on yet uncommon lfs version
Kim Alvefur <zash@zash.se>
parents: 3663
diff changeset
   118
lfs.mkdir(storage_path);
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   119
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   120
local function expire(username, host)
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   121
	if not max_age then return true; end
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   122
	local uploads, err = datamanager.list_load(username, host, module.name);
3594
d8cc8b71a199 mod_http_upload: Propagate errors from expiry procedure
Kim Alvefur <zash@zash.se>
parents: 3593
diff changeset
   123
	if err then return false, err; end
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   124
	if not uploads then return true; end
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   125
	uploads = array(uploads);
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   126
	local expiry = os.time() - max_age;
2692
ef80c9d0ebff mod_http_upload: Remove unused upload slots
Kim Alvefur <zash@zash.se>
parents: 2691
diff changeset
   127
	local upload_window = os.time() - 900;
3663
bb8a6df5ecba mod_http_upload: Skip write if nothing expired when checking
Kim Alvefur <zash@zash.se>
parents: 3662
diff changeset
   128
	local before = #uploads;
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   129
	uploads:filter(function (item)
2695
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   130
		local filename = item.filename;
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   131
		if item.dir then
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   132
			filename = join_path(storage_path, item.dir, item.filename);
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   133
		end
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   134
		if item.time < expiry then
2695
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   135
			local deleted, whynot = os.remove(filename);
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   136
			if not deleted then
2695
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   137
				module:log("warn", "Could not delete expired upload %s: %s", filename, whynot or "delete failed");
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   138
			end
2736
b1c5b0c369c2 mod_http_upload: Remove directory when deleting a file (fixes #950)
Kim Alvefur <zash@zash.se>
parents: 2735
diff changeset
   139
			os.remove(filename:match("^(.*)[/\\]"));
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   140
			return false;
2695
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   141
		elseif item.time < upload_window and not lfs.attributes(filename) then
2692
ef80c9d0ebff mod_http_upload: Remove unused upload slots
Kim Alvefur <zash@zash.se>
parents: 2691
diff changeset
   142
			return false; -- File was not uploaded or has been deleted since
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   143
		end
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   144
		return true;
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   145
	end);
3663
bb8a6df5ecba mod_http_upload: Skip write if nothing expired when checking
Kim Alvefur <zash@zash.se>
parents: 3662
diff changeset
   146
	local after = #uploads;
bb8a6df5ecba mod_http_upload: Skip write if nothing expired when checking
Kim Alvefur <zash@zash.se>
parents: 3662
diff changeset
   147
	if before == after then return true end -- nothing changed, skip write
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   148
	return datamanager.list_store(username, host, module.name, uploads);
2681
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   149
end
6daaa1ad2559 mod_http_upload: Add option for expiry of files after a configurable time (closes #557)
Kim Alvefur <zash@zash.se>
parents: 2671
diff changeset
   150
2682
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   151
local function check_quota(username, host, does_it_fit)
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   152
	if not quota then return true; end
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   153
	local uploads, err = datamanager.list_load(username, host, module.name);
3592
85057c4e7b66 mod_http_upload: Consider quota reached if it can't be checked
Kim Alvefur <zash@zash.se>
parents: 3553
diff changeset
   154
	if err then
85057c4e7b66 mod_http_upload: Consider quota reached if it can't be checked
Kim Alvefur <zash@zash.se>
parents: 3553
diff changeset
   155
		return false;
85057c4e7b66 mod_http_upload: Consider quota reached if it can't be checked
Kim Alvefur <zash@zash.se>
parents: 3553
diff changeset
   156
	elseif not uploads then
3593
dec5683f91a2 mod_http_upload: Check attempted upload against quota even with no previous uploads
Kim Alvefur <zash@zash.se>
parents: 3592
diff changeset
   157
		if does_it_fit then
dec5683f91a2 mod_http_upload: Check attempted upload against quota even with no previous uploads
Kim Alvefur <zash@zash.se>
parents: 3592
diff changeset
   158
			return does_it_fit < quota;
dec5683f91a2 mod_http_upload: Check attempted upload against quota even with no previous uploads
Kim Alvefur <zash@zash.se>
parents: 3592
diff changeset
   159
		end
3592
85057c4e7b66 mod_http_upload: Consider quota reached if it can't be checked
Kim Alvefur <zash@zash.se>
parents: 3553
diff changeset
   160
		return true;
85057c4e7b66 mod_http_upload: Consider quota reached if it can't be checked
Kim Alvefur <zash@zash.se>
parents: 3553
diff changeset
   161
	end
2682
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   162
	local sum = does_it_fit or 0;
2691
5f0b755b42a3 Backed out changeset e491a15d7621 (closes #888)
Kim Alvefur <zash@zash.se>
parents: 2688
diff changeset
   163
	for _, item in ipairs(uploads) do
2682
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   164
		sum = sum + item.size;
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   165
	end
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   166
	return sum < quota;
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   167
end
2dec7cad9218 mod_http_upload: Implement quota support (closes #823)
Kim Alvefur <zash@zash.se>
parents: 2681
diff changeset
   168
3370
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   169
local measure_slot = function () end
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   170
if module.measure then
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   171
	-- COMPAT 0.9
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   172
	-- module:measure was added in 0.10
3373
fca95f1b8870 mod_http_upload: Fix order of arguments to :measure
Kim Alvefur <zash@zash.se>
parents: 3370
diff changeset
   173
	measure_slot = module:measure("slot", "sizes");
3370
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   174
end
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   175
2735
d48faff92490 mod_http_upload: Remove MIME type restrictions and checking (fixes #958)
Kim Alvefur <zash@zash.se>
parents: 2696
diff changeset
   176
local function handle_request(origin, stanza, xmlns, filename, filesize)
2693
0fc706855af9 mod_http_upload: Keep user- and hostname in locals
Kim Alvefur <zash@zash.se>
parents: 2692
diff changeset
   177
	local username, host = origin.username, origin.host;
4447
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
   178
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
   179
	local user_bare = jid.bare(stanza.attr.from);
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
   180
	local user_host = jid.host(user_bare);
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
   181
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
   182
	-- local clients or whitelisted jids/hosts only
0a56dc6c61af mod_http_upload: Add access config option
Nicolas Cedilnik <nicoco@nicoco.fr>
parents: 4080
diff changeset
   183
	if not (origin.type == "c2s" or access:contains(user_bare) or access:contains(user_host)) then
2211
c45ad4b7aaa3 mod_http_upload: Add additional debug logging
Kim Alvefur <zash@zash.se>
parents: 2197
diff changeset
   184
		module:log("debug", "Request for upload slot from a %s", origin.type);
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   185
		return nil, st.error_reply(stanza, "cancel", "not-authorized");
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   186
	end
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   187
	-- validate
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   188
	if not filename or filename:find("/") then
2211
c45ad4b7aaa3 mod_http_upload: Add additional debug logging
Kim Alvefur <zash@zash.se>
parents: 2197
diff changeset
   189
		module:log("debug", "Filename %q not allowed", filename or "");
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   190
		return nil, st.error_reply(stanza, "modify", "bad-request", "Invalid filename");
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   191
	end
2693
0fc706855af9 mod_http_upload: Keep user- and hostname in locals
Kim Alvefur <zash@zash.se>
parents: 2692
diff changeset
   192
	expire(username, host);
1855
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
   193
	if not filesize then
2211
c45ad4b7aaa3 mod_http_upload: Add additional debug logging
Kim Alvefur <zash@zash.se>
parents: 2197
diff changeset
   194
		module:log("debug", "Missing file size");
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   195
		return nil, st.error_reply(stanza, "modify", "bad-request", "Missing or invalid file size");
1855
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
   196
	elseif filesize > file_size_limit then
2212
e654d6e1fb50 mod_http_upload: Log if file size exceeds limit
Kim Alvefur <zash@zash.se>
parents: 2211
diff changeset
   197
		module:log("debug", "File too large (%d > %d)", filesize, file_size_limit);
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   198
		return nil, st.error_reply(stanza, "modify", "not-acceptable", "File too large")
2645
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   199
			:tag("file-too-large", {xmlns=xmlns})
3653
d252c8573f33 mod_http_upload: Also format max file size as integer in error (thanks lovetox)
Kim Alvefur <zash@zash.se>
parents: 3652
diff changeset
   200
				:tag("max-file-size"):text(("%d"):format(file_size_limit));
2693
0fc706855af9 mod_http_upload: Keep user- and hostname in locals
Kim Alvefur <zash@zash.se>
parents: 2692
diff changeset
   201
	elseif not check_quota(username, host, filesize) then
4614
342664061c9b mod_http_upload: Fix issuing slots to components or other non-c2s sessions
Kim Alvefur <zash@zash.se>
parents: 4447
diff changeset
   202
		module:log("debug", "Upload of %dB by %s would exceed quota", filesize, user_bare);
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   203
		return nil, st.error_reply(stanza, "wait", "resource-constraint", "Quota reached");
1855
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
   204
	end
2684
96bf67f1f960 mod_http_upload: Validate that file extension (used by mod_http_files) matches mime type given by client
Kim Alvefur <zash@zash.se>
parents: 2682
diff changeset
   205
2804
8d9aed6d1f87 mod_http_upload: Only try to create a randomly named directory once.
Kim Alvefur <zash@zash.se>
parents: 2771
diff changeset
   206
	local random_dir = uuid();
8d9aed6d1f87 mod_http_upload: Only try to create a randomly named directory once.
Kim Alvefur <zash@zash.se>
parents: 2771
diff changeset
   207
	local created, err = lfs.mkdir(join_path(storage_path, random_dir));
8d9aed6d1f87 mod_http_upload: Only try to create a randomly named directory once.
Kim Alvefur <zash@zash.se>
parents: 2771
diff changeset
   208
8d9aed6d1f87 mod_http_upload: Only try to create a randomly named directory once.
Kim Alvefur <zash@zash.se>
parents: 2771
diff changeset
   209
	if not created then
8d9aed6d1f87 mod_http_upload: Only try to create a randomly named directory once.
Kim Alvefur <zash@zash.se>
parents: 2771
diff changeset
   210
		module:log("error", "Could not create directory for slot: %s", err);
3180
d34f5d969940 mod_http_upload: use correct error condition
Jonas Wielicki <jonas@wielicki.name>
parents: 3015
diff changeset
   211
		return nil, st.error_reply(stanza, "wait", "internal-server-error");
2804
8d9aed6d1f87 mod_http_upload: Only try to create a randomly named directory once.
Kim Alvefur <zash@zash.se>
parents: 2771
diff changeset
   212
	end
2472
3bff2848af12 mod_http_upload: Create random directory name when assigning slot
Kim Alvefur <zash@zash.se>
parents: 2471
diff changeset
   213
2694
43ad92c5b91a mod_http_upload: Return an error if unable to store slot info
Kim Alvefur <zash@zash.se>
parents: 2693
diff changeset
   214
	local ok = datamanager.list_append(username, host, module.name, {
2695
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   215
		filename = filename, dir = random_dir, size = filesize, time = os.time() });
92ddfc548ce8 mod_http_upload: Store filename and directory separately
Kim Alvefur <zash@zash.se>
parents: 2694
diff changeset
   216
2694
43ad92c5b91a mod_http_upload: Return an error if unable to store slot info
Kim Alvefur <zash@zash.se>
parents: 2693
diff changeset
   217
	if not ok then
3180
d34f5d969940 mod_http_upload: use correct error condition
Jonas Wielicki <jonas@wielicki.name>
parents: 3015
diff changeset
   218
		return nil, st.error_reply(stanza, "wait", "internal-server-error");
2694
43ad92c5b91a mod_http_upload: Return an error if unable to store slot info
Kim Alvefur <zash@zash.se>
parents: 2693
diff changeset
   219
	end
43ad92c5b91a mod_http_upload: Return an error if unable to store slot info
Kim Alvefur <zash@zash.se>
parents: 2693
diff changeset
   220
2653
abea818eed7b mod_http_upload: Rename variable to avoid name clash
Kim Alvefur <zash@zash.se>
parents: 2652
diff changeset
   221
	local slot = random_dir.."/"..filename;
4614
342664061c9b mod_http_upload: Fix issuing slots to components or other non-c2s sessions
Kim Alvefur <zash@zash.se>
parents: 4447
diff changeset
   222
	pending_slots[slot] = user_bare;
2686
3fd50495c89d mod_http_upload: Clear unused slots after 15 minutes
Kim Alvefur <zash@zash.se>
parents: 2685
diff changeset
   223
3fd50495c89d mod_http_upload: Clear unused slots after 15 minutes
Kim Alvefur <zash@zash.se>
parents: 2685
diff changeset
   224
	module:add_timer(900, function()
3fd50495c89d mod_http_upload: Clear unused slots after 15 minutes
Kim Alvefur <zash@zash.se>
parents: 2685
diff changeset
   225
		pending_slots[slot] = nil;
3fd50495c89d mod_http_upload: Clear unused slots after 15 minutes
Kim Alvefur <zash@zash.se>
parents: 2685
diff changeset
   226
	end);
3fd50495c89d mod_http_upload: Clear unused slots after 15 minutes
Kim Alvefur <zash@zash.se>
parents: 2685
diff changeset
   227
3370
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   228
	measure_slot(filesize);
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   229
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   230
	origin.log("debug", "Given upload slot %q", slot);
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   231
4658
ea17cfcbffab mod_http_upload: Prevent the module from starting without TLS
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 4657
diff changeset
   232
	local base_url = module:http_url();
2290
0a3f526779a1 mod_http_upload: Construct the upload slot URL using the LuaSocket URL library (fixes #717)
Kim Alvefur <zash@zash.se>
parents: 2289
diff changeset
   233
	local slot_url = url.parse(base_url);
2292
827f01cbf6ba mod_http_upload: Handle case of non-existant path
Kim Alvefur <zash@zash.se>
parents: 2291
diff changeset
   234
	slot_url.path = url.parse_path(slot_url.path or "/");
2653
abea818eed7b mod_http_upload: Rename variable to avoid name clash
Kim Alvefur <zash@zash.se>
parents: 2652
diff changeset
   235
	t_insert(slot_url.path, random_dir);
2290
0a3f526779a1 mod_http_upload: Construct the upload slot URL using the LuaSocket URL library (fixes #717)
Kim Alvefur <zash@zash.se>
parents: 2289
diff changeset
   236
	t_insert(slot_url.path, filename);
0a3f526779a1 mod_http_upload: Construct the upload slot URL using the LuaSocket URL library (fixes #717)
Kim Alvefur <zash@zash.se>
parents: 2289
diff changeset
   237
	slot_url.path.is_directory = false;
0a3f526779a1 mod_http_upload: Construct the upload slot URL using the LuaSocket URL library (fixes #717)
Kim Alvefur <zash@zash.se>
parents: 2289
diff changeset
   238
	slot_url.path = url.build_path(slot_url.path);
0a3f526779a1 mod_http_upload: Construct the upload slot URL using the LuaSocket URL library (fixes #717)
Kim Alvefur <zash@zash.se>
parents: 2289
diff changeset
   239
	slot_url = url.build(slot_url);
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   240
	return slot_url;
2645
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   241
end
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   242
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   243
-- hooks
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   244
module:hook("iq/host/"..namespace..":request", function (event)
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   245
	local stanza, origin = event.stanza, event.origin;
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   246
	local request = stanza.tags[1];
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   247
	local filename = request.attr.filename;
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   248
	local filesize = tonumber(request.attr.size);
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   249
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   250
	local slot_url, err = handle_request(origin, stanza, namespace, filename, filesize);
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   251
	if not slot_url then
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   252
		origin.send(err);
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   253
		return true;
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   254
	end
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   255
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   256
	local reply = st.reply(stanza)
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   257
		:tag("slot", { xmlns = namespace })
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   258
			:tag("get", { url = slot_url }):up()
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   259
			:tag("put", { url = slot_url }):up()
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   260
		:up();
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   261
	origin.send(reply);
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   262
	return true;
2645
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   263
end);
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   264
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   265
module:hook("iq/host/"..legacy_namespace..":request", function (event)
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   266
	local stanza, origin = event.stanza, event.origin;
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   267
	local request = stanza.tags[1];
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   268
	local filename = request:get_child_text("filename");
2d83e6c8160b mod_http_upload: add support for XEP-0363 version 0.3
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2611
diff changeset
   269
	local filesize = tonumber(request:get_child_text("size"));
2771
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   270
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   271
	local slot_url, err = handle_request(origin, stanza, legacy_namespace, filename, filesize);
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   272
	if not slot_url then
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   273
		origin.send(err);
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   274
		return true;
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   275
	end
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   276
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   277
	local reply = st.reply(stanza)
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   278
		:tag("slot", { xmlns = legacy_namespace })
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   279
			:tag("get"):text(slot_url):up()
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   280
			:tag("put"):text(slot_url):up()
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   281
		:up();
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   282
	origin.send(reply);
e1edf643fbb1 mod_http_upload: Send a correct response on namespace :0.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 2742
diff changeset
   283
	return true;
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   284
end);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   285
3370
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   286
local measure_upload = function () end
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   287
if module.measure then
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   288
	-- COMPAT 0.9
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   289
	-- module:measure was added in 0.10
3373
fca95f1b8870 mod_http_upload: Fix order of arguments to :measure
Kim Alvefur <zash@zash.se>
parents: 3370
diff changeset
   290
	measure_upload = module:measure("upload", "sizes");
3370
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   291
end
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   292
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   293
-- http service
3382
aefd64629e29 mod_http_upload: Relocate function definition to avoid traceback
Matthew Wild <mwild1@gmail.com>
parents: 3381
diff changeset
   294
local function set_cross_domain_headers(response)
3450
a5a50cd34386 mod_http_upload: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 3384
diff changeset
   295
	local headers = response.headers;
a5a50cd34386 mod_http_upload: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 3384
diff changeset
   296
	headers.access_control_allow_methods = "GET, PUT, OPTIONS";
a5a50cd34386 mod_http_upload: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 3384
diff changeset
   297
	headers.access_control_allow_headers = "Content-Type";
a5a50cd34386 mod_http_upload: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 3384
diff changeset
   298
	headers.access_control_max_age = "7200";
a5a50cd34386 mod_http_upload: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 3384
diff changeset
   299
	headers.access_control_allow_origin = response.request.headers.origin or "*";
a5a50cd34386 mod_http_upload: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 3384
diff changeset
   300
	return response;
3382
aefd64629e29 mod_http_upload: Relocate function definition to avoid traceback
Matthew Wild <mwild1@gmail.com>
parents: 3381
diff changeset
   301
end
aefd64629e29 mod_http_upload: Relocate function definition to avoid traceback
Matthew Wild <mwild1@gmail.com>
parents: 3381
diff changeset
   302
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   303
local function upload_data(event, path)
3381
683365d370d8 mod_http_upload: Also add CORS headers in response to PUT
Matthew Wild <mwild1@gmail.com>
parents: 3380
diff changeset
   304
	set_cross_domain_headers(event.response);
683365d370d8 mod_http_upload: Also add CORS headers in response to PUT
Matthew Wild <mwild1@gmail.com>
parents: 3380
diff changeset
   305
2471
290fef768a81 mod_http_upload: Forget upload slot under some error conditions
Kim Alvefur <zash@zash.se>
parents: 2449
diff changeset
   306
	local uploader = pending_slots[path];
290fef768a81 mod_http_upload: Forget upload slot under some error conditions
Kim Alvefur <zash@zash.se>
parents: 2449
diff changeset
   307
	if not uploader then
2195
e47046abf568 mod_http_upload: Add more logging
Kim Alvefur <zash@zash.se>
parents: 2070
diff changeset
   308
		module:log("warn", "Attempt to upload to unknown slot %q", path);
2197
40824a38d505 mod_http_upload: Return nil if no upload slot is found (should prevent conflicts between multiple instances on the same path)
Kim Alvefur <zash@zash.se>
parents: 2196
diff changeset
   309
		return; -- 404
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   310
	end
2653
abea818eed7b mod_http_upload: Rename variable to avoid name clash
Kim Alvefur <zash@zash.se>
parents: 2652
diff changeset
   311
	local random_dir, filename = path:match("^([^/]+)/([^/]+)$");
abea818eed7b mod_http_upload: Rename variable to avoid name clash
Kim Alvefur <zash@zash.se>
parents: 2652
diff changeset
   312
	if not random_dir then
2211
c45ad4b7aaa3 mod_http_upload: Add additional debug logging
Kim Alvefur <zash@zash.se>
parents: 2197
diff changeset
   313
		module:log("warn", "Invalid file path %q", path);
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   314
		return 400;
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   315
	end
1855
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
   316
	if #event.request.body > file_size_limit then
2196
bb8f7785aed7 mod_http_upload: Demote some errors to warnings
Kim Alvefur <zash@zash.se>
parents: 2195
diff changeset
   317
		module:log("warn", "Uploaded file too large %d bytes", #event.request.body);
1855
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
   318
		return 400;
03c5639882a7 mod_http_upload: Add support for a file size limit
Kim Alvefur <zash@zash.se>
parents: 1854
diff changeset
   319
	end
2471
290fef768a81 mod_http_upload: Forget upload slot under some error conditions
Kim Alvefur <zash@zash.se>
parents: 2449
diff changeset
   320
	pending_slots[path] = nil;
2653
abea818eed7b mod_http_upload: Rename variable to avoid name clash
Kim Alvefur <zash@zash.se>
parents: 2652
diff changeset
   321
	local full_filename = join_path(storage_path, random_dir, filename);
2473
43f7637f0143 mod_http_upload: Make sure that target file does not exist prior to upload
Kim Alvefur <zash@zash.se>
parents: 2472
diff changeset
   322
	if lfs.attributes(full_filename) then
43f7637f0143 mod_http_upload: Make sure that target file does not exist prior to upload
Kim Alvefur <zash@zash.se>
parents: 2472
diff changeset
   323
		module:log("warn", "File %s exists already, not replacing it", full_filename);
43f7637f0143 mod_http_upload: Make sure that target file does not exist prior to upload
Kim Alvefur <zash@zash.se>
parents: 2472
diff changeset
   324
		return 409;
43f7637f0143 mod_http_upload: Make sure that target file does not exist prior to upload
Kim Alvefur <zash@zash.se>
parents: 2472
diff changeset
   325
	end
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   326
	local fh, ferr = io.open(full_filename, "w");
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   327
	if not fh then
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   328
		module:log("error", "Could not open file %s for upload: %s", full_filename, ferr);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   329
		return 500;
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   330
	end
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   331
	local ok, err = fh:write(event.request.body);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   332
	if not ok then
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   333
		module:log("error", "Could not write to file %s for upload: %s", full_filename, err);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   334
		os.remove(full_filename);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   335
		return 500;
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   336
	end
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   337
	ok, err = fh:close();
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   338
	if not ok then
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   339
		module:log("error", "Could not write to file %s for upload: %s", full_filename, err);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   340
		os.remove(full_filename);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   341
		return 500;
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   342
	end
3370
6d1c5ecf72c1 mod_http_upload: Report statistics on upload sizes (0.10+)
Kim Alvefur <zash@zash.se>
parents: 3345
diff changeset
   343
	measure_upload(#event.request.body);
2653
abea818eed7b mod_http_upload: Rename variable to avoid name clash
Kim Alvefur <zash@zash.se>
parents: 2652
diff changeset
   344
	module:log("info", "File uploaded by %s to slot %s", uploader, random_dir);
2611
a7ef9b765891 mod_http_upload: Return 201 on successful PUT (as per XEP-0363 and RFC 2616) (Thanks Flow)
Matthew Wild <mwild1@gmail.com>
parents: 2493
diff changeset
   345
	return 201;
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   346
end
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   347
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   348
-- FIXME Duplicated from net.http.server
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   349
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   350
local codes = require "net.http.codes";
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   351
local headerfix = setmetatable({}, {
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   352
	__index = function(t, k)
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   353
		local v = "\r\n"..k:gsub("_", "-"):gsub("%f[%w].", s_upper)..": ";
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   354
		t[k] = v;
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   355
		return v;
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   356
	end
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   357
});
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   358
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   359
local function send_response_sans_body(response, body)
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   360
	if response.finished then return; end
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   361
	response.finished = true;
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   362
	response.conn._http_open_response = nil;
2069
624e3fed6f92 mod_http_upload: Trim trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 2057
diff changeset
   363
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   364
	local status_line = "HTTP/"..response.request.httpversion.." "..(response.status or codes[response.status_code]);
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   365
	local headers = response.headers;
2742
46b29a377bdf mod_http_upload: Handle HEAD requests in 0.10 when reading body from a file handle
Kim Alvefur <zash@zash.se>
parents: 2736
diff changeset
   366
	if type(body) == "string" then
46b29a377bdf mod_http_upload: Handle HEAD requests in 0.10 when reading body from a file handle
Kim Alvefur <zash@zash.se>
parents: 2736
diff changeset
   367
		headers.content_length = #body;
46b29a377bdf mod_http_upload: Handle HEAD requests in 0.10 when reading body from a file handle
Kim Alvefur <zash@zash.se>
parents: 2736
diff changeset
   368
	elseif io.type(body) == "file" then
46b29a377bdf mod_http_upload: Handle HEAD requests in 0.10 when reading body from a file handle
Kim Alvefur <zash@zash.se>
parents: 2736
diff changeset
   369
		headers.content_length = body:seek("end");
46b29a377bdf mod_http_upload: Handle HEAD requests in 0.10 when reading body from a file handle
Kim Alvefur <zash@zash.se>
parents: 2736
diff changeset
   370
		body:close();
46b29a377bdf mod_http_upload: Handle HEAD requests in 0.10 when reading body from a file handle
Kim Alvefur <zash@zash.se>
parents: 2736
diff changeset
   371
	end
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   372
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   373
	local output = { status_line };
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   374
	for k,v in pairs(headers) do
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   375
		t_insert(output, headerfix[k]..v);
1909
43fac0c2c772 mod_http_upload: Fix HEAD requests
Kim Alvefur <zash@zash.se>
parents: 1878
diff changeset
   376
	end
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   377
	t_insert(output, "\r\n\r\n");
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   378
	-- Here we *don't* add the body to the output
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   379
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   380
	response.conn:write(t_concat(output));
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   381
	if response.on_destroy then
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   382
		response:on_destroy();
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   383
		response.on_destroy = nil;
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   384
	end
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   385
	if response.persistent then
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   386
		response:finish_cb();
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   387
	else
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   388
		response.conn:close();
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   389
	end
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   390
end
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   391
3629
a578b4977bb0 mod_http_upload: Duplicate mime types handling from mod_http_files (fixes #1374)
Kim Alvefur <zash@zash.se>
parents: 3594
diff changeset
   392
local serve_uploaded_files = http_files.serve({ path = storage_path, mime_map = mime_map });
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   393
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   394
local function serve_head(event, path)
3380
972832108c78 mod_http_upload: Add CORS headers for web clients (untested)
Matthew Wild <mwild1@gmail.com>
parents: 3373
diff changeset
   395
	set_cross_domain_headers(event.response);
1916
24c22cbb86e4 mod_http_upload: Duplicate code from net.http.server in order send proper HEAD responses
Kim Alvefur <zash@zash.se>
parents: 1910
diff changeset
   396
	event.response.send = send_response_sans_body;
2742
46b29a377bdf mod_http_upload: Handle HEAD requests in 0.10 when reading body from a file handle
Kim Alvefur <zash@zash.se>
parents: 2736
diff changeset
   397
	event.response.send_file = send_response_sans_body;
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   398
	return serve_uploaded_files(event, path);
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   399
end
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   400
3717
53fc4b612fb2 mod_http_upload: Skip custom HEAD handling on recent Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3665
diff changeset
   401
if httpserver.send_head_response then
53fc4b612fb2 mod_http_upload: Skip custom HEAD handling on recent Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3665
diff changeset
   402
	-- Prosody will take care of HEAD requests since hg:3f4c25425589
53fc4b612fb2 mod_http_upload: Skip custom HEAD handling on recent Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3665
diff changeset
   403
	serve_head = nil
53fc4b612fb2 mod_http_upload: Skip custom HEAD handling on recent Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3665
diff changeset
   404
end
53fc4b612fb2 mod_http_upload: Skip custom HEAD handling on recent Prosody trunk
Kim Alvefur <zash@zash.se>
parents: 3665
diff changeset
   405
1946
ff95d983940c mod_http_upload: Say Hello to anyone opening the "bare" HTTP URL (helpful to show that module is loaded correctly)
Kim Alvefur <zash@zash.se>
parents: 1918
diff changeset
   406
local function serve_hello(event)
ff95d983940c mod_http_upload: Say Hello to anyone opening the "bare" HTTP URL (helpful to show that module is loaded correctly)
Kim Alvefur <zash@zash.se>
parents: 1918
diff changeset
   407
	event.response.headers.content_type = "text/html;charset=utf-8"
2951
faec53f4b31e mod_http_upload: Include the current VirtualHost name in greeting to help with debugging
Kim Alvefur <zash@zash.se>
parents: 2804
diff changeset
   408
	return "<!DOCTYPE html>\n<h1>Hello from mod_"..module.name.." on "..module.host.."!</h1>\n";
1946
ff95d983940c mod_http_upload: Say Hello to anyone opening the "bare" HTTP URL (helpful to show that module is loaded correctly)
Kim Alvefur <zash@zash.se>
parents: 1918
diff changeset
   409
end
ff95d983940c mod_http_upload: Say Hello to anyone opening the "bare" HTTP URL (helpful to show that module is loaded correctly)
Kim Alvefur <zash@zash.se>
parents: 1918
diff changeset
   410
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   411
module:provides("http", {
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   412
	route = {
1946
ff95d983940c mod_http_upload: Say Hello to anyone opening the "bare" HTTP URL (helpful to show that module is loaded correctly)
Kim Alvefur <zash@zash.se>
parents: 1918
diff changeset
   413
		["GET"] = serve_hello;
ff95d983940c mod_http_upload: Say Hello to anyone opening the "bare" HTTP URL (helpful to show that module is loaded correctly)
Kim Alvefur <zash@zash.se>
parents: 1918
diff changeset
   414
		["GET /"] = serve_hello;
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   415
		["GET /*"] = serve_uploaded_files;
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   416
		["HEAD /*"] = serve_head;
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   417
		["PUT /*"] = upload_data;
3380
972832108c78 mod_http_upload: Add CORS headers for web clients (untested)
Matthew Wild <mwild1@gmail.com>
parents: 3373
diff changeset
   418
972832108c78 mod_http_upload: Add CORS headers for web clients (untested)
Matthew Wild <mwild1@gmail.com>
parents: 3373
diff changeset
   419
		["OPTIONS /*"] = function (event)
3383
f1c1f6bc4892 mod_http_upload: Remove extra check for Origin HTTP header
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3382
diff changeset
   420
			set_cross_domain_headers(event.response);
3380
972832108c78 mod_http_upload: Add CORS headers for web clients (untested)
Matthew Wild <mwild1@gmail.com>
parents: 3373
diff changeset
   421
			return "";
972832108c78 mod_http_upload: Add CORS headers for web clients (untested)
Matthew Wild <mwild1@gmail.com>
parents: 3373
diff changeset
   422
		end;
1776
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   423
	};
45f7e3c2557f mod_http_upload: Implementation of Conversations HTTP upload file transfer mode
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   424
});
1853
5244c9b0b297 mod_http_upload: Log a message with the upload URL and storage path for easy discovery
Kim Alvefur <zash@zash.se>
parents: 1852
diff changeset
   425
3662
02a1615d0392 mod_http_upload: Add hint about checking that the base URL is reachable
Kim Alvefur <zash@zash.se>
parents: 3661
diff changeset
   426
module:log("info", "URL: <%s> - Ensure this can be reached by users", module:http_url());
02a1615d0392 mod_http_upload: Add hint about checking that the base URL is reachable
Kim Alvefur <zash@zash.se>
parents: 3661
diff changeset
   427
module:log("info", "Storage path: '%s'", storage_path);
3015
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   428
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   429
function module.command(args)
3345
1e1dbd7e5b6c mod_http_upload: Use legacy datamanager directly (makes it work)
Kim Alvefur <zash@zash.se>
parents: 3344
diff changeset
   430
	datamanager = require "core.storagemanager".olddm;
3343
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   431
	-- luacheck: ignore 421/user
3966
190e74e097ee mod_http_upload: Show help message if not at least one host/user is given
Kim Alvefur <zash@zash.se>
parents: 3965
diff changeset
   432
	if args[1] == "expire" and args[2] then
3015
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   433
		local split = require "util.jid".prepped_split;
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   434
		for i = 2, #args do
3343
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   435
			local user, host = split(args[i]);
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   436
			if user then
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   437
				assert(expire(user, host));
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   438
			else
3344
6081cbfd1220 mod_http_upload: Abort and throw error in case of failure to iterate over users
Kim Alvefur <zash@zash.se>
parents: 3343
diff changeset
   439
				for user in assert(datamanager.users(host, module.name, "list")) do
3343
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   440
					expire(user, host);
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   441
				end
babb584e24a2 mod_http_upload: Run expiry for all users if command run with a hostname
Kim Alvefur <zash@zash.se>
parents: 3180
diff changeset
   442
			end
3015
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   443
		end
3965
6fd9c9708422 mod_http_upload: Add some kind of help message to prosodyctl command
Kim Alvefur <zash@zash.se>
parents: 3717
diff changeset
   444
	else
6fd9c9708422 mod_http_upload: Add some kind of help message to prosodyctl command
Kim Alvefur <zash@zash.se>
parents: 3717
diff changeset
   445
		print("prosodyctl mod_http_upload expire [host or user@host]+")
6fd9c9708422 mod_http_upload: Add some kind of help message to prosodyctl command
Kim Alvefur <zash@zash.se>
parents: 3717
diff changeset
   446
		print("\tProcess upload expiry for the given list of hosts and/or users");
6fd9c9708422 mod_http_upload: Add some kind of help message to prosodyctl command
Kim Alvefur <zash@zash.se>
parents: 3717
diff changeset
   447
		return 1;
3015
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   448
	end
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   449
end
995836ee4f26 mod_http_upload: Add an experimental prosodyctl command for expiring uploads
Kim Alvefur <zash@zash.se>
parents: 2951
diff changeset
   450