From 83ab43ca8ff3d3e93042f76b91194f2ec3c6e36f Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Wed, 28 Nov 2018 20:36:53 +0100
Subject: util.format: Tweak how nil values are handled

Because [<nil>] seems exsessive
---
 util/format.lua | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

(limited to 'util')

diff --git a/util/format.lua b/util/format.lua
index c5e513fa..16c57bc6 100644
--- a/util/format.lua
+++ b/util/format.lua
@@ -28,13 +28,12 @@ local function format(formatstring, ...)
 		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
+			if arg == nil then
+				args[i] = "nil";
+				spec = "<%s>";
+			elseif 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);
-- 
cgit v1.2.3


From 755f1d8050c373af7abf578ac30067f1d141c93f Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sat, 8 Dec 2018 16:35:39 +0100
Subject: util.format: Use pack from util.table

---
 util/format.lua | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'util')

diff --git a/util/format.lua b/util/format.lua
index 16c57bc6..6c46384a 100644
--- a/util/format.lua
+++ b/util/format.lua
@@ -3,12 +3,13 @@
 --
 
 local tostring = tostring;
-local select = select;
 local unpack = table.unpack or unpack; -- luacheck: ignore 113/unpack
+local pack = require "util.table".pack; -- TODO table.pack in 5.2+
 local type = type;
 
 local function format(formatstring, ...)
-	local args, args_length = { ... }, select('#', ...);
+	local args = pack(...);
+	local args_length = args.n;
 
 	-- format specifier spec:
 	-- 1. Start: '%%'
-- 
cgit v1.2.3


From 08cb0002476600be61921a3a2a15bc9626e052e5 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sat, 8 Dec 2018 16:36:05 +0100
Subject: util.iterators: Use pack from table.pack

---
 util/iterators.lua | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'util')

diff --git a/util/iterators.lua b/util/iterators.lua
index 302cca36..c03c2fd6 100644
--- a/util/iterators.lua
+++ b/util/iterators.lua
@@ -11,9 +11,9 @@
 local it = {};
 
 local t_insert = table.insert;
-local select, next = select, next;
-local unpack = table.unpack or unpack; --luacheck: ignore 113 143
-local pack = table.pack or function (...) return { n = select("#", ...), ... }; end -- luacheck: ignore 143
+local next = next;
+local unpack = table.unpack or unpack; --luacheck: ignore 113
+local pack = table.pack or require "util.table".pack;
 local type = type;
 local table, setmetatable = table, setmetatable;
 
-- 
cgit v1.2.3


From a8b096516b2ef1791bc348e18baa7e7f5399de8f Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sat, 8 Dec 2018 17:10:51 +0100
Subject: lint: Remove use of the 143 error code

Does not appear to be invoked by anything
---
 util/import.lua        | 2 +-
 util/multitable.lua    | 2 +-
 util/serialization.lua | 1 -
 3 files changed, 2 insertions(+), 3 deletions(-)

(limited to 'util')

diff --git a/util/import.lua b/util/import.lua
index 8ecfe43c..1007bc0a 100644
--- a/util/import.lua
+++ b/util/import.lua
@@ -8,7 +8,7 @@
 
 
 
-local unpack = table.unpack or unpack; --luacheck: ignore 113 143
+local unpack = table.unpack or unpack; --luacheck: ignore 113
 local t_insert = table.insert;
 function _G.import(module, ...)
 	local m = package.loaded[module] or require(module);
diff --git a/util/multitable.lua b/util/multitable.lua
index 8d32ed8a..4f2cd972 100644
--- a/util/multitable.lua
+++ b/util/multitable.lua
@@ -9,7 +9,7 @@
 local select = select;
 local t_insert = table.insert;
 local pairs, next, type = pairs, next, type;
-local unpack = table.unpack or unpack; --luacheck: ignore 113 143
+local unpack = table.unpack or unpack; --luacheck: ignore 113
 
 local _ENV = nil;
 -- luacheck: std none
diff --git a/util/serialization.lua b/util/serialization.lua
index dd6a2a2b..7ae77a3a 100644
--- a/util/serialization.lua
+++ b/util/serialization.lua
@@ -20,7 +20,6 @@ local pcall = pcall;
 local envload = require"util.envload".envload;
 
 local pos_inf, neg_inf = math.huge, -math.huge;
--- luacheck: ignore 143/math
 local m_type = math.type or function (n)
 	return n % 1 == 0 and n <= 9007199254740992 and n >= -9007199254740992 and "integer" or "float";
 end;
-- 
cgit v1.2.3


From c0b8a6ef63746675fbe1441bceed47f6fb2bee88 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Fri, 12 Oct 2018 01:29:34 +0200
Subject: util.format: Serialize values for the %q format

Improves eg debug logs
---
 util/format.lua | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

(limited to 'util')

diff --git a/util/format.lua b/util/format.lua
index 6c46384a..c31f599f 100644
--- a/util/format.lua
+++ b/util/format.lua
@@ -6,6 +6,7 @@ local tostring = tostring;
 local unpack = table.unpack or unpack; -- luacheck: ignore 113/unpack
 local pack = require "util.table".pack; -- TODO table.pack in 5.2+
 local type = type;
