Merge 0.10->trunk
authorKim Alvefur <zash@zash.se>
Thu, 14 Sep 2017 02:48:34 +0200
changeset 8238 7d9a2c200736
parent 8224 4989a625419a (current diff)
parent 8237 97b3ca502547 (diff)
child 8239 4878e4159e12
Merge 0.10->trunk
plugins/mod_c2s.lua
plugins/mod_component.lua
plugins/mod_posix.lua
plugins/mod_s2s/mod_s2s.lua
util/dependencies.lua
--- a/core/loggingmanager.lua	Wed Sep 13 18:46:39 2017 +0200
+++ b/core/loggingmanager.lua	Thu Sep 14 02:48:34 2017 +0200
@@ -7,7 +7,7 @@
 --
 -- luacheck: globals log prosody.log
 
-local format = string.format;
+local format = require "util.format".format;
 local setmetatable, rawset, pairs, ipairs, type =
 	setmetatable, rawset, pairs, ipairs, type;
 local stdout = io.stdout;
@@ -15,9 +15,6 @@
 local math_max, rep = math.max, string.rep;
 local os_date = os.date;
 local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
-local tostring = tostring;
-local select = select;
-local unpack = table.unpack or unpack; --luacheck: ignore 113
 
 local config = require "core.configmanager";
 local logger = require "util.logger";
@@ -194,23 +191,15 @@
 	-- Column width for "source" (used by stdout and console)
 	local sourcewidth = sink_config.source_width;
 