+local dump = require "util.serialization".new("debug");
 
 local function format(formatstring, ...)
 	local args = pack(...);
@@ -34,7 +35,10 @@ local function format(formatstring, ...)
 			if arg == nil then
 				args[i] = "nil";
 				spec = "<%s>";
-			elseif option == "q" or option == "s" then -- arg should be string
+			elseif option == "q" then
+				args[i] = dump(arg);
+				spec = "%s";
+			elseif option == "s" then
 				args[i] = tostring(arg);
 			elseif type(arg) ~= "number" then -- arg isn't number as expected?
 				args[i] = tostring(arg);
-- 
cgit v1.2.3


From b250ff0d70b614a5ee0025fc68f175428bfca4b5 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Fri, 28 Dec 2018 20:49:01 +0100
Subject: util.stanza: Require a type attribute for iq stanzas

---
 util/stanza.lua | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

(limited to 'util')

diff --git a/util/stanza.lua b/util/stanza.lua
index a90d56b3..e9847ca6 100644
--- a/util/stanza.lua
+++ b/util/stanza.lua
@@ -423,9 +423,15 @@ local function message(attr, body)
 	end
 end
 local function iq(attr)
-	if not (attr and attr.id) then
+	if not attr then
+		error("iq stanzas require id and type attributes");
+	end
+	if not attr.id then
 		error("iq stanzas require an id attribute");
 	end
+	if not attr.type then
+		error("iq stanzas require a type attribute");
+	end
 	return new_stanza("iq", attr);
 end
 
-- 
cgit v1.2.3


From 93c5ebb743337c82103ea94166065106a9f5b641 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sun, 30 Dec 2018 03:24:54 +0100
Subject: util.promise: Remove references to callbacks after settling promise

This is to help the garbage collector.
---
 util/promise.lua | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'util')

diff --git a/util/promise.lua b/util/promise.lua
index 07c9c4dc..0b182b54 100644
--- a/util/promise.lua
+++ b/util/promise.lua
@@ -49,6 +49,9 @@ local function promise_settle(promise, new_state, new_next, cbs, value)
 	for _, cb in ipairs(cbs) do
 		cb(value);
 	end
+	-- No need to keep references to callbacks
+	promise._pending_on_fulfilled = nil;
+	promise._pending_on_rejected = nil;
 	return true;
 end
 
-- 
cgit v1.2.3


From 38462e35420ca9e93af018210be940353b32d508 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sun, 30 Dec 2018 12:55:58 +0000
Subject: util.error: Add new util library for structured errors

---
 util/error.lua | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 util/error.lua

(limited to 'util')

diff --git a/util/error.lua b/util/error.lua
new file mode 100644
index 00000000..ed61793f
--- /dev/null
+++ b/util/error.lua
@@ -0,0 +1,40 @@
+local error_mt = { __name = "error" };
+
+function error_mt:__tostring()
+	return ("error<%s:%s:%s>"):format(self.type, self.condition, self.text);
+end
+
+local function is_err(e)
+	return getmetatable(e) == error_mt;
+end
+
+local function new(e, context, registry)
+	local template = (registry and registry[e]) or e or {};
+	return setmetatable({
+		type = template.type or "cancel";
+		condition = template.condition or "undefined-condition";
+		text = template.text;
+
+		context = context or template.context or { _error_id = e };
+	}, error_mt);
+end
+
+local function coerce(ok, err, ...)
+	if ok or is_err(err) then
+		return ok, err, ...;
+	end
+
+	local new_err = setmetatable({
+		native = err;
+
+		type = "cancel";
+		condition = "undefined-condition";
+	}, error_mt);
+	return ok, new_err, ...;
+end
+
+return {
+	new = new;
+	coerce = coerce;
+	is_err = is_err;
+}
-- 
cgit v1.2.3


From ac2d2297b62ba2973c49d7d5bee3927cef64ea97 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sun, 30 Dec 2018 20:30:59 +0100
Subject: util.error: Add a function for creating an error object from an error
 stanza

---
 util/error.lua | 12 ++++++++++++
 1 file changed, 12 insertions(+)

(limited to 'util')

diff --git a/util/error.lua b/util/error.lua
index ed61793f..344dd274 100644
--- a/util/error.lua
+++ b/util/error.lua
@@ -33,8 +33,20 @@ local function coerce(ok, err, ...)
 	return ok, new_err, ...;
 end
 
+local function from_stanza(stanza, context)
+	local error_type, condition, text = stanza:get_error();
+	return setmetatable({
+		type = error_type or "cancel";
+		condition = condition or "undefined-condition";
+		text = text;
+
+		context = context or { stanza = stanza };
+	}, error_mt);
+end
+
 return {
 	new = new;
 	coerce = coerce;
 	is_err = is_err;
+	from_stanza = from_stanza;
 }
-- 
cgit v1.2.3


From 60213520c2a27bf0472a0ef5a2cf16640134a1a8 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sun, 6 Jan 2019 10:39:33 +0100
Subject: util.http: Pre-generate urlencoding mappings (optimization)

Function calls are more expensive than table lookups
---
 util/http.lua | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

(limited to 'util')

diff --git a/util/http.lua b/util/http.lua
index cfb89193..1730d4d4 100644
--- a/util/http.lua
+++ b/util/http.lua
@@ -6,24 +6,25 @@
 --
 
 local format, char = string.format, string.char;
-local pairs, ipairs, tonumber = pairs, ipairs, tonumber;
+local pairs, ipairs = pairs, ipairs;
 local t_insert, t_concat = table.insert, table.concat;
 
+local url_codes = {};
+for i = 0, 255 do
+	local c = char(i);
+	local u = format("%%%02x", i);
+	url_codes[c] = u;
+	url_codes[u] = c;
+end
 local function urlencode(s)
-	return s and (s:gsub("[^a-zA-Z0-9.~_-]", function (c) return format("%%%02x", c:byte()); end));
+	return s and (s:gsub("[^a-zA-Z0-9.~_-]", url_codes));
 end
 local function urldecode(s)
-	return s and (s:gsub("%%(%x%x)", function (c) return char(tonumber(c,16)); end));
+	return s and (s:gsub("%%%x%x", url_codes));
 end
 
 local function _formencodepart(s)
-	return s and (s:gsub("%W", function (c)
-		if c ~= " " then
-			return format("%%%02x", c:byte());
-		else
-			return "+";
-		end
-	end));
+	return s and (urlencode(s):gsub("%%20", "+"));
 end
 
 local function formencode(form)
-- 
cgit v1.2.3


From 1a3edc0ab921f131c7304e92d7402ef88ff465ef Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Thu, 10 Jan 2019 14:57:26 +0100
Subject: util.prosodyctl: Allow passing path to Lua runtime to the start()
 function

By default the shebang is used. Being able to override it is useful in
cases where the shebang does not match the configured runtime.
---
 util/prosodyctl.lua | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'util')

diff --git a/util/prosodyctl.lua b/util/prosodyctl.lua
index 5f0c4d12..9b627bde 100644
--- a/util/prosodyctl.lua
+++ b/util/prosodyctl.lua
@@ -229,7 +229,8 @@ local function isrunning()
 	return true, signal.kill(pid, 0) == 0;
 end
 
-local function start(source_dir)
+local function start(source_dir, lua)
+	lua = lua and lua .. " " or "";
 	local ok, ret = isrunning();
 	if not ok then
 		return ok, ret;
@@ -238,9 +239,9 @@ local function start(source_dir)
 		return false, "already-running";
 	end
 	if not source_dir then
-		os.execute("./prosody");
+		os.execute(lua .. "./prosody");
 	else
-		os.execute(source_dir.."/../../bin/prosody");
+		os.execute(lua .. source_dir.."/../../bin/prosody");
 	end
 	return true;
 end
-- 
cgit v1.2.3


From 7ae9fe492d2e616d94b77c280a2f5e0f2c744075 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Wed, 16 Jan 2019 13:53:04 +0100
Subject: util.http: Fix decoding of uppercase URL encoded chars

Broken in 1af5106a2c34
---
 util/http.lua | 1 +
 1 file changed, 1 insertion(+)

(limited to 'util')

diff --git a/util/http.lua b/util/http.lua
index 1730d4d4..3852f91c 100644
--- a/util/http.lua
+++ b/util/http.lua
@@ -15,6 +15,7 @@ for i = 0, 255 do
 	local u = format("%%%02x", i);
 	url_codes[c] = u;
 	url_codes[u] = c;
+	url_codes[u:upper()] = c;
 end
 local function urlencode(s)
 	return s and (s:gsub("[^a-zA-Z0-9.~_-]", url_codes));
-- 
cgit v1.2.3


From 8dbde146973dbdf875e1a5fc5a455218426f454c Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sun, 17 Mar 2019 20:40:01 +0100
Subject: util.serialization: Optimize handling of last table separator

Fewer next() calls and a step towards allowing use of a different iterator.
---
 util/serialization.lua | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

(limited to 'util')

diff --git a/util/serialization.lua b/util/serialization.lua
index 7ae77a3a..c64bfec1 100644
--- a/util/serialization.lua
+++ b/util/serialization.lua
@@ -163,7 +163,9 @@ local function new(opt)
 		local indent = s_rep(indentwith, d);
 		local numkey = 1;
 		local ktyp, vtyp;
+		local had_items = false;
 		for k,v in next,t do
+			had_items = true;
 			o[l], l = itemstart, l + 1;
 			o[l], l = indent, l + 1;
 			ktyp, vtyp = type(k), type(v);
@@ -194,14 +196,10 @@ local function new(opt)
 			else
 				o[l], l = ser(v), l + 1;
 			end
-			-- last item?
-			if next(t, k) ~= nil then
-				o[l], l = itemsep, l + 1;
-			else
-				o[l], l = itemlast, l + 1;
-			end
+			o[l], l = itemsep, l + 1;
 		end
-		if next(t) ~= nil then
+		if had_items then
+			o[l - 1] = itemlast;
 			o[l], l = s_rep(indentwith, d-1), l + 1;
 		end
 		o[l], l = tend, l +1;