-	return function (name, level, message, ...)
-		local n = select('#', ...);
-		if n ~= 0 then
-			local arg = { ... };
-			for i = 1, n do
-				arg[i] = tostring(arg[i]);
-			end
-			message = format(message, unpack(arg, 1, n));
+	if sourcewidth then
+		return function (name, level, message, ...)
+			sourcewidth = math_max(#name+2, sourcewidth);
+			write(logfile, timestamps and os_date(timestamps) or "", name, rep(" ", sourcewidth-#name), level, "\t", format(message, ...), "\n");
 		end
-
-		if sourcewidth then
-			sourcewidth = math_max(#name+2, sourcewidth);
-			name = name ..  rep(" ", sourcewidth-#name);
-		else
-			name = name .. "\t";
+	else
+		return function (name, level, message, ...)
+			write(logfile, timestamps and os_date(timestamps) or "", name, "\t", level, "\t", format(message, ...), "\n");
 		end
-		write(logfile, timestamps and os_date(timestamps) or "", name, level, "\t", message, "\n");
 	end
 end
 log_sink_types.file = log_to_file;
--- a/plugins/mod_c2s.lua	Wed Sep 13 18:46:39 2017 +0200
+++ b/plugins/mod_c2s.lua	Thu Sep 14 02:48:34 2017 +0200
@@ -112,16 +112,14 @@
 		session:close("not-well-formed");
 	elseif error == "stream-error" then
 		local condition, text = "undefined-condition";
-		for child in data:children() do
-			if child.attr.xmlns == xmlns_xmpp_streams then
-				if child.name ~= "text" then
-					condition = child.name;
-				else
-					text = child:get_text();
-				end
-				if condition ~= "undefined-condition" and text then
-					break;
-				end
+		for child in data:childtags(nil, xmlns_xmpp_streams) do
+			if child.name ~= "text" then
+				condition = child.name;
+			else
+				text = child:get_text();
+			end
+			if condition ~= "undefined-condition" and text then
+				break;
 			end
 		end
 		text = condition .. (text and (" ("..text..")") or "");
--- a/plugins/mod_component.lua	Wed Sep 13 18:46:39 2017 +0200
+++ b/plugins/mod_component.lua	Thu Sep 14 02:48:34 2017 +0200
@@ -170,16 +170,14 @@
 		session:close("not-well-formed");
 	elseif error == "stream-error" then
 		local condition, text = "undefined-condition";
-		for child in data:children() do
-			if child.attr.xmlns == xmlns_xmpp_streams then
-				if child.name ~= "text" then
-					condition = child.name;
-				else
-					text = child:get_text();
-				end
-				if condition ~= "undefined-condition" and text then
-					break;
-				end
+		for child in data:childtags(nil, xmlns_xmpp_streams) do
+			if child.name ~= "text" then
+				condition = child.name;
+			else
+				text = child:get_text();
+			end
+			if condition ~= "undefined-condition" and text then
+				break;
 			end
 		end
 		text = condition .. (text and (" ("..text..")") or "");
--- a/plugins/mod_mam/mod_mam.lua	Wed Sep 13 18:46:39 2017 +0200
+++ b/plugins/mod_mam/mod_mam.lua	Thu Sep 14 02:48:34 2017 +0200
@@ -56,6 +56,13 @@
 
 local cleanup;
 
+local function schedule_cleanup(username)
+	if cleanup and not cleanup[username] then
+		table.insert(cleanup, username);
+		cleanup[username] = true;
+	end
+end
+
 -- Handle prefs.
 module:hook("iq/self/"..xmlns_mam..":prefs", function(event)
 	local origin, stanza = event.origin, event.stanza;
@@ -97,7 +104,7 @@
 	local query = stanza.tags[1];
 	local qid = query.attr.queryid;
 
-	if cleanup then cleanup[origin.username] = true; end
+	schedule_cleanup(origin.username);
 
 	-- Search query parameters
 	local qwith, qstart, qend;
@@ -304,7 +311,7 @@
 			local id = ok;
 			clone_for_other_handlers:tag("stanza-id", { xmlns = xmlns_st_id, by = store_user.."@"..host, id = id }):up();
 			event.stanza = clone_for_other_handlers;
-			if cleanup then cleanup[store_user] = true; end
+			schedule_cleanup(store_user);
 			module:fire_event("archive-message-added", { origin = origin, stanza = clone_for_storage, for_user = store_user, id = id });
 		end
 	else
@@ -326,7 +333,9 @@
 
 local cleanup_after = module:get_option_string("archive_expires_after", "1w");
 local cleanup_interval = module:get_option_number("archive_cleanup_interval", 4 * 60 * 60);
-if cleanup_after ~= "never" then
+if not archive.delete then
+	module:log("debug", "Selected storage driver does not support deletion, archives will not expire");
+elseif cleanup_after ~= "never" then
 	local day = 86400;
 	local multipliers = { d = day, w = day * 7, m = 31 * day, y = 365.2425 * day };
 	local n, m = cleanup_after:lower():match("(%d+)%s*([dwmy]?)");
@@ -353,13 +362,13 @@
 	pcall(function ()
 		-- If this works, then we schedule cleanup for all known users on startup
 		for user in um.users(module.host) do
-			cleanup[user] = true;
+			schedule_cleanup(user);
 		end
 	end);
 
 	-- At odd intervals, delete old messages for one user
 	module:add_timer(math.random(10, 60), function()
-		local user = next(cleanup);
+		local user = table.remove(cleanup, 1);
 		if user then
 			module:log("debug", "Removing old messages for user %q", user);
 			local ok, err = archive:delete(user, { ["end"] = os.time() - cleanup_after; })
--- a/plugins/mod_posix.lua	Wed Sep 13 18:46:39 2017 +0200
+++ b/plugins/mod_posix.lua	Thu Sep 14 02:48:34 2017 +0200
@@ -20,6 +20,7 @@
 	module:log("warn", "Couldn't load signal library, won't respond to SIGTERM");
 end
 
+local format = require "util.format".format;
 local lfs = require "lfs";
 local stat = lfs.attributes;
 
@@ -118,13 +119,9 @@
 		pposix.syslog_open("prosody", module:get_option_string("syslog_facility"));
 		syslog_opened = true;
 	end
-	local syslog, format = pposix.syslog_log, string.format;
+	local syslog = pposix.syslog_log;
 	return function (name, level, message, ...)
-		if ... then
-			syslog(level, name, format(message, ...));
-		else
-			syslog(level, name, message);
-		end
+		syslog(level, name, format(message, ...));
 	end;
 end
 require "core.loggingmanager".register_sink_type("syslog", syslog_sink_maker);
--- a/plugins/mod_s2s/mod_s2s.lua	Wed Sep 13 18:46:39 2017 +0200
+++ b/plugins/mod_s2s/mod_s2s.lua	Thu Sep 14 02:48:34 2017 +0200
@@ -438,16 +438,14 @@
 		session:close("not-well-formed");
 	elseif error == "stream-error" then
 		local condition, text = "undefined-condition";
-		for child in data:children() do
-			if child.attr.xmlns == xmlns_xmpp_streams then
-				if child.name ~= "text" then
-					condition = child.name;
-				else
-					text = child:get_text();
-				end
-				if condition ~= "undefined-condition" and text then
-					break;
-				end
+		for child in data:childtags(nil, xmlns_xmpp_streams) do
+			if child.name ~= "text" then
+				condition = child.name;
+			else
+				text = child:get_text();
+			end
+			if condition ~= "undefined-condition" and text then
+				break;
 			end
 		end
 		text = condition .. (text and (" ("..text..")") or "");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/format.lua	Thu Sep 14 02:48:34 2017 +0200
@@ -0,0 +1,74 @@
+--
+-- A string.format wrapper that gracefully handles invalid arguments
+--
+
+local tostring = tostring;
+local select = select;
+local assert = assert;
+local unpack = unpack;
+local type = type;
+
+local function format(format, ...)
+	local args, args_length = { ... }, select('#', ...);
+
+	-- format specifier spec:
+	-- 1. Start: '%%'
+	-- 2. Flags: '[%-%+ #0]'
+	-- 3. Width: '%d?%d?'
+	-- 4. Precision: '%.?%d?%d?'
+	-- 5. Option: '[cdiouxXaAeEfgGqs%%]'
+	--
+	-- The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, whereas q and s expect a string.
+	-- This function does not accept string values containing embedded zeros, except as arguments to the q option.
+	-- a and A are only in Lua 5.2+
+
+
+	-- process each format specifier
+	local i = 0;
+	format = format:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec)
+		if spec ~= "%%" then
+			i = i + 1;
+			local arg = args[i];
+			if arg == nil then -- special handling for nil
+				arg = "<nil>"
+				args[i] = "<nil>";
+			end
+
+			local option = spec:sub(-1);
+			if option == "q" or option == "s" then -- arg should be string
+				args[i] = tostring(arg);
+			elseif type(arg) ~= "number" then -- arg isn't number as expected?
+				args[i] = tostring(arg);
+				spec = "[%s]";
+			end
+		end
+		return spec;
+	end);
+
+	-- process extra args
+	while i < args_length do
+		i = i + 1;
+		local arg = args[i];
+		if arg == nil then
+			args[i] = "<nil>";
+		else
+			args[i] = tostring(arg);
+		end
+		format = format .. " [%s]"
+	end
+
+	return format:format(unpack(args));
+end
+
+local function test()
+	assert(format("%s", "hello") == "hello");
+	assert(format("%s") == "<nil>");
+	assert(format("%s", true) == "true");
+	assert(format("%d", true) == "[true]");
+	assert(format("%%", true) == "% [true]");
+end
+
+return {
+	format = format;
+	test = test;
+};