-- 
cgit v1.2.3


From a335b6de27f7da7df46ec7a4091b6d1ea8ba2fba Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sun, 17 Mar 2019 21:16:27 +0100
Subject: util.serialization: Allow overriding table iterator

Could be useful to eg swap it out with sorted_pairs to get a stable
serialization.

Default to next() wrapper to avoid metatable tricks from pairs().
---
 util/serialization.lua | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'util')

diff --git a/util/serialization.lua b/util/serialization.lua
index c64bfec1..2ead8c12 100644
--- a/util/serialization.lua
+++ b/util/serialization.lua
@@ -33,6 +33,10 @@ local function to_hex(s)
 	return (s_gsub(s, ".", char_to_hex));
 end
 
+local function rawpairs(t)
+	return next, t, nil;
+end
+
 local function fatal_error(obj, why)
 	error("Can't serialize "..type(obj) .. (why and ": ".. why or ""));
 end
@@ -122,6 +126,7 @@ local function new(opt)
 	local freeze = opt.freeze;
 	local maxdepth = opt.maxdepth or 127;
 	local multirefs = opt.multiref;
+	local table_pairs = opt.table_iterator or rawpairs;
 
 	-- serialize one table, recursively
 	-- t - table being serialized
@@ -164,7 +169,7 @@ local function new(opt)
 		local numkey = 1;
 		local ktyp, vtyp;
 		local had_items = false;
-		for k,v in next,t do
+		for k,v in table_pairs(t) do
 			had_items = true;
 			o[l], l = itemstart, l + 1;
 			o[l], l = indent, l + 1;
-- 
cgit v1.2.3


From 8999b2a97c8d5e0d9dcf10d7692f928287d6bc5e Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sun, 17 Mar 2019 21:25:33 +0100
Subject: util.serialization: Use util.hex

---
 util/serialization.lua | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

(limited to 'util')

diff --git a/util/serialization.lua b/util/serialization.lua
index 2ead8c12..60e341cf 100644
--- a/util/serialization.lua
+++ b/util/serialization.lua
@@ -16,6 +16,8 @@ local s_char = string.char;
 local s_match = string.match;
 local t_concat = table.concat;
 
+local to_hex = require "util.hex".to;
+
 local pcall = pcall;
 local envload = require"util.envload".envload;
 
@@ -24,15 +26,6 @@ local m_type = math.type or function (n)
 	return n % 1 == 0 and n <= 9007199254740992 and n >= -9007199254740992 and "integer" or "float";
 end;
 
-local char_to_hex = {};
-for i = 0,255 do
-	char_to_hex[s_char(i)] = s_format("%02x", i);
-end
-
-local function to_hex(s)
-	return (s_gsub(s, ".", char_to_hex));
-end
-
 local function rawpairs(t)
 	return next, t, nil;
 end
-- 
cgit v1.2.3


From 67b08fccf7d370c1df426890057d2775edd49797 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Wed, 20 Mar 2019 12:18:34 +0000
Subject: util.startup: Give function a more generic name so it can apply to
 all warnings

---
 util/startup.lua | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'util')

diff --git a/util/startup.lua b/util/startup.lua
index c101c290..4d3c6e4e 100644
--- a/util/startup.lua
+++ b/util/startup.lua
@@ -96,7 +96,7 @@ function startup.init_logging()
 	end);
 end
 
-function startup.log_dependency_warnings()
+function startup.log_startup_warnings()
 	dependencies.log_warnings();
 end
 
@@ -518,7 +518,7 @@ function startup.prosodyctl()
 	startup.read_version();
 	startup.switch_user();
 	startup.check_dependencies();
-	startup.log_dependency_warnings();
+	startup.log_startup_warnings();
 	startup.check_unwriteable();
 	startup.load_libraries();
 	startup.init_http_client();
@@ -543,7 +543,7 @@ function startup.prosody()
 	startup.add_global_prosody_functions();
 	startup.read_version();
 	startup.log_greeting();
-	startup.log_dependency_warnings();
+	startup.log_startup_warnings();
 	startup.load_secondary_libraries();
 	startup.init_http_client();
 	startup.init_data_store();
-- 
cgit v1.2.3


From 798be44f563b8764dad50e893f4b25268b42e5a8 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Wed, 20 Mar 2019 12:45:58 +0000
Subject: util.startup: Log configuration warnings at startup

---
 util/startup.lua | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'util')

diff --git a/util/startup.lua b/util/startup.lua
index 4d3c6e4e..966f2934 100644
--- a/util/startup.lua
+++ b/util/startup.lua
@@ -7,6 +7,7 @@ local logger = require "util.logger";
 local log = logger.init("startup");
 
 local config = require "core.configmanager";
+local config_warnings;
 
 local dependencies = require "util.dependencies";
 
@@ -64,6 +65,8 @@ function startup.read_config()
 		print("**************************");
 		print("");
 		os.exit(1);
+	elseif err and #err > 0 then
+		config_warnings = err;
 	end
 	prosody.config_loaded = true;
 end
@@ -98,6 +101,9 @@ end
 
 function startup.log_startup_warnings()
 	dependencies.log_warnings();
+	for _, warning in ipairs(config_warnings) do
+		log("warn", "Configuration warning: %s", warning);
+	end
 end
 
 function startup.sanity_check()
-- 
cgit v1.2.3


From c77d416cfffd6604cc4d9a633f9f7941f6fd5f10 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Wed, 20 Mar 2019 13:44:29 +0000
Subject: util.startup: Don't die if there are no config warnings to log
 (thanks buildbot)

---
 util/startup.lua | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

(limited to 'util')

diff --git a/util/startup.lua b/util/startup.lua
index 966f2934..7a1a95aa 100644
--- a/util/startup.lua
+++ b/util/startup.lua
@@ -101,8 +101,10 @@ end
 
 function startup.log_startup_warnings()
 	dependencies.log_warnings();
-	for _, warning in ipairs(config_warnings) do
-		log("warn", "Configuration warning: %s", warning);
+	if config_warnings then
+		for _, warning in ipairs(config_warnings) do
+			log("warn", "Configuration warning: %s", warning);
+		end
 	end
 end
 
-- 
cgit v1.2.3


From 2080433daf5a956d0456c6ce24ce1ef9183a023e Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sat, 23 Mar 2019 08:47:55 +0000
Subject: util.queue: Add 'consume()' convenience iterator

---
 util/queue.lua | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'util')

diff --git a/util/queue.lua b/util/queue.lua
index 728e905f..e63b3f1c 100644
--- a/util/queue.lua
+++ b/util/queue.lua
@@ -64,6 +64,9 @@ local function new(size, allow_wrapping)
 				return pos+1, t._items[read_pos];
 			end, self, 0;
 		end;
+		consume = function (self)
+			return self.pop, self;
+		end;
 	};
 end
 
-- 
cgit v1.2.3


From bd52e2269b0fff09fc8aea6c6807a9f08727bb31 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sat, 23 Mar 2019 08:52:57 +0000
Subject: util.queue: Update :items() to consistently use private data directly

It will perform better this way, and we were accessing private variables
already within the iterator.
---
 util/queue.lua | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

(limited to 'util')

diff --git a/util/queue.lua b/util/queue.lua
index e63b3f1c..66ed098b 100644
--- a/util/queue.lua
+++ b/util/queue.lua
@@ -52,16 +52,15 @@ local function new(size, allow_wrapping)
 			return t[tail];
 		end;
 		items = function (self)
-			--luacheck: ignore 431/t
-			return function (t, pos)
-				if pos >= t:count() then
+			return function (_, pos)
+				if pos >= items then
 					return nil;
 				end
 				local read_pos = tail + pos;
-				if read_pos > t.size then
+				if read_pos > self.size then
 					read_pos = (read_pos%size);
 				end
-				return pos+1, t._items[read_pos];
+				return pos+1, t[read_pos];
 			end, self, 0;
 		end;
 		consume = function (self)
-- 
cgit v1.2.3


From ff3904d881514abc83443b02e10cd621873bed64 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Fri, 4 Jan 2019 10:20:51 +0100
Subject: util.x509: Add function that extracts usable names from a certificate

---
 util/x509.lua | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

(limited to 'util')

diff --git a/util/x509.lua b/util/x509.lua
index 15cc4d3c..1cdf07dc 100644
--- a/util/x509.lua
+++ b/util/x509.lua
@@ -20,6 +20,7 @@
 
 local nameprep = require "util.encodings".stringprep.nameprep;
 local idna_to_ascii = require "util.encodings".idna.to_ascii;
+local idna_to_unicode = require "util.encodings".idna.to_unicode;
 local base64 = require "util.encodings".base64;
 local log = require "util.logger".init("x509");
 local s_format = string.format;
@@ -216,6 +217,32 @@ local function verify_identity(host, service, cert)
 	return false
 end
 
+-- TODO Support other SANs
+local function get_identities(cert) --> set of names
+	if cert.setencode then
+		cert:setencode("utf8");
+	end
+
+	local names = {};
+
+	local ext = cert:extensions();
+	local sans = ext[oid_subjectaltname];
+	if sans and sans["dNSName"] then
+		for i = 1, #sans["dNSName"] do
+			names[ idna_to_unicode(sans["dNSName"][i]) ] = true;
+		end
+	end
+
+	local subject = cert:subject();
+	for i = 1, #subject do
+		local dn = subject[i];
+		if dn.oid == oid_commonname and nameprep(dn.value) then
+			names[dn.value] = true;
+		end
+	end
+	return names;
+end
+
 local pat = "%-%-%-%-%-BEGIN ([A-Z ]+)%-%-%-%-%-\r?\n"..
 "([0-9A-Za-z+/=\r\n]*)\r?\n%-%-%-%-%-END %1%-%-%-%-%-";
 
@@ -237,6 +264,7 @@ end
 
 return {
 	verify_identity = verify_identity;
+	get_identities = get_identities;
 	pem2der = pem2der;
 	der2pem = der2pem;
 };
-- 
cgit v1.2.3


From e9eca8cd5521f2bfc8f9285b606eb84de5a467e4 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Mon, 25 Mar 2019 14:37:43 +0000
Subject: util.stanza: Fix :top_tag() handling of namespaced attributes

---
 util/stanza.lua | 62 ++++++++++++++++++++++++++++-----------------------------
 1 file changed, 30 insertions(+), 32 deletions(-)

(limited to 'util')

diff --git a/util/stanza.lua b/util/stanza.lua
index e9847ca6..7fe5c7ae 100644
--- a/util/stanza.lua
+++ b/util/stanza.lua
@@ -270,6 +270,34 @@ function stanza_mt:find(path)
 	until not self
 end
 
+local function _clone(stanza, only_top)
+	local attr, tags = {}, {};
+	for k,v in pairs(stanza.attr) do attr[k] = v; end
+	local old_namespaces, namespaces = stanza.namespaces;
+	if old_namespaces then
+		namespaces = {};
+		for k,v in pairs(old_namespaces) do namespaces[k] = v; end
+	end
+	local new = { name = stanza.name, attr = attr, namespaces = namespaces, tags = tags };
+	if not only_top then
+		for i=1,#stanza do
+			local child = stanza[i];
+			if child.name then
+				child = _clone(child);
+				t_insert(tags, child);
+			end
+			t_insert(new, child);
+		end
+	end
+	return setmetatable(new, stanza_mt);
+end
+
+local function clone(stanza, only_top)
+	if not is_stanza(stanza) then
+		error("bad argument to clone: expected stanza, got "..type(stanza));
+	end
+	return _clone(stanza, only_top);
+end
 
 local escape_table = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end
@@ -310,11 +338,8 @@ function stanza_mt.__tostring(t)
 end
 
 function stanza_mt.top_tag(t)
-	local attr_string = "";
-	if t.attr then
-		for k, v in pairs(t.attr) do if type(k) == "string" then attr_string = attr_string .. s_format(" %s='%s'", k, xml_escape(tostring(v))); end end
-	end
-	return s_format("<%s%s>", t.name, attr_string);
+	local top_tag_clone = clone(t, true);
+	return tostring(top_tag_clone):sub(1,-3)..">";
 end
 
 function stanza_mt.get_text(t)
@@ -388,33 +413,6 @@ local function deserialize(serialized)
 	end
 end
 
-local function _clone(stanza)
-	local attr, tags = {}, {};
-	for k,v in pairs(stanza.attr) do attr[k] = v; end
-	local old_namespaces, namespaces = stanza.namespaces;
-	if old_namespaces then
-		namespaces = {};
-		for k,v in pairs(old_namespaces) do namespaces[k] = v; end
-	end
-	local new = { name = stanza.name, attr = attr, namespaces = namespaces, tags = tags };
-	for i=1,#stanza do
-		local child = stanza[i];
-		if child.name then
-			child = _clone(child);
-			t_insert(tags, child);
-		end
-		t_insert(new, child);
-	end
-	return setmetatable(new, stanza_mt);
-end
-
-local function clone(stanza)
-	if not is_stanza(stanza) then
-		error("bad argument to clone: expected stanza, got "..type(stanza));
-	end
-	return _clone(stanza);
-end
-
 local function message(attr, body)
 	if not body then
 		return new_stanza("message", attr);
-- 
cgit v1.2.3


From 08ec4600470e32bbc4bb0afdfce9012f6a8cb5e9 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 26 Mar 2019 13:51:06 +0000
Subject: Backed out changeset 3eea63a68e0f

Commit included intended changes to loggingmanager
---
 util/queue.lua | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

(limited to 'util')

diff --git a/util/queue.lua b/util/queue.lua
index 66ed098b..e63b3f1c 100644
--- a/util/queue.lua
+++ b/util/queue.lua
@@ -52,15 +52,16 @@ local function new(size, allow_wrapping)
 			return t[tail];
 		end;
 		items = function (self)
-			return function (_, pos)
-				if pos >= items then
+			--luacheck: ignore 431/t
+			return function (t, pos)
+				if pos >= t:count() then
 					return nil;
 				end
 				local read_pos = tail + pos;
-				if read_pos > self.size then
+				if read_pos > t.size then
 					read_pos = (read_pos%size);
 				end
-				return pos+1, t[read_pos];
+				return pos+1, t._items[read_pos];
 			end, self, 0;
 		end;
 		consume = function (self)
-- 
cgit v1.2.3


From 8e20f176e04a261129c9d49705b72f9460999145 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 26 Mar 2019 13:54:14 +0000
Subject: util.queue: Update :items() to consistently use private data directly

It will perform better this way, and we were accessing private variables already within the iterator.

Replaces 3eea63a68e0f
---
 util/queue.lua | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

(limited to 'util')

diff --git a/util/queue.lua b/util/queue.lua
index e63b3f1c..66ed098b 100644
--- a/util/queue.lua
+++ b/util/queue.lua
@@ -52,16 +52,15 @@ local function new(size, allow_wrapping)
 			return t[tail];
 		end;
 		items = function (self)
-			--luacheck: ignore 431/t
-			return function (t, pos)
-				if pos >= t:count() then
+			return function (_, pos)
+				if pos >= items then
 					return nil;
 				end
 				local read_pos = tail + pos;
-				if read_pos > t.size then
+				if read_pos > self.size then
 					read_pos = (read_pos%size);
 				end
-				return pos+1, t._items[read_pos];
+				return pos+1, t[read_pos];
 			end, self, 0;
 		end;
 		consume = function (self)
-- 
cgit v1.2.3


From c0e30a99fc9b49847577598541328ebe1d7eaaba Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Wed, 3 Apr 2019 17:20:57 +0200
Subject: util.session: Fix session id not include unauthed forever

---
 util/session.lua | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'util')

diff --git a/util/session.lua b/util/session.lua
index b2a726ce..b9c6bec7 100644
--- a/util/session.lua
+++ b/util/session.lua
@@ -4,12 +4,13 @@ local logger = require "util.logger";
 local function new_session(typ)
 	local session = {
 		type = typ .. "_unauthed";
+		base_type = typ;
 	};
 	return session;
 end
 
 local function set_id(session)
-	local id = session.type .. tostring(session):match("%x+$"):lower();
+	local id = session.base_type .. tostring(session):match("%x+$"):lower();
 	session.id = id;
 	return session;
 end
-- 
cgit v1.2.3


From 8e2e187ff819b98ebae24f2a5ebd9994a2d41c2f Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Fri, 19 Apr 2019 12:46:24 +0200
Subject: util.hmac: Reflow code

---
 util/hmac.lua | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

(limited to 'util')

diff --git a/util/hmac.lua b/util/hmac.lua
index 2c4cc6ef..f3caae33 100644
--- a/util/hmac.lua
+++ b/util/hmac.lua
@@ -10,6 +10,8 @@
 
 local hashes = require "util.hashes"
 
-return { md5 = hashes.hmac_md5,
-	 sha1 = hashes.hmac_sha1,
-	 sha256 = hashes.hmac_sha256 };
+return {
+	md5 = hashes.hmac_md5,
+	sha1 = hashes.hmac_sha1,
+	sha256 = hashes.hmac_sha256,
+};
-- 
cgit v1.2.3


From 1d11df9a67d5f650d1ff4404ba7d6668df99875e Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Fri, 19 Apr 2019 12:47:49 +0200
Subject: util.hmac: Expose hmac-sha-512 too

All these are provided by util.hashes so why not?
---
 util/hmac.lua | 1 +
 1 file changed, 1 insertion(+)

(limited to 'util')

diff --git a/util/hmac.lua b/util/hmac.lua
index f3caae33..4cad17cc 100644
--- a/util/hmac.lua
+++ b/util/hmac.lua
@@ -14,4 +14,5 @@ return {
 	md5 = hashes.hmac_md5,
 	sha1 = hashes.hmac_sha1,
 	sha256 = hashes.hmac_sha256,
+	sha512 = hashes.hmac_sha512,
 };
-- 
cgit v1.2.3


From 690c6a4eb240ede63cf7a31007c25df29fa123f2 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Fri, 3 May 2019 20:54:24 +0200
Subject: Fix various spelling mistakes [codespell]

---
 util/datamanager.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'util')

diff --git a/util/datamanager.lua b/util/datamanager.lua
index cf96887b..b52c77fa 100644
--- a/util/datamanager.lua
+++ b/util/datamanager.lua
@@ -24,7 +24,7 @@ local t_concat = table.concat;
 local envloadfile = require"util.envload".envloadfile;
 local serialize = require "util.serialization".serialize;
 local lfs = require "lfs";
--- Extract directory seperator from package.config (an undocumented string that comes with lua)
+-- Extract directory separator from package.config (an undocumented string that comes with lua)
 local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.config not in standard form" )
 
 local prosody = prosody;
-- 
cgit v1.2.3


From b61b308c569dda7ca5e214466503e9cc7ea4a7e7 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Mon, 13 May 2019 10:03:46 +0100
Subject: util.hashring: Implementation of hashring data structure

---
 util/hashring.lua | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 util/hashring.lua

(limited to 'util')

diff --git a/util/hashring.lua b/util/hashring.lua
new file mode 100644
index 00000000..322bc005
--- /dev/null
+++ b/util/hashring.lua
@@ -0,0 +1,88 @@
+local function generate_ring(nodes, num_replicas, hash)
+	local new_ring = {};
+        for _, node_name in ipairs(nodes) do
+                for replica = 1, num_replicas do
+                        local replica_hash = hash(node_name..":"..replica);
+                        new_ring[replica_hash] = node_name;
+                        table.insert(new_ring, replica_hash);
+                end
+        end
+        table.sort(new_ring);
+	return new_ring;
+end
+
+local hashring_methods = {};
+local hashring_mt = {
+	__index = function (self, k)
+		-- Automatically build self.ring if it's missing
+		if k == "ring" then
+			local ring = generate_ring(self.nodes, self.num_replicas, self.hash);
+			rawset(self, "ring", ring);
+			return ring;
+		end
+		return rawget(hashring_methods, k);
+	end
+};
+
+local function new(num_replicas, hash_function)
+	return setmetatable({ nodes = {}, num_replicas = num_replicas, hash = hash_function }, hashring_mt);
+end;
+
+function hashring_methods:add_node(name)
+	self.ring = nil;
+	self.nodes[name] = true;
+	table.insert(self.nodes, name);
+	return true;
+end
+
+function hashring_methods:add_nodes(nodes)
+	self.ring = nil;
+	for _, node_name in ipairs(nodes) do
+		if not self.nodes[node_name] then
+			self.nodes[node_name] = true;
+			table.insert(self.nodes, node_name);
+		end
+	end
+	return true;
+end
+
+function hashring_methods:remove_node(node_name)
+	self.ring = nil;
+	if self.nodes[node_name] then
+		for i, stored_node_name in ipairs(self.nodes) do
+			if node_name == stored_node_name then
+				self.nodes[node_name] = nil;
+				table.remove(self.nodes, i);
+				return true;
+			end
+		end
+	end
+	return false;
+end
+
+function hashring_methods:remove_nodes(nodes)
+	self.ring = nil;
+	for _, node_name in ipairs(nodes) do
+		self:remove_node(node_name);
+	end
+end
+
+function hashring_methods:clone()
+	local clone_hashring = new(self.num_replicas, self.hash);
+	clone_hashring:add_nodes(self.nodes);
+	return clone_hashring;
+end
+
+function hashring_methods:get_node(key)
+	local key_hash = self.hash(key);
+	for _, replica_hash in ipairs(self.ring) do
+		if key_hash < replica_hash then
+			return self.ring[replica_hash];
+		end
+	end
+	return self.ring[self.ring[1]];
+end
+
+return {
+	new = new;
+}
-- 
cgit v1.2.3


From be249b1a12e22c3276598555bedf7beb8386f550 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Thu, 30 May 2019 13:41:05 +0200
Subject: util.format: Handle formats expecting an integer in Lua 5.3+ (fixes
 #1371)

---
 util/format.lua | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'util')

diff --git a/util/format.lua b/util/format.lua
index c31f599f..857bb694 100644
--- a/util/format.lua
+++ b/util/format.lua
@@ -7,6 +7,9 @@ local unpack = table.unpack or unpack; -- luacheck: ignore 113/unpack
 local pack = require "util.table".pack; -- TODO table.pack in 5.2+
 local type = type;
 local dump = require "util.serialization".new("debug");
+local num_type = math.type;
+
+local expects_integer = num_type and { c = true, d = true, i = true, o = true, u = true, X = true, x = true, } or {};
 
 local function format(formatstring, ...)
 	local args = pack(...);
@@ -43,6 +46,9 @@ local function format(formatstring, ...)
 			elseif type(arg) ~= "number" then -- arg isn't number as expected?
 				args[i] = tostring(arg);
 				spec = "[%s]";
+			elseif expects_integer[option] and num_type(arg) ~= "integer" then
+				args[i] = tostring(arg);
+				spec = "[%s]";
 			end
 		end
 		return spec;
-- 
cgit v1.2.3


From 9991f8892518b2d48cf27b3667a2fe33d25dcd67 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Thu, 30 May 2019 13:54:11 +0200
Subject: util.format: Handle integer formats the same way on Lua versions
 without integer support

---
 util/format.lua | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'util')

diff --git a/util/format.lua b/util/format.lua
index 857bb694..1ce670f3 100644
--- a/util/format.lua
+++ b/util/format.lua
@@ -7,9 +7,12 @@ local unpack = table.unpack or unpack; -- luacheck: ignore 113/unpack
 local pack = require "util.table".pack; -- TODO table.pack in 5.2+
 local type = type;
 local dump = require "util.serialization".new("debug");
-local num_type = math.type;
+local num_type = math.type or function (n)
+	return n % 1 == 0 and n <= 9007199254740992 and n >= -9007199254740992 and "integer" or "float";
+end
 
-local expects_integer = num_type and { c = true, d = true, i = true, o = true, u = true, X = true, x = true, } or {};
+-- In Lua 5.3+ these formats throw an error if given a float
+local expects_integer = { c = true, d = true, i = true, o = true, u = true, X = true, x = true, };
 
 local function format(formatstring, ...)
 	local args = pack(...);
-- 
cgit v1.2.3


From 4e7d17bfff9ff33d5c0b58cae1941aac45090b70 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Wed, 19 Jun 2019 19:16:09 +0200
Subject: util.dependencies: Increase Lua version to warn about to 5.4

No significant problems have been encountered with Lua 5.3 itself, so
apart from some odd problems in LuaExpat it seems about time to declare
it ready.
---
 util/dependencies.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'util')

diff --git a/util/dependencies.lua b/util/dependencies.lua
index 7c7b938e..84e2dd5c 100644
--- a/util/dependencies.lua
+++ b/util/dependencies.lua
@@ -140,7 +140,7 @@ local function check_dependencies()
 end
 
 local function log_warnings()
-	if _VERSION > "Lua 5.2" then
+	if _VERSION > "Lua 5.3" then
 		prosody.log("warn", "Support for %s is experimental, please report any issues", _VERSION);
 	end
 	local ssl = softreq"ssl";
-- 
cgit v1.2.3