From bfc6ce85617ded179bc04ce2337eb583e58b4578 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 21 Dec 2010 14:44:13 +0000
Subject: util.xmppstream: Allow stream_ns = "" for parsing streams with no
 xmlns

---
 util/xmppstream.lua | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/util/xmppstream.lua b/util/xmppstream.lua
index 0a1bf7ac..cbdadd9b 100644
--- a/util/xmppstream.lua
+++ b/util/xmppstream.lua
@@ -45,7 +45,10 @@ function new_sax_handlers(session, stream_callbacks)
 	local cb_handlestanza = stream_callbacks.handlestanza;
 	
 	local stream_ns = stream_callbacks.stream_ns or xmlns_streams;
-	local stream_tag = stream_ns..ns_separator..(stream_callbacks.stream_tag or "stream");
+	local stream_tag = stream_callbacks.stream_tag or "stream";
+	if stream_ns ~= "" then
+		stream_tag = stream_ns..ns_separator..stream_tag;
+	end
 	local stream_error_tag = stream_ns..ns_separator..(stream_callbacks.error_tag or "error");
 	
 	local stream_default_ns = stream_callbacks.default_ns;
-- 
cgit v1.2.3


From 949fdfb956690ce0c4a2817a0f410db0bb751e88 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 21 Dec 2010 22:25:54 +0000
Subject: configmanager: Filenames without a path are also relative to the
 config file path, not the current working directory

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

diff --git a/core/configmanager.lua b/core/configmanager.lua
index 839927df..b703bb8c 100644
--- a/core/configmanager.lua
+++ b/core/configmanager.lua
@@ -221,10 +221,11 @@ do
 			if file:match("[*?]") then
 				local path_pos, glob = file:match("()([^"..path_sep.."]+)$");
 				local path = file:sub(1, math_max(path_pos-2,0));
+				local config_path = config_file:gsub("[^"..path_sep.."]+$", "");
 				if #path > 0 then
-					path = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), path);
+					path = resolve_relative_path(config_path, path);
 				else
-					path = ".";
+					path = config_path;
 				end
 				local patt = glob_to_pattern(glob);
 				for f in lfs.dir(path) do
-- 
cgit v1.2.3


From 18972368fe1a471b367b528058e399dfaf42e377 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 21 Dec 2010 22:26:22 +0000
Subject: prosody: Catch a recursive Include error and print a more friendly
 error

---
 prosody | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/prosody b/prosody
index d4bf7578..07ec2bdb 100755
--- a/prosody
+++ b/prosody
@@ -77,9 +77,15 @@ function read_config()
 		print("\n");
 		print("**************************");
 		if level == "parser" then
-			print("A problem occured while reading the config file "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua");
+			print("A problem occured while reading the config file "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"..":");
+			print("");
 			local err_line, err_message = tostring(err):match("%[string .-%]:(%d*): (.*)");
-			print("Error"..(err_line and (" on line "..err_line) or "")..": "..(err_message or tostring(err)));
+			if err:match("chunk has too many syntax levels$") then
+				print("An Include statement in a config file is including an already-included");
+				print("file and causing an infinite loop. An Include statement in a config file is...");
+			else
+				print("Error"..(err_line and (" on line "..err_line) or "")..": "..(err_message or tostring(err)));
+			end
 			print("");
 		elseif level == "file" then
 			print("Prosody was unable to find the configuration file.");
-- 
cgit v1.2.3


From f050d463d41893bc552756723a937c05ff5988ed Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Wed, 22 Dec 2010 16:46:19 +0000
Subject: util.filters: Add remove_filter_hook()

---
 util/filters.lua | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/util/filters.lua b/util/filters.lua
index f304e71a..d143666b 100644
--- a/util/filters.lua
+++ b/util/filters.lua
@@ -76,4 +76,12 @@ function add_filter_hook(callback)
 	t_insert(new_filter_hooks, callback);
 end
 
+function remove_filter_hook(callback)
+	for i=1,#new_filter_hooks do
+		if new_filter_hooks[i] == callback then
+			t_remove(new_filter_hooks, i);
+		end
+	end
+end
+
 return _M;
-- 
cgit v1.2.3


From abb088f7c4b9ab4371bc9eb22022a9e5a34e09cc Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Wed, 22 Dec 2010 20:38:40 +0000
Subject: s2smanager: send_to_host(): Return false on failure, and true
 otherwise

---
 core/s2smanager.lua | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index c6e6df8e..4e6dba5b 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -105,6 +105,7 @@ function send_to_host(from_host, to_host, data)
 			log("error", "Trying to send a stanza to ourselves??")
 			log("error", "Traceback: %s", get_traceback());
 			log("error", "Stanza: %s", tostring(data));
+			return false;
 		else
 			(host.log or log)("debug", "going to send stanza to "..to_host.." from "..from_host);
 			-- FIXME
@@ -125,8 +126,10 @@ function send_to_host(from_host, to_host, data)
 		if (not host_session.connecting) and (not host_session.conn) then
 			log("warn", "Connection to %s failed already, destroying session...", to_host);
 			destroy_session(host_session);
+			return false;
 		end
 	end
+	return true;
 end
 
 local open_sessions = 0;
-- 
cgit v1.2.3


From c63e6361ada543078637d762b8b643f051b6d745 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Wed, 22 Dec 2010 20:39:30 +0000
Subject: s2smanager: session.send(): Return the result of send_to_host() (and
 incidentally make this a tail call \o/)

---
 core/s2smanager.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index 4e6dba5b..b8163efa 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -518,7 +518,7 @@ function mark_connected(session)
 	session.log("info", session.direction.." s2s connection "..from.."->"..to.." complete");
 	
 	local send_to_host = send_to_host;
-	function session.send(data) send_to_host(to, from, data); end
+	function session.send(data) return send_to_host(to, from, data); end
 	
 	local event_data = { session = session };
 	if session.type == "s2sout" then
-- 
cgit v1.2.3


From 208c7ca51180cd51fef6b5862bc948c3a656cd30 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:47:18 +0000
Subject: s2smanager: retire_session(): Add a 'reason' parameter

---
 core/s2smanager.lua | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index b8163efa..212a2fe1 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -555,7 +555,7 @@ local resting_session = { -- Resting, not dead
 		filter = function (type, data) return data; end;
 	}; resting_session.__index = resting_session;
 
-function retire_session(session)
+function retire_session(session, reason)
 	local log = session.log or log;
 	for k in pairs(session) do
 		if k ~= "trace" and k ~= "log" and k ~= "id" then
@@ -563,6 +563,8 @@ function retire_session(session)
 		end
 	end
 
+	session.destruction_reason = reason;
+
 	function session.send(data) log("debug", "Discarding data sent to resting session: %s", tostring(data)); end
 	function session.data(data) log("debug", "Discarding data received from resting session: %s", tostring(data)); end
 	return setmetatable(session, resting_session);
-- 
cgit v1.2.3


From d47a1f622b276c68fd7bff32da24315d8788317c Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:48:18 +0000
Subject: s2smanager: destroy_session(): Pass reason to retire_session() and
 return true on successful destruction

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

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index 212a2fe1..dac95314 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -594,7 +594,8 @@ function destroy_session(session, reason)
 		end
 	end
 	
-	retire_session(session); -- Clean session until it is GC'd
+	retire_session(session, reason); -- Clean session until it is GC'd
+	return true;
 end
 
 return _M;
-- 
cgit v1.2.3


From 40fc886767dd4f4371d1400c9534c8979d5b50d1 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:48:38 +0000
Subject: s2smanager: Add a missing semi-colon

---
 core/s2smanager.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index dac95314..5dde476f 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -315,7 +315,7 @@ function make_connect(host_session, connect_host, connect_port)
 	
 	local from_host, to_host = host_session.from_host, host_session.to_host;
 	
-	local conn, handler = socket.tcp()
+	local conn, handler = socket.tcp();
 	
 	if not conn then
 		log("warn", "Failed to create outgoing connection, system error: %s", handler);
-- 
cgit v1.2.3


From 4d132026d0cc13c429139a06f8096752c899711b Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:49:30 +0000
Subject: s2smanager: Give all new outgoing s2s sessions a close method by
 default (destroy_session)

---
 core/s2smanager.lua | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index 5dde476f..c7b950e2 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -177,6 +177,8 @@ function new_outgoing(from_host, to_host, connect)
 		
 		hosts[from_host].s2sout[to_host] = host_session;
 		
+		host_session.close = destroy_session; -- This gets replaced by xmppserver_listener later
+		
 		local log;
 		do
 			local conn_name = "s2sout"..tostring(host_session):match("[a-f0-9]*$");
-- 
cgit v1.2.3


From b186a9c3bfb5fdb93a8a0d80d7db8ad2a1587505 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:51:34 +0000
Subject: net.dns: resolver:getsocket(): Return nil, err on failure

---
 net/dns.lua | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/dns.lua b/net/dns.lua
index 23a453aa..0101daa3 100644
--- a/net/dns.lua
+++ b/net/dns.lua
@@ -602,7 +602,11 @@ function resolver:getsocket(servernum)    -- - - - - - - - - - - - - getsocket
 	local sock = self.socket[servernum];
 	if sock then return sock; end
 
-	sock = socket.udp();
+	local err;
+	sock, err = socket.udp();
+	if not sock then
+		return nil, err;
+	end
 	if self.socket_wrapper then sock = self.socket_wrapper(sock, self); end
 	sock:settimeout(0);
 	-- todo: attempt to use a random port, fallback to 0
-- 
cgit v1.2.3


From d3f185272930a58a3ce4f963ec1dffcbf7a5cab2 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:52:13 +0000
Subject: net.dns: resolver:query(): Handle getsocket() failures, and return
 true on success

---
 net/dns.lua | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/net/dns.lua b/net/dns.lua
index 0101daa3..61fb62e8 100644
--- a/net/dns.lua
+++ b/net/dns.lua
@@ -722,7 +722,10 @@ function resolver:query(qname, qtype, qclass)    -- - - - - - - - - - -- query
 		--set(self.yielded, co, qclass, qtype, qname, true);
 	end
 
-	local conn = self:getsocket(o.server)
+	local conn, err = self:getsocket(o.server)
+	if not conn then
+		return nil, err;
+	end
 	conn:send (o.packet)
 	
 	if timer and self.timeout then
@@ -734,16 +737,18 @@ function resolver:query(qname, qtype, qclass)    -- - - - - - - - - - -- query
 					i = i + 1;
 					self:servfail(conn);
 					o.server = self.best_server;
-					conn = self:getsocket(o.server);
-					conn:send(o.packet);
-					return self.timeout;
-				else
-					-- Tried everything, failed
-					self:cancel(qclass, qtype, qname, co, true);
+					conn, err = self:getsocket(o.server);
+					if conn then
+						conn:send(o.packet);
+						return self.timeout;
+					end
 				end
+				-- Tried everything, failed
+				self:cancel(qclass, qtype, qname, co, true);
 			end
 		end)
 	end
+	return true;
 end
 
 function resolver:servfail(sock)
-- 
cgit v1.2.3


From b1a22d59e455f22151650c88d622ee3a2710a9ca Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:52:40 +0000
Subject: net.adns: Handle dns.query() failures, and pass error to handler

---
 net/adns.lua | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/adns.lua b/net/adns.lua
index d0151c8c..2f7b6804 100644
--- a/net/adns.lua
+++ b/net/adns.lua
@@ -26,10 +26,17 @@ function lookup(handler, qname, qtype, qclass)
 					return;
 				end
 				log("debug", "Records for %s not in cache, sending query (%s)...", qname, tostring(coroutine.running()));
-				dns.query(qname, qtype, qclass);
-				coroutine.yield({ qclass or "IN", qtype or "A", qname, coroutine.running()}); -- Wait for reply
-				log("debug", "Reply for %s (%s)", qname, tostring(coroutine.running()));
-				local ok, err = pcall(handler, dns.peek(qname, qtype, qclass));
+				local ok, err = dns.query(qname, qtype, qclass);
+				if ok then
+					coroutine.yield({ qclass or "IN", qtype or "A", qname, coroutine.running()}); -- Wait for reply
+					log("debug", "Reply for %s (%s)", qname, tostring(coroutine.running()));
+				end
+				if ok then
+					ok, err = pcall(handler, dns.peek(qname, qtype, qclass));
+				else
+					log("error", "Error sending DNS query: %s", err);
+					ok, err = pcall(handler, nil, err);
+				end
 				if not ok then
 					log("error", "Error in DNS response handler: %s", tostring(err));
 				end
-- 
cgit v1.2.3


From 9502dc7be9248d9d7c9d1ef5ad3dd2f26d748e70 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:56:02 +0000
Subject: s2smanager: new_outgoing(): Destroy session if first connection
 attempt fails immediately (e.g. can't create sockets)

---
 core/s2smanager.lua | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index c7b950e2..8fa97c49 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -190,7 +190,11 @@ function new_outgoing(from_host, to_host, connect)
 		
 		if connect ~= false then
 			-- Kick the connection attempting machine into life
-			attempt_connection(host_session);
+			if not attempt_connection(host_session) then
+				-- Intentionally not returning here, the
+				-- session is needed, connected or not
+				destroy_session(host_session);
+			end
 		end
 		
 		if not host_session.sends2s then
-- 
cgit v1.2.3


From 0f27eda0d6c669de07363fdbb50648b5749b2a21 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:56:37 +0000
Subject: s2smanager: send_to_host(): Handle already-destroyed session and
 bounce stanza accordingly

---
 core/s2smanager.lua | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index 8fa97c49..cd381308 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -125,7 +125,10 @@ function send_to_host(from_host, to_host, data)
 		log("debug", "stanza [%s] queued until connection complete", tostring(data.name));
 		if (not host_session.connecting) and (not host_session.conn) then
 			log("warn", "Connection to %s failed already, destroying session...", to_host);
-			destroy_session(host_session);
+			if not destroy_session(host_session, "Connection failed") then
+				-- Already destroyed, we need to bounce our stanza
+				bounce_sendq(host_session, host_session.destruction_reason);
+			end
 			return false;
 		end
 	end
-- 
cgit v1.2.3


From ec15ee49795f6adde327b1731dcea6ec894346b8 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:57:17 +0000
Subject: s2smanager: Handle DNS lookup error in response handler

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

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index cd381308..dc0bf3d9 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -287,7 +287,7 @@ end
 function try_connect(host_session, connect_host, connect_port)
 	host_session.connecting = true;
 	local handle;
-	handle = adns.lookup(function (reply)
+	handle = adns.lookup(function (reply, err)
 		handle = nil;
 		host_session.connecting = nil;
 		
@@ -310,7 +310,8 @@ function try_connect(host_session, connect_host, connect_port)
 			log("debug", "DNS lookup failed to get a response for %s", connect_host);
 			if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can
 				log("debug", "No other records to try for %s - destroying", host_session.to_host);
-				destroy_session(host_session, "DNS resolution failed"); -- End of the line, we can't
+				err = err and (": "..err) or "";
+				destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't
 			end
 		end
 	end, connect_host, "A", "IN");
-- 
cgit v1.2.3


From 84b19928a500c595c1348bbef05c36a5484199e8 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 04:58:09 +0000
Subject: s2smanager: Destroy session on immediate failure of a connection
 attempt (e.g. inability to create sockets)

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

diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index dc0bf3d9..2af5ec1a 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -305,7 +305,13 @@ function try_connect(host_session, connect_host, connect_port)
 		
 		if reply and reply[#reply] and reply[#reply].a then
 			log("debug", "DNS reply for %s gives us %s", connect_host, reply[#reply].a);
-			return make_connect(host_session, reply[#reply].a, connect_port);
+			local ok, err = make_connect(host_session, reply[#reply].a, connect_port);
+			if not ok then
+				if not attempt_connection(host_session, err or "closed") then
+					err = err and (": "..err) or "";
+					destroy_session(host_session, "Connection failed"..err);
+				end
+			end
 		else
 			log("debug", "DNS lookup failed to get a response for %s", connect_host);
 			if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can
-- 
cgit v1.2.3


From 819fefe58ed1cc7580fb1b26779134f857f7edc5 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Fri, 24 Dec 2010 18:54:54 +0000
Subject: mod_saslauth: Handle session bind requests to the host, fixes OneTeam
 login

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

diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua
index c6ead31a..e1746c8e 100644
--- a/plugins/mod_saslauth.lua
+++ b/plugins/mod_saslauth.lua
@@ -189,7 +189,10 @@ module:hook("iq/self/urn:ietf:params:xml:ns:xmpp-bind:bind", function(event)
 	return true;
 end);
 
-module:hook("iq/self/urn:ietf:params:xml:ns:xmpp-session:session", function(event)
+local function handle_legacy_session(event)
 	event.origin.send(st.reply(event.stanza));
 	return true;
-end);
+end
+
+module:hook("iq/self/urn:ietf:params:xml:ns:xmpp-session:session", handle_legacy_session);
+module:hook("iq/host/urn:ietf:params:xml:ns:xmpp-session:session", handle_legacy_session);
-- 
cgit v1.2.3


From 33ff6899730227ef6145148097f80b83f07b27d9 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sun, 26 Dec 2010 05:00:45 +0000
Subject: configure: Don't add -llua to LDFLAGS, it's unnecessary

---
 configure | 2 --
 1 file changed, 2 deletions(-)

diff --git a/configure b/configure
index 50591f29..af046223 100755
--- a/configure
+++ b/configure
@@ -279,8 +279,6 @@ then
 	IDNA_LIBS="-l$IDN_LIB"
 fi
 
-LDFLAGS="$LDFLAGS -llua$LUA_SUFFIX"
-
 echo -n "Checking Lua includes... "
 lua_h="$LUA_INCDIR/lua.h"
 if [ -e "$lua_h" ]
-- 
cgit v1.2.3


From ff4b7235372ef96bc5663fce4aa7715c287e1665 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sun, 26 Dec 2010 05:01:58 +0000
Subject: util-src/Makefile: Clean up and remove unnecessary all linking

---
 util-src/Makefile | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/util-src/Makefile b/util-src/Makefile
index c3669c35..15af3e68 100644
--- a/util-src/Makefile
+++ b/util-src/Makefile
@@ -12,19 +12,20 @@ LD?=gcc
 
 .SUFFIXES: .c .o .so
 
-encodings.o:
-	$(CC) $(CFLAGS) -I$(LUA_INCDIR) -c -o encodings.o encodings.c
-
 encodings.so: encodings.o
 	MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET;
-	$(CC) $(LDFLAGS) $(IDNA_LIBS) -o encodings.so encodings.o -lcrypto
+	$(CC) $(LDFLAGS) $(IDNA_LIBS) -o $@ $<
+
+hashes.so: hashes.o
+	MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET;
+	$(CC) $(LDFLAGS) -l$(OPENSSL_LIB) -o $@ $<
 
 .c.o:
 	$(CC) $(CFLAGS) -I$(LUA_INCDIR) -c -o $@ $<
 
 .o.so:
 	MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET;
-	$(LD) $(LDFLAGS) -o $@ $< -lidn -lcrypto
+	$(LD) $(LDFLAGS) -o $@ $<
 
 all: encodings.so hashes.so pposix.so signal.so
 
-- 
cgit v1.2.3


From 5d2fe8b47955040411a5940fe8481b22941a7934 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sun, 26 Dec 2010 05:37:27 +0000
Subject: util-src/Makefile: Change parameter order so that LDFLAGS always
 comes later than the input files

---
 util-src/Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/util-src/Makefile b/util-src/Makefile
index 15af3e68..1ca934ad 100644
--- a/util-src/Makefile
+++ b/util-src/Makefile
@@ -14,18 +14,18 @@ LD?=gcc
 
 encodings.so: encodings.o
 	MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET;
-	$(CC) $(LDFLAGS) $(IDNA_LIBS) -o $@ $<
+	$(CC) -o $@ $< $(LDFLAGS) $(IDNA_LIBS)
 
 hashes.so: hashes.o
 	MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET;
-	$(CC) $(LDFLAGS) -l$(OPENSSL_LIB) -o $@ $<
+	$(CC) -o $@ $< $(LDFLAGS) -l$(OPENSSL_LIB)
 
 .c.o:
 	$(CC) $(CFLAGS) -I$(LUA_INCDIR) -c -o $@ $<
 
 .o.so:
 	MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET;
-	$(LD) $(LDFLAGS) -o $@ $<
+	$(LD) -o $@ $< $(LDFLAGS)
 
 all: encodings.so hashes.so pposix.so signal.so
 
-- 
cgit v1.2.3


From 3a5ee7ec2dbac739038db5bf79dcff7627fd4309 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sun, 26 Dec 2010 05:45:35 +0000
Subject: util.encodings: Switch comment styles to build ok as ANSI C

---
 util-src/encodings.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/util-src/encodings.c b/util-src/encodings.c
index a6fdada3..2a4653fb 100644
--- a/util-src/encodings.c
+++ b/util-src/encodings.c
@@ -12,7 +12,7 @@
 * Lua library for base64, stringprep and idna encodings
 */
 
-// Newer MSVC compilers deprecate strcpy as unsafe, but we use it in a safe way
+/* Newer MSVC compilers deprecate strcpy as unsafe, but we use it in a safe way */
 #define _CRT_SECURE_NO_DEPRECATE
 
 #include <string.h>
@@ -135,7 +135,7 @@ static int stringprep_prep(lua_State *L, const Stringprep_profile *profile)
 	s = lua_tolstring(L, 1, &len);
 	if (len >= 1024) {
 		lua_pushnil(L);
-		return 1; // TODO return error message
+		return 1; /* TODO return error message */
 	}
 	strcpy(string, s);
 	ret = stringprep(string, 1024, (Stringprep_profile_flags)0, profile);
@@ -144,7 +144,7 @@ static int stringprep_prep(lua_State *L, const Stringprep_profile *profile)
 		return 1;
 	} else {
 		lua_pushnil(L);
-		return 1; // TODO return error message
+		return 1; /* TODO return error message */
 	}
 }
 
@@ -261,7 +261,7 @@ static int Lidna_to_ascii(lua_State *L)		/** idna.to_ascii(s) */
 	} else {
 		lua_pushnil(L);
 		idn_free(output);
-		return 1; // TODO return error message
+		return 1; /* TODO return error message */
 	}
 }
 
@@ -278,7 +278,7 @@ static int Lidna_to_unicode(lua_State *L)		/** idna.to_unicode(s) */
 	} else {
 		lua_pushnil(L);
 		idn_free(output);
-		return 1; // TODO return error message
+		return 1; /* TODO return error message */
 	}
 }
 #else
-- 
cgit v1.2.3


From ae079311da4f326844508461169b93eb9ddfaf8f Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Sun, 26 Dec 2010 05:47:38 +0000
Subject: util.pposix: Remove extraneous semicolon

---
 util-src/pposix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/util-src/pposix.c b/util-src/pposix.c
index 4ff84bde..ffd21288 100644
--- a/util-src/pposix.c
+++ b/util-src/pposix.c
@@ -620,4 +620,4 @@ int luaopen_util_pposix(lua_State *L)
 	lua_setfield(L, -2, "_VERSION");
 
 	return 1;
-};
+}
-- 
cgit v1.2.3


From c23fedb91f14f5d026651ccb9ebe28c034216c82 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 06:10:34 +0500
Subject: modulemanager: Auto-load mod_offline.

---
 core/modulemanager.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/modulemanager.lua b/core/modulemanager.lua
index 8928ce14..0af9a271 100644
--- a/core/modulemanager.lua
+++ b/core/modulemanager.lua
@@ -39,7 +39,7 @@ end
 
 local array, set = require "util.array", require "util.set";
 
-local autoload_modules = {"presence", "message", "iq"};
+local autoload_modules = {"presence", "message", "iq", "offline"};
 local component_inheritable_modules = {"tls", "dialback", "iq"};
 
 -- We need this to let modules access the real global namespace
-- 
cgit v1.2.3


From 7bfadb35ede2969b0e286191346d60dc5b4fab40 Mon Sep 17 00:00:00 2001
From: Robert Hoelz <rob@hoelz.ro>
Date: Thu, 9 Dec 2010 12:23:37 -0600
Subject: core.offlinemanager, mod_message, mod_presence: Removed
 core.offlinemanager in favor of mod_offline.

---
 core/offlinemanager.lua  | 41 -----------------------------------------
 plugins/mod_message.lua  |  7 +++++--
 plugins/mod_presence.lua | 11 +++--------
 3 files changed, 8 insertions(+), 51 deletions(-)
 delete mode 100644 core/offlinemanager.lua

diff --git a/core/offlinemanager.lua b/core/offlinemanager.lua
deleted file mode 100644
index 97781e82..00000000
--- a/core/offlinemanager.lua
+++ /dev/null
@@ -1,41 +0,0 @@
--- Prosody IM
--- Copyright (C) 2008-2010 Matthew Wild
--- Copyright (C) 2008-2010 Waqas Hussain
--- 
--- This project is MIT/X11 licensed. Please see the
--- COPYING file in the source package for more information.
---
-
-
-
-local datamanager = require "util.datamanager";
-local st = require "util.stanza";
-local datetime = require "util.datetime";
-local ipairs = ipairs;
-
-module "offlinemanager"
-
-function store(node, host, stanza)
-	stanza.attr.stamp = datetime.datetime();
-	stanza.attr.stamp_legacy = datetime.legacy();
-	return datamanager.list_append(node, host, "offline", st.preserialize(stanza));
-end
-
-function load(node, host)
-	local data = datamanager.list_load(node, host, "offline");
-	if not data then return; end
-	for k, v in ipairs(data) do
-		local stanza = st.deserialize(v);
-		stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = host, stamp = stanza.attr.stamp}):up(); -- XEP-0203
-		stanza:tag("x", {xmlns = "jabber:x:delay", from = host, stamp = stanza.attr.stamp_legacy}):up(); -- XEP-0091 (deprecated)
-		stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;
-		data[k] = stanza;
-	end
-	return data;
-end
-
-function deleteAll(node, host)
-	return datamanager.list_store(node, host, "offline", nil);
-end
-
-return _M;
diff --git a/plugins/mod_message.lua b/plugins/mod_message.lua
index e38b60e6..6ac23ab2 100644
--- a/plugins/mod_message.lua
+++ b/plugins/mod_message.lua
@@ -14,7 +14,6 @@ local st = require "util.stanza";
 local jid_bare = require "util.jid".bare;
 local jid_split = require "util.jid".split;
 local user_exists = require "core.usermanager".user_exists;
-local offlinemanager = require "core.offlinemanager";
 local t_insert = table.insert;
 
 local function process_to_bare(bare, origin, stanza)
@@ -47,7 +46,11 @@ local function process_to_bare(bare, origin, stanza)
 		local node, host = jid_split(bare);
 		if user_exists(node, host) then
 			-- TODO apply the default privacy list
-			offlinemanager.store(node, host, stanza);
+
+                        module:fire_event('message/offline/store', {
+                            origin = origin,
+                            stanza = stanza,
+                        });
 		else
 			origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
 		end
diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua
index 65abe665..933aac62 100644
--- a/plugins/mod_presence.lua
+++ b/plugins/mod_presence.lua
@@ -22,7 +22,6 @@ local NULL = {};
 
 local rostermanager = require "core.rostermanager";
 local sessionmanager = require "core.sessionmanager";
-local offlinemanager = require "core.offlinemanager";
 
 local function select_top_resources(user)
 	local priority = 0;
@@ -116,13 +115,9 @@ function handle_normal_presence(origin, stanza)
 		end
 
 		if priority >= 0 then
-			local offline = offlinemanager.load(node, host);
-			if offline then
-				for _, msg in ipairs(offline) do
-					origin.send(msg); -- FIXME do we need to modify to/from in any way?
-				end
-				offlinemanager.deleteAll(node, host);
-			end
+                        local event = { origin = origin }
+                        module:fire_event('message/offline/broadcast', event);
+                        module:fire_event('message/offline/delete', event);
 		end
 	end
 	if stanza.attr.type == "unavailable" then
-- 
cgit v1.2.3


From f60a52f7131ceaba2f1baaa87f12a0ff8004b1ba Mon Sep 17 00:00:00 2001
From: Robert Hoelz <rob@hoelz.ro>
Date: Thu, 9 Dec 2010 12:28:05 -0600
Subject: mod_presence, mod_offline: Merge message/offline/delete with
 message/offline/broadcast.

---
 plugins/mod_offline.lua  | 8 +-------
 plugins/mod_presence.lua | 1 -
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/plugins/mod_offline.lua b/plugins/mod_offline.lua
index a3ca21d0..f44d16af 100644
--- a/plugins/mod_offline.lua
+++ b/plugins/mod_offline.lua
@@ -47,13 +47,7 @@ module:hook("message/offline/broadcast", function(event)
 			stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;
 			origin.send(stanza);
 		end
+		datamanager.list_store(node, host, "offline", nil);
 		return true;
 	end
 end);
-
-module:hook("message/offline/delete", function(event)
-	local origin = event.origin;
-	local node, host = origin.username, origin.host;
-
-	return datamanager.list_store(node, host, "offline", nil);
-end);
diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua
index 933aac62..61239c9a 100644
--- a/plugins/mod_presence.lua
+++ b/plugins/mod_presence.lua
@@ -117,7 +117,6 @@ function handle_normal_presence(origin, stanza)
 		if priority >= 0 then
                         local event = { origin = origin }
                         module:fire_event('message/offline/broadcast', event);
-                        module:fire_event('message/offline/delete', event);
 		end
 	end
 	if stanza.attr.type == "unavailable" then
-- 
cgit v1.2.3


From 5211c741efc2070ad7fa1bdad132fd7b6423ce53 Mon Sep 17 00:00:00 2001
From: Robert Hoelz <rob@hoelz.ro>
Date: Thu, 9 Dec 2010 12:36:29 -0600
Subject: mod_message: Send service-unavailable if offline storage fails.

---
 plugins/mod_message.lua | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/plugins/mod_message.lua b/plugins/mod_message.lua
index 6ac23ab2..bd4e353a 100644
--- a/plugins/mod_message.lua
+++ b/plugins/mod_message.lua
@@ -44,14 +44,17 @@ local function process_to_bare(bare, origin, stanza)
 		end
 		-- no resources are online
 		local node, host = jid_split(bare);
+		local ok
 		if user_exists(node, host) then
 			-- TODO apply the default privacy list
 
-                        module:fire_event('message/offline/store', {
-                            origin = origin,
-                            stanza = stanza,
-                        });
-		else
+			ok = module:fire_event('message/offline/store', {
+			    origin = origin,
+			    stanza = stanza,
+			});
+		end
+
+		if not ok then
 			origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
 		end
 	end
-- 
cgit v1.2.3


From d4d1388349098ec125e84b0f877ae999d75f6e22 Mon Sep 17 00:00:00 2001
From: Robert Hoelz <rob@hoelz.ro>
Date: Thu, 9 Dec 2010 12:38:33 -0600
Subject: mod_offline: Make sure mod_offline's store handler reports success vs
 failure.

---
 plugins/mod_offline.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plugins/mod_offline.lua b/plugins/mod_offline.lua
index f44d16af..d1370b41 100644
--- a/plugins/mod_offline.lua
+++ b/plugins/mod_offline.lua
@@ -29,7 +29,7 @@ module:hook("message/offline/store", function(event)
 	local result = datamanager.list_append(node, host, "offline", st.preserialize(stanza));
 	stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;
 	
-	return true;
+	return result;
 end);
 
 module:hook("message/offline/broadcast", function(event)
-- 
cgit v1.2.3


From 3e726703179ca5268d23fc595bbe11e5fb94d6f8 Mon Sep 17 00:00:00 2001
From: Robert Hoelz <rob@hoelz.ro>
Date: Thu, 9 Dec 2010 12:41:30 -0600
Subject: mod_message, mod_offline: Change message/offline/store ->
 message/offline/handle

---
 plugins/mod_message.lua | 2 +-
 plugins/mod_offline.lua | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/plugins/mod_message.lua b/plugins/mod_message.lua
index bd4e353a..df317532 100644
--- a/plugins/mod_message.lua
+++ b/plugins/mod_message.lua
@@ -48,7 +48,7 @@ local function process_to_bare(bare, origin, stanza)
 		if user_exists(node, host) then
 			-- TODO apply the default privacy list
 
-			ok = module:fire_event('message/offline/store', {
+			ok = module:fire_event('message/offline/handle', {
 			    origin = origin,
 			    stanza = stanza,
 			});
diff --git a/plugins/mod_offline.lua b/plugins/mod_offline.lua
index d1370b41..c956a40b 100644
--- a/plugins/mod_offline.lua
+++ b/plugins/mod_offline.lua
@@ -15,7 +15,7 @@ local jid_split = require "util.jid".split;
 
 module:add_feature("msgoffline");
 
-module:hook("message/offline/store", function(event)
+module:hook("message/offline/handle", function(event)
 	local origin, stanza = event.origin, event.stanza;
 	local to = stanza.attr.to;
 	local node, host;
-- 
cgit v1.2.3


From aa3093c81a91f9bc37e586d54dad36f312b62920 Mon Sep 17 00:00:00 2001
From: Robert Hoelz <rob@hoelz.ro>
Date: Thu, 9 Dec 2010 23:25:16 -0600
Subject: Don't check priority in mod_offline

---
 plugins/mod_offline.lua | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/plugins/mod_offline.lua b/plugins/mod_offline.lua
index c956a40b..1ac62f94 100644
--- a/plugins/mod_offline.lua
+++ b/plugins/mod_offline.lua
@@ -35,19 +35,17 @@ end);
 module:hook("message/offline/broadcast", function(event)
 	local origin = event.origin;
 
-	if origin.priority >= 0 then
-		local node, host = origin.username, origin.host;
+	local node, host = origin.username, origin.host;
 
-		local data = datamanager.list_load(node, host, "offline");
-		if not data then return true; end
-		for _, stanza in ipairs(data) do
-			stanza = st.deserialize(stanza);
-			stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = host, stamp = stanza.attr.stamp}):up(); -- XEP-0203
-			stanza:tag("x", {xmlns = "jabber:x:delay", from = host, stamp = stanza.attr.stamp_legacy}):up(); -- XEP-0091 (deprecated)
-			stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;
-			origin.send(stanza);
-		end
-		datamanager.list_store(node, host, "offline", nil);
-		return true;
+	local data = datamanager.list_load(node, host, "offline");
+	if not data then return true; end
+	for _, stanza in ipairs(data) do
+		stanza = st.deserialize(stanza);
+		stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = host, stamp = stanza.attr.stamp}):up(); -- XEP-0203
+		stanza:tag("x", {xmlns = "jabber:x:delay", from = host, stamp = stanza.attr.stamp_legacy}):up(); -- XEP-0091 (deprecated)
+		stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;
+		origin.send(stanza);
 	end
+	datamanager.list_store(node, host, "offline", nil);
+	return true;
 end);
-- 
cgit v1.2.3


From ef3729312cb9d7394f4dbf01cd717fe61dac7698 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 06:10:35 +0500
Subject: mod_storage_sql: Quote identifiers in SQL with backquotes, and use
 the empty string for NULL, and '=' instead of 'IS' for comparison, to work
 with MySQL's limitations...

---
 plugins/mod_storage_sql.lua | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index 3d5aa0a3..e5d5e86c 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -49,11 +49,11 @@ do -- process options to get a db connection
 	connection = dbh;
 	
 	if params.driver == "SQLite3" then -- auto initialize
-		local stmt = assert(connection:prepare("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='Prosody';"));
+		local stmt = assert(connection:prepare("SELECT COUNT(*) FROM `sqlite_master` WHERE `type`='table' AND `name`='Prosody';"));
 		local ok = assert(stmt:execute());
 		local count = stmt:fetch()[1];
 		if count == 0 then
-			local stmt = assert(connection:prepare("CREATE TABLE Prosody (host TEXT, user TEXT, store TEXT, key TEXT, subkey TEXT, type TEXT, value TEXT);"));
+			local stmt = assert(connection:prepare("CREATE TABLE `Prosody` (`host` TEXT, `user` TEXT, `store` TEXT, `key` TEXT, `subkey` TEXT, `type` TEXT, `value` TEXT);"));
 			assert(stmt:execute());
 			assert(connection:commit());
 			module:log("debug", "Initialized new SQLite3 database");
@@ -89,7 +89,7 @@ local function getsql(sql, ...)
 	local stmt, err = connection:prepare(sql);
 	if not stmt then return nil, err; end
 	-- run query
-	local ok, err = stmt:execute(host, user, store, ...);
+	local ok, err = stmt:execute(host or "", user or "", store or "", ...);
 	if not ok then return nil, err; end
 	
 	return stmt;
@@ -115,7 +115,7 @@ local keyval_store = {};
 keyval_store.__index = keyval_store;
 function keyval_store:get(username)
 	user,store = username,self.store;
-	local stmt, err = getsql("SELECT * FROM Prosody WHERE host IS ? AND user IS ? AND store IS ? AND subkey IS NULL");
+	local stmt, err = getsql("SELECT * FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `subkey`=''");
 	if not stmt then return nil, err; end
 	
 	local haveany;
@@ -137,15 +137,15 @@ end
 function keyval_store:set(username, data)
 	user,store = username,self.store;
 	-- start transaction
-	local affected, err = setsql("DELETE FROM Prosody WHERE host IS ? AND user IS ? AND store IS ? AND subkey IS NULL");
+	local affected, err = setsql("DELETE FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `subkey`=''");
 	
 	if data and next(data) ~= nil then
 		local extradata = {};
 		for key, value in pairs(data) do
-			if type(key) == "string" then
+			if type(key) == "string" and key ~= "" then
 				local t, value = serialize(value);
 				if not t then return rollback(t, value); end
-				local ok, err = setsql("INSERT INTO Prosody (host,user,store,key,type,value) VALUES (?,?,?,?,?,?)", key, t, value);
+				local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`type`,`value`,`subkey`) VALUES (?,?,?,?,?,?,'')", key or "", t, value);
 				if not ok then return rollback(ok, err); end
 			else
 				extradata[key] = value;
@@ -154,7 +154,7 @@ function keyval_store:set(username, data)
 		if next(extradata) ~= nil then
 			local t, extradata = serialize(extradata);
 			if not t then return rollback(t, extradata); end
-			local ok, err = setsql("INSERT INTO Prosody (host,user,store,key,type,value) VALUES (?,?,?,?,?,?)", nil, t, extradata);
+			local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`type`,`value`,`subkey`) VALUES (?,?,?,?,?,?,'')", "", t, extradata);
 			if not ok then return rollback(ok, err); end
 		end
 	end
@@ -165,7 +165,7 @@ local map_store = {};
 map_store.__index = map_store;
 function map_store:get(username, key)
 	user,store = username,self.store;
-	local stmt, err = getsql("SELECT * FROM Prosody WHERE host IS ? AND user IS ? AND store IS ? AND key IS ?", key);
+	local stmt, err = getsql("SELECT * FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", key or "");
 	if not stmt then return nil, err; end
 	
 	local haveany;
@@ -187,15 +187,15 @@ end
 function map_store:set(username, key, data)
 	user,store = username,self.store;
 	-- start transaction
-	local affected, err = setsql("DELETE FROM Prosody WHERE host IS ? AND user IS ? AND store IS ? AND key IS ?", key);
+	local affected, err = setsql("DELETE FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", key or "");
 	
 	if data and next(data) ~= nil then
 		local extradata = {};
 		for subkey, value in pairs(data) do
-			if type(subkey) == "string" then
+			if type(subkey) == "string" and key ~= "" then
 				local t, value = serialize(value);
 				if not t then return rollback(t, value); end
-				local ok, err = setsql("INSERT INTO Prosody (host,user,store,key,subkey,type,value) VALUES (?,?,?,?,?,?)", key, subkey, t, value);
+				local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`subkey`,`type`,`value`) VALUES (?,?,?,?,?,?,?)", key or "", subkey or "", t, value);
 				if not ok then return rollback(ok, err); end
 			else
 				extradata[subkey] = value;
@@ -204,7 +204,7 @@ function map_store:set(username, key, data)
 		if next(extradata) ~= nil then
 			local t, extradata = serialize(extradata);
 			if not t then return rollback(t, extradata); end
-			local ok, err = setsql("INSERT INTO Prosody (host,user,store,key,subkey,type,value) VALUES (?,?,?,?,?,?)", key, nil, t, extradata);
+			local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`subkey`,`type`,`value`) VALUES (?,?,?,?,?,?,?)", key or "", "", t, extradata);
 			if not ok then return rollback(ok, err); end
 		end
 	end
@@ -219,10 +219,10 @@ function list_store:scan(username, from, to, jid, typ)
 	local cols = {"from", "to", "jid", "typ"};
 	local vals = { from ,  to ,  jid ,  typ };
 	local stmt, err;
-	local query = "SELECT * FROM ProsodyArchive WHERE host IS ? AND user IS ? AND store IS ?";
+	local query = "SELECT * FROM `ProsodyArchive` WHERE `host`=? AND `user`=? AND `store`=?";
 	
 	query = query.." ORDER BY time";
-	--local stmt, err = getsql("SELECT * FROM Prosody WHERE host IS ? AND user IS ? AND store IS ? AND key IS ?", key);
+	--local stmt, err = getsql("SELECT * FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", key or "");
 	
 	return nil, "not-implemented"
 end
-- 
cgit v1.2.3


From 92c4204ee2bedfdf279e7d2051ed1a9293a61802 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 06:10:35 +0500
Subject: mod_storage_sql: Call commit() after all SQL statements, including
 SELECT, to get SQLite to drop its locks.

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

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index e5d5e86c..12c8eebe 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -55,9 +55,9 @@ do -- process options to get a db connection
 		if count == 0 then
 			local stmt = assert(connection:prepare("CREATE TABLE `Prosody` (`host` TEXT, `user` TEXT, `store` TEXT, `key` TEXT, `subkey` TEXT, `type` TEXT, `value` TEXT);"));
 			assert(stmt:execute());
-			assert(connection:commit());
 			module:log("debug", "Initialized new SQLite3 database");
 		end
+		assert(connection:commit());
 		--print("===", json.stringify())
 	end
 end
@@ -132,7 +132,7 @@ function keyval_store:get(username)
 			end
 		end
 	end
-	return haveany and result or nil;
+	return commit(haveany and result or nil);
 end
 function keyval_store:set(username, data)
 	user,store = username,self.store;
@@ -182,7 +182,7 @@ function map_store:get(username, key)
 			end
 		end
 	end
-	return haveany and result or nil;
+	return commit(haveany and result or nil);
 end
 function map_store:set(username, key, data)
 	user,store = username,self.store;
-- 
cgit v1.2.3


From e96a87344cf41cf392f29692b43225995f271c2c Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 06:10:35 +0500
Subject: mod_storage_sql: Dynamically replace backquotes with double quotes
 when connecting to PostgreSQL...

---
 plugins/mod_storage_sql.lua | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index 12c8eebe..ca024329 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -29,12 +29,13 @@ local json = { stringify = function(s) return require"util.serialization".serial
 
 local connection = ...;
 local host,user,store = module.host;
+local params = module:get_option("sql");
 
 do -- process options to get a db connection
 	local DBI = require "DBI";
 
-	local params = module:get_option("sql") or { driver = "SQLite3", database = "prosody.sqlite" };
-	assert(params and params.driver and params.database, "invalid params");
+	params = params or { driver = "SQLite3", database = "prosody.sqlite" };
+	assert(params.driver and params.database, "invalid params");
 	
 	prosody.unlock_globals();
 	local dbh, err = DBI.Connect(
@@ -85,6 +86,9 @@ local function deserialize(t, value)
 end
 
 local function getsql(sql, ...)
+	if params.driver == "PostgreSQL" then
+		sql = sql:gsub("`", "\"");
+	end
 	-- do prepared statement stuff
 	local stmt, err = connection:prepare(sql);
 	if not stmt then return nil, err; end
-- 
cgit v1.2.3


From 7320deb664449e74b6a78420a2b287de9ee2d41b Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 06:10:35 +0500
Subject: mod_storage_sql: Remove the subkey column from the Prosody table, and
 make the map store compatible with the key-value store.

---
 plugins/mod_storage_sql.lua | 51 +++++++++++++++++++--------------------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index ca024329..85c9fbdf 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -3,16 +3,16 @@
 
 DB Tables:
 	Prosody - key-value, map
-		| host | user | store | key | subkey | type | value |
+		| host | user | store | key | type | value |
 	ProsodyArchive - list
 		| host | user | store | key | time | stanzatype | jsonvalue |
 
 Mapping:
 	Roster - Prosody
-		| host | user | "roster" | "contactjid" | item-subkey | type | value |
-		| host | user | "roster" | NULL | NULL | "json" | roster[false] data |
+		| host | user | "roster" | "contactjid" | type | value |
+		| host | user | "roster" | NULL | "json" | roster[false] data |
 	Account - Prosody
-		| host | user | "accounts" | "username" | NULL | type | value |
+		| host | user | "accounts" | "username" | type | value |
 
 	Offline - ProsodyArchive
 		| host | user | "offline" | "contactjid" | time | "message" | json|XML |
@@ -54,7 +54,7 @@ do -- process options to get a db connection
 		local ok = assert(stmt:execute());
 		local count = stmt:fetch()[1];
 		if count == 0 then
-			local stmt = assert(connection:prepare("CREATE TABLE `Prosody` (`host` TEXT, `user` TEXT, `store` TEXT, `key` TEXT, `subkey` TEXT, `type` TEXT, `value` TEXT);"));
+			local stmt = assert(connection:prepare("CREATE TABLE `Prosody` (`host` TEXT, `user` TEXT, `store` TEXT, `key` TEXT, `type` TEXT, `value` TEXT);"));
 			assert(stmt:execute());
 			module:log("debug", "Initialized new SQLite3 database");
 		end
@@ -119,7 +119,7 @@ local keyval_store = {};
 keyval_store.__index = keyval_store;
 function keyval_store:get(username)
 	user,store = username,self.store;
-	local stmt, err = getsql("SELECT * FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `subkey`=''");
+	local stmt, err = getsql("SELECT * FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=?");
 	if not stmt then return nil, err; end
 	
 	local haveany;
@@ -128,8 +128,8 @@ function keyval_store:get(username)
 		haveany = true;
 		local k = row.key;
 		local v = deserialize(row.type, row.value);
-		if v then
-			if k then result[k] = v; elseif type(v) == "table" then
+		if k and v then
+			if k ~= "" then result[k] = v; elseif type(v) == "table" then
 				for a,b in pairs(v) do
 					result[a] = b;
 				end
@@ -141,7 +141,7 @@ end
 function keyval_store:set(username, data)
 	user,store = username,self.store;
 	-- start transaction
-	local affected, err = setsql("DELETE FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `subkey`=''");
+	local affected, err = setsql("DELETE FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=?");
 	
 	if data and next(data) ~= nil then
 		local extradata = {};
@@ -149,7 +149,7 @@ function keyval_store:set(username, data)
 			if type(key) == "string" and key ~= "" then
 				local t, value = serialize(value);
 				if not t then return rollback(t, value); end
-				local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`type`,`value`,`subkey`) VALUES (?,?,?,?,?,?,'')", key or "", t, value);
+				local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`type`,`value`) VALUES (?,?,?,?,?,?)", key, t, value);
 				if not ok then return rollback(ok, err); end
 			else
 				extradata[key] = value;
@@ -158,7 +158,7 @@ function keyval_store:set(username, data)
 		if next(extradata) ~= nil then
 			local t, extradata = serialize(extradata);
 			if not t then return rollback(t, extradata); end
-			local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`type`,`value`,`subkey`) VALUES (?,?,?,?,?,?,'')", "", t, extradata);
+			local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`type`,`value`) VALUES (?,?,?,?,?,?)", "", t, extradata);
 			if not ok then return rollback(ok, err); end
 		end
 	end
@@ -176,17 +176,17 @@ function map_store:get(username, key)
 	local result = {};
 	for row in stmt:rows(true) do
 		haveany = true;
-		local k = row.subkey;
+		local k = row.key;
 		local v = deserialize(row.type, row.value);
-		if v then
-			if k then result[k] = v; elseif type(v) == "table" then
+		if k and v then
+			if k ~= "" then result[k] = v; elseif type(v) == "table" then
 				for a,b in pairs(v) do
 					result[a] = b;
 				end
 			end
 		end
 	end
-	return commit(haveany and result or nil);
+	return commit(haveany and result[key] or nil);
 end
 function map_store:set(username, key, data)
 	user,store = username,self.store;
@@ -194,22 +194,13 @@ function map_store:set(username, key, data)
 	local affected, err = setsql("DELETE FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", key or "");
 	
 	if data and next(data) ~= nil then
-		local extradata = {};
-		for subkey, value in pairs(data) do
-			if type(subkey) == "string" and key ~= "" then
-				local t, value = serialize(value);
-				if not t then return rollback(t, value); end
-				local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`subkey`,`type`,`value`) VALUES (?,?,?,?,?,?,?)", key or "", subkey or "", t, value);
-				if not ok then return rollback(ok, err); end
-			else
-				extradata[subkey] = value;
-			end
-		end
-		if next(extradata) ~= nil then
-			local t, extradata = serialize(extradata);
-			if not t then return rollback(t, extradata); end
-			local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`subkey`,`type`,`value`) VALUES (?,?,?,?,?,?,?)", key or "", "", t, extradata);
+		if type(key) == "string" and key ~= "" then
+			local t, value = serialize(data);
+			if not t then return rollback(t, value); end
+			local ok, err = setsql("INSERT INTO `Prosody` (`host`,`user`,`store`,`key`,`type`,`value`) VALUES (?,?,?,?,?,?)", key, t, value);
 			if not ok then return rollback(ok, err); end
+		else
+			-- TODO non-string keys
 		end
 	end
 	return commit(true);
-- 
cgit v1.2.3


From d2117a8141eae8edb22862a48e14268258b3df85 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 06:10:35 +0500
Subject: mod_storage_sql: Log an error on query failure.

---
 plugins/mod_storage_sql.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index 85c9fbdf..75080726 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -91,7 +91,7 @@ local function getsql(sql, ...)
 	end
 	-- do prepared statement stuff
 	local stmt, err = connection:prepare(sql);
-	if not stmt then return nil, err; end
+	if not stmt then module:log("error", "QUERY FAILED: %s %s", err, debug.traceback()); return nil, err; end
 	-- run query
 	local ok, err = stmt:execute(host or "", user or "", store or "", ...);
 	if not ok then return nil, err; end
-- 
cgit v1.2.3


From 75e3837663ee13a9b81dd585356b001d70e7a59b Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 19:37:04 +0500
Subject: util.json: Initial commit.

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

diff --git a/util/json.lua b/util/json.lua
new file mode 100644
index 00000000..40939bb4
--- /dev/null
+++ b/util/json.lua
@@ -0,0 +1,356 @@
+
+local type = type;
+local t_insert, t_concat, t_remove = table.insert, table.concat, table.remove;
+local s_char = string.char;
+local tostring, tonumber = tostring, tonumber;
+local pairs, ipairs = pairs, ipairs;
+local next = next;
+local error = error;
+local newproxy, getmetatable = newproxy, getmetatable;
+local print = print;
+
+--module("json")
+local json = {};
+
+local null = newproxy and newproxy(true) or {};
+if getmetatable and getmetatable(null) then
+	getmetatable(null).__tostring = function() return "null"; end;
+end
+json.null = null;
+
+local escapes = {
+	["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b",
+	["\f"] = "\\f", ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"};
+local unescapes = {
+	["\""] = "\"", ["\\"] = "\\", ["/"] = "/",
+	b = "\b", f = "\f", n = "\n", r = "\r", t = "\t"};
+for i=0,31 do
+	local ch = s_char(i);
+	if not escapes[ch] then escapes[ch] = ("\\u%.4X"):format(i); end
+end
+
+local valid_types = {
+	number  = true,
+	string  = true,
+	table   = true,
+	boolean = true
+};
+local special_keys = {
+	__array = true;
+	__hash  = true;
+};
+
+local simplesave, tablesave, arraysave, stringsave;
+
+function stringsave(o, buffer)
+	-- FIXME do proper utf-8 and binary data detection
+	t_insert(buffer, "\""..(o:gsub(".", escapes)).."\"");
+end
+
+function arraysave(o, buffer)
+	t_insert(buffer, "[");
+	if next(o) then
+		for i,v in ipairs(o) do
+			simplesave(v, buffer);
+			t_insert(buffer, ",");
+		end
+		t_remove(buffer);
+	end
+	t_insert(buffer, "]");
+end
+
+function tablesave(o, buffer)
+	local __array = {};
+	local __hash = {};
+	local hash = {};
+	for i,v in ipairs(o) do
+		__array[i] = v;
+	end
+	for k,v in pairs(o) do
+		local ktype, vtype = type(k), type(v);
+		if valid_types[vtype] or v == null then
+			if ktype == "string" and not special_keys[k] then
+				hash[k] = v;
+			elseif (valid_types[ktype] or k == null) and __array[k] == nil then
+				__hash[k] = v;
+			end
+		end
+	end
+	if next(__hash) ~= nil or next(hash) ~= nil or next(__array) == nil then
+		t_insert(buffer, "{");
+		local mark = #buffer;
+		for k,v in pairs(hash) do
+			stringsave(k, buffer);
+			t_insert(buffer, ":");
+			simplesave(v, buffer);
+			t_insert(buffer, ",");
+		end
+		if next(__hash) ~= nil then
+			t_insert(buffer, "\"__hash\":[");
+			for k,v in pairs(__hash) do
+				simplesave(k, buffer);
+				t_insert(buffer, ",");
+				simplesave(v, buffer);
+				t_insert(buffer, ",");
+			end
+			t_remove(buffer);
+			t_insert(buffer, "]");
+			t_insert(buffer, ",");
+		end
+		if next(__array) then
+			t_insert(buffer, "\"__array\":");
+			arraysave(__array, buffer);
+			t_insert(buffer, ",");
+		end
+		if mark ~= #buffer then t_remove(buffer); end
+		t_insert(buffer, "}");
+	else
+		arraysave(__array, buffer);
+	end
+end
+
+function simplesave(o, buffer)
+	local t = type(o);
+	if t == "number" then
+		t_insert(buffer, tostring(o));
+	elseif t == "string" then
+		stringsave(o, buffer);
+	elseif t == "table" then
+		tablesave(o, buffer);
+	elseif t == "boolean" then
+		t_insert(buffer, (o and "true" or "false"));
+	else
+		t_insert(buffer, "null");
+	end
+end
+
+function json.encode(obj)
+	local t = {};
+	simplesave(obj, t);
+	return t_concat(t);
+end
+
+-----------------------------------
+
+
+function json.decode(json)
+	local pos = 1;
+	local current = {};
+	local stack = {};
+	local ch, peek;
+	local function next()
+		ch = json:sub(pos, pos);
+		pos = pos+1;
+		peek = json:sub(pos, pos);
+		return ch;
+	end
+	
+	local function skipwhitespace()
+		while ch and (ch == "\r" or ch == "\n" or ch == "\t" or ch == " ") do
+			next();
+		end
+	end
+	local function skiplinecomment()
+		repeat next(); until not(ch) or ch == "\r" or ch == "\n";
+		skipwhitespace();
+	end
+	local function skipstarcomment()
+		next(); next(); -- skip '/', '*'
+		while peek and ch ~= "*" and peek ~= "/" do next(); end
+		if not peek then error("eof in star comment") end
+		next(); next(); -- skip '*', '/'
+		skipwhitespace();
+	end
+	local function skipstuff()
+		while true do
+			skipwhitespace();
+			if ch == "/" and peek == "*" then
+				skipstarcomment();
+			elseif ch == "/" and peek == "*" then
+				skiplinecomment();
+			else
+				return;
+			end
+		end
+	end
+	
+	local readvalue;
+	local function readarray()
+		local t = {};
+		next(); -- skip '['
+		skipstuff();
+		if ch == "]" then next(); return t; end
+		t_insert(t, readvalue());
+		while true do
+			skipstuff();
+			if ch == "]" then next(); return t; end
+			if not ch then error("eof while reading array");
+			elseif ch == "," then next();
+			elseif ch then error("unexpected character in array, comma expected"); end
+			if not ch then error("eof while reading array"); end
+			t_insert(t, readvalue());
+		end
+	end
+	
+	local function checkandskip(c)
+		local x = ch or "eof";
+		if x ~= c then error("unexpected "..x..", '"..c.."' expected"); end
+		next();
+	end
+	local function readliteral(lit, val)
+		for c in lit:gmatch(".") do
+			checkandskip(c);
+		end
+		return val;
+	end
+	local function readstring()
+		local s = "";
+		checkandskip("\"");
+		while ch do
+			while ch and ch ~= "\\" and ch ~= "\"" do
+				s = s..ch; next();
+			end
+			if ch == "\\" then
+				next();
+				if unescapes[ch] then
+					s = s..unescapes[ch];
+					next();
+				elseif ch == "u" then
+					local seq = "";
+					for i=1,4 do
+						next();
+						if not ch then error("unexpected eof in string"); end
+						if not ch:match("[0-9a-fA-F]") then error("invalid unicode escape sequence in string"); end
+						seq = seq..ch;
+					end
+					s = s..s.char(tonumber(seq, 16)); -- FIXME do proper utf-8
+					next();
+				else error("invalid escape sequence in string"); end
+			end
+			if ch == "\"" then
+				next();
+				return s;
+			end
+		end
+		error("eof while reading string");
+	end
+	local function readnumber()
+		local s = "";
+		if ch == "-" then
+			s = s..ch; next();
+			if not ch:match("[0-9]") then error("number format error"); end
+		end
+		if ch == "0" then
+			s = s..ch; next();
+			if ch:match("[0-9]") then error("number format error"); end
+		else
+			while ch and ch:match("[0-9]") do
+				s = s..ch; next();
+			end
+		end
+		if ch == "." then
+			s = s..ch; next();
+			if not ch:match("[0-9]") then error("number format error"); end
+			while ch and ch:match("[0-9]") do
+				s = s..ch; next();
+			end
+			if ch == "e" or ch == "E" then
+				s = s..ch; next();
+				if ch == "+" or ch == "-" then
+					s = s..ch; next();
+					if not ch:match("[0-9]") then error("number format error"); end
+					while ch and ch:match("[0-9]") do
+						s = s..ch; next();
+					end
+				end
+			end
+		end
+		return tonumber(s);
+	end
+	local function readmember(t)
+		local k = readstring();
+		checkandskip(":");
+		t[k] = readvalue();
+	end
+	local function fixobject(obj)
+		local __array = obj.__array;
+		if __array then
+			obj.__array = nil;
+			for i,v in ipairs(__array) do
+				t_insert(obj, v);
+			end
+		end
+		local __hash = obj.__hash;
+		if __hash then
+			obj.__hash = nil;
+			local k;
+			for i,v in ipairs(__hash) do
+				if k ~= nil then
+					obj[k] = v; k = nil;
+				else
+					k = v;
+				end
+			end
+		end
+		return obj;
+	end
+	local function readobject()
+		local t = {};
+		next(); -- skip '{'
+		skipstuff();
+		if ch == "}" then next(); return t; end
+		if not ch then error("eof while reading object"); end
+		readmember(t);
+		while true do
+			skipstuff();
+			if ch == "}" then next(); return fixobject(t); end
+			if not ch then error("eof while reading object");
+			elseif ch == "," then next();
+			elseif ch then error("unexpected character in object, comma expected"); end
+			if not ch then error("eof while reading object"); end
+			readmember(t);
+		end
+	end
+	
+	function readvalue()
+		skipstuff();
+		while ch do
+			if ch == "{" then
+				return readobject();
+			elseif ch == "[" then
+				return readarray();
+			elseif ch == "\"" then
+				return readstring();
+			elseif ch:match("[%-0-9%.]") then
+				return readnumber();
+			elseif ch == "n" then
+				return readliteral("null", null);
+			elseif ch == "t" then
+				return readliteral("true", true);
+			elseif ch == "f" then
+				return readliteral("false", false);
+			else
+				error("invalid character at value start: "..ch);
+			end
+		end
+		error("eof while reading value");
+	end
+	next();
+	return readvalue();
+end
+
+function json.test(object)
+	local encoded = json.encode(object);
+	local decoded = json.decode(encoded);
+	local recoded = json.encode(decoded);
+	if encoded ~= recoded then
+		print("FAILED");
+		print("encoded:", encoded);
+		print("recoded:", recoded);
+	else
+		print(encoded);
+	end
+	return encoded == recoded;
+end
+
+return json;
-- 
cgit v1.2.3


From c1d6450cec9153c4b6c3d46ed1127a4eee092c50 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 19:43:57 +0500
Subject: mod_storage_sql: Use util.json instead of util.serialization.

---
 plugins/mod_storage_sql.lua | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index 75080726..53f1ea0a 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -25,7 +25,7 @@ local tonumber = tonumber;
 local pairs = pairs;
 local next = next;
 local setmetatable = setmetatable;
-local json = { stringify = function(s) return require"util.serialization".serialize(s) end, parse = require"util.serialization".deserialize };
+local json = require "util.json";
 
 local connection = ...;
 local host,user,store = module.host;
@@ -59,7 +59,7 @@ do -- process options to get a db connection
 			module:log("debug", "Initialized new SQLite3 database");
 		end
 		assert(connection:commit());
-		--print("===", json.stringify())
+		--print("===", json.encode())
 	end
 end
 
@@ -68,7 +68,7 @@ local function serialize(value)
 	if t == "string" or t == "boolean" or t == "number" then
 		return t, tostring(value);
 	elseif t == "table" then
-		local value,err = json.stringify(value);
+		local value,err = json.encode(value);
 		if value then return "json", value; end
 		return nil, err;
 	end
@@ -81,7 +81,7 @@ local function deserialize(t, value)
 		elseif value == "false" then return false; end
 	elseif t == "number" then return tonumber(value);
 	elseif t == "json" then
-		return json.parse(value);
+		return json.decode(value);
 	end
 end
 
-- 
cgit v1.2.3


From 1865c2454bf4037fdc992485451de1fc5214c508 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 19:57:04 +0500
Subject: util.sasl.*, mod_auth_*, mod_saslauth: Pass SASL handler as first
 parameter to SASL profile callbacks.

---
 plugins/mod_auth_anonymous.lua       | 2 +-
 plugins/mod_auth_internal_hashed.lua | 4 ++--
 plugins/mod_auth_internal_plain.lua  | 2 +-
 plugins/mod_saslauth.lua             | 2 +-
 util/sasl/anonymous.lua              | 2 +-
 util/sasl/digest-md5.lua             | 4 ++--
 util/sasl/plain.lua                  | 4 ++--
 util/sasl/scram.lua                  | 4 ++--
 8 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/plugins/mod_auth_anonymous.lua b/plugins/mod_auth_anonymous.lua
index 0741a158..9d0896e5 100644
--- a/plugins/mod_auth_anonymous.lua
+++ b/plugins/mod_auth_anonymous.lua
@@ -36,7 +36,7 @@ function new_default_provider(host)
 	function provider.get_sasl_handler()
 		local realm = module:get_option("sasl_realm") or module.host;
 		local anonymous_authentication_profile = {
-			anonymous = function(username, realm)
+			anonymous = function(sasl, username, realm)
 				return true; -- for normal usage you should always return true here
 			end
 		};
diff --git a/plugins/mod_auth_internal_hashed.lua b/plugins/mod_auth_internal_hashed.lua
index 300bebf8..ec8da9ab 100644
--- a/plugins/mod_auth_internal_hashed.lua
+++ b/plugins/mod_auth_internal_hashed.lua
@@ -138,7 +138,7 @@ function new_hashpass_provider(host)
 	function provider.get_sasl_handler()
 		local realm = module:get_option("sasl_realm") or module.host;
 		local testpass_authentication_profile = {
-			plain_test = function(username, password, realm)
+			plain_test = function(sasl, username, password, realm)
 				local prepped_username = nodeprep(username);
 				if not prepped_username then
 					log("debug", "NODEprep failed on username: %s", username);
@@ -146,7 +146,7 @@ function new_hashpass_provider(host)
 				end
 				return usermanager.test_password(prepped_username, realm, password), true;
 			end,
-			scram_sha_1 = function(username, realm)
+			scram_sha_1 = function(sasl, username, realm)
 				local credentials = datamanager.load(username, host, "accounts");
 				if not credentials then return; end
 				if credentials.password then
diff --git a/plugins/mod_auth_internal_plain.lua b/plugins/mod_auth_internal_plain.lua
index 4cf0edb6..3721781b 100644
--- a/plugins/mod_auth_internal_plain.lua
+++ b/plugins/mod_auth_internal_plain.lua
@@ -66,7 +66,7 @@ function new_default_provider(host)
 	function provider.get_sasl_handler()
 		local realm = module:get_option("sasl_realm") or module.host;
 		local getpass_authentication_profile = {
-			plain = function(username, realm)
+			plain = function(sasl, username, realm)
 				local prepped_username = nodeprep(username);
 				if not prepped_username then
 					log("debug", "NODEprep failed on username: %s", username);
diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua
index e1746c8e..65053ffa 100644
--- a/plugins/mod_saslauth.lua
+++ b/plugins/mod_saslauth.lua
@@ -31,7 +31,7 @@ local xmlns_stanzas ='urn:ietf:params:xml:ns:xmpp-stanzas';
 local new_sasl = require "util.sasl".new;
 
 local anonymous_authentication_profile = {
-	anonymous = function(username, realm)
+	anonymous = function(sasl, username, realm)
 		return true; -- for normal usage you should always return true here
 	end
 };
diff --git a/util/sasl/anonymous.lua b/util/sasl/anonymous.lua
index 6e6f0949..b9af17fe 100644
--- a/util/sasl/anonymous.lua
+++ b/util/sasl/anonymous.lua
@@ -34,7 +34,7 @@ local function anonymous(self, message)
 	local username;
 	repeat
 		username = generate_uuid();
-	until self.profile.anonymous(username, self.realm);
+	until self.profile.anonymous(self, username, self.realm);
 	self.username = username;
 	return "success"
 end
diff --git a/util/sasl/digest-md5.lua b/util/sasl/digest-md5.lua
index 2837148e..6f2c765e 100644
--- a/util/sasl/digest-md5.lua
+++ b/util/sasl/digest-md5.lua
@@ -181,12 +181,12 @@ local function digest(self, message)
 		self.username = response["username"];
 		local Y, state;
 		if self.profile.plain then
-			local password, state = self.profile.plain(response["username"], self.realm)
+			local password, state = self.profile.plain(self, response["username"], self.realm)
 			if state == nil then return "failure", "not-authorized"
 			elseif state == false then return "failure", "account-disabled" end
 			Y = md5(response["username"]..":"..response["realm"]..":"..password);
 		elseif self.profile["digest-md5"] then
-			Y, state = self.profile["digest-md5"](response["username"], self.realm, response["realm"], response["charset"])
+			Y, state = self.profile["digest-md5"](self, response["username"], self.realm, response["realm"], response["charset"])
 			if state == nil then return "failure", "not-authorized"
 			elseif state == false then return "failure", "account-disabled" end
 		elseif self.profile["digest-md5-test"] then
diff --git a/util/sasl/plain.lua b/util/sasl/plain.lua
index 1a2ba01e..d6ebe304 100644
--- a/util/sasl/plain.lua
+++ b/util/sasl/plain.lua
@@ -57,10 +57,10 @@ local function plain(self, message)
 	local correct, state = false, false;
 	if self.profile.plain then
 		local correct_password;
-		correct_password, state = self.profile.plain(authentication, self.realm);
+		correct_password, state = self.profile.plain(self, authentication, self.realm);
 		correct = (correct_password == password);
 	elseif self.profile.plain_test then
-		correct, state = self.profile.plain_test(authentication, password, self.realm);
+		correct, state = self.profile.plain_test(self, authentication, password, self.realm);
 	end
 
 	self.username = authentication
diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua
index c846a7d1..530ef5a0 100644
--- a/util/sasl/scram.lua
+++ b/util/sasl/scram.lua
@@ -143,7 +143,7 @@ local function scram_gen(hash_name, H_f, HMAC_f)
 			
 			-- retreive credentials
 			if self.profile.plain then
-				local password, state = self.profile.plain(self.state.name, self.realm)
+				local password, state = self.profile.plain(self, self.state.name, self.realm)
 				if state == nil then return "failure", "not-authorized"
 				elseif state == false then return "failure", "account-disabled" end
 				
@@ -163,7 +163,7 @@ local function scram_gen(hash_name, H_f, HMAC_f)
 					return "failure", "temporary-auth-failure";
 				end
 			elseif self.profile["scram_"..hashprep(hash_name)] then
-				local stored_key, server_key, iteration_count, salt, state = self.profile["scram_"..hashprep(hash_name)](self.state.name, self.realm);
+				local stored_key, server_key, iteration_count, salt, state = self.profile["scram_"..hashprep(hash_name)](self, self.state.name, self.realm);
 				if state == nil then return "failure", "not-authorized"
 				elseif state == false then return "failure", "account-disabled" end
 				
-- 
cgit v1.2.3


From 318b00eeb121d48c1e1466cc67419a4f8830debd Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Mon, 27 Dec 2010 20:46:01 +0500
Subject: usermanager: Assume authentication="anonymous" when
 anonymous_login=true.

---
 core/usermanager.lua | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/core/usermanager.lua b/core/usermanager.lua
index 1aea0de9..2e64af8c 100644
--- a/core/usermanager.lua
+++ b/core/usermanager.lua
@@ -36,6 +36,7 @@ function initialize_host(host)
 	host_session.events.add_handler("item-added/auth-provider", function (event)
 		local provider = event.item;
 		local auth_provider = config.get(host, "core", "authentication") or default_provider;
+		if config.get(host, "core", "anonymous_login") then auth_provider = "anonymous"; end -- COMPAT 0.7
 		if provider.name == auth_provider then
 			host_session.users = provider;
 		end
@@ -51,6 +52,7 @@ function initialize_host(host)
 	end);
 	host_session.users = new_null_provider(); -- Start with the default usermanager provider
 	local auth_provider = config.get(host, "core", "authentication") or default_provider;
+	if config.get(host, "core", "anonymous_login") then auth_provider = "anonymous"; end -- COMPAT 0.7
 	if auth_provider ~= "null" then
 		modulemanager.load(host, "auth_"..auth_provider);
 	end
-- 
cgit v1.2.3


From 55d5f1ffe35463b0a0790af1b9131110f7a756ad Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Tue, 28 Dec 2010 05:28:15 +0500
Subject: mod_saslauth: Remove special handling for SASL ANONYMOUS, and let
 mod_auth_anonymous handle it.

---
 plugins/mod_saslauth.lua | 31 ++-----------------------------
 1 file changed, 2 insertions(+), 29 deletions(-)

diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua
index 65053ffa..4906d01f 100644
--- a/plugins/mod_saslauth.lua
+++ b/plugins/mod_saslauth.lua
@@ -15,11 +15,9 @@ local base64 = require "util.encodings".base64;
 
 local nodeprep = require "util.encodings".stringprep.nodeprep;
 local usermanager_get_sasl_handler = require "core.usermanager".get_sasl_handler;
-local t_concat, t_insert = table.concat, table.insert;
 local tostring = tostring;
 
 local secure_auth_only = module:get_option("c2s_require_encryption") or module:get_option("require_encryption");
-local anonymous_login = module:get_option("anonymous_login");
 local allow_unencrypted_plain_auth = module:get_option("allow_unencrypted_plain_auth")
 
 local log = module._log;
@@ -28,14 +26,6 @@ local xmlns_sasl ='urn:ietf:params:xml:ns:xmpp-sasl';
 local xmlns_bind ='urn:ietf:params:xml:ns:xmpp-bind';
 local xmlns_stanzas ='urn:ietf:params:xml:ns:xmpp-stanzas';
 
-local new_sasl = require "util.sasl".new;
-
-local anonymous_authentication_profile = {
-	anonymous = function(sasl, username, realm)
-		return true; -- for normal usage you should always return true here
-	end
-};
-
 local function build_reply(status, ret, err_msg)
 	local reply = st.stanza(status, {xmlns = xmlns_sasl});
 	if status == "challenge" then
@@ -99,22 +89,9 @@ module:hook("stanza/urn:ietf:params:xml:ns:xmpp-sasl:auth", function(event)
 		session.sasl_handler = nil; -- allow starting a new SASL negotiation before completing an old one
 	end
 	if not session.sasl_handler then
-		if anonymous_login then
-			session.sasl_handler = new_sasl(module.host, anonymous_authentication_profile);
-		else
-			session.sasl_handler = usermanager_get_sasl_handler(module.host);
-		end
+		session.sasl_handler = usermanager_get_sasl_handler(module.host);
 	end
 	local mechanism = stanza.attr.mechanism;
-	if anonymous_login then
-		if mechanism ~= "ANONYMOUS" then
-			session.send(build_reply("failure", "invalid-mechanism"));
-			return true;
-		end
-	elseif mechanism == "ANONYMOUS" then
-		session.send(build_reply("failure", "mechanism-too-weak"));
-		return true;
-	end
 	if not session.secure and (secure_auth_only or (mechanism == "PLAIN" and not allow_unencrypted_plain_auth)) then
 		session.send(build_reply("failure", "encryption-required"));
 		return true;
@@ -150,11 +127,7 @@ module:hook("stream-features", function(event)
 		if secure_auth_only and not origin.secure then
 			return;
 		end
-		if anonymous_login then
-			origin.sasl_handler = new_sasl(module.host, anonymous_authentication_profile);
-		else
-			origin.sasl_handler = usermanager_get_sasl_handler(module.host);
-		end
+		origin.sasl_handler = usermanager_get_sasl_handler(module.host);
 		features:tag("mechanisms", mechanisms_attr);
 		for mechanism in pairs(origin.sasl_handler:mechanisms()) do
 			if mechanism ~= "PLAIN" or origin.secure or allow_unencrypted_plain_auth then
-- 
cgit v1.2.3


From a2b49b64ae934a578130dff7efbb48a1a8627048 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Tue, 28 Dec 2010 09:58:40 +0500
Subject: hostmanager: Don't set host.disallow_s2s when anonymous_login=true
 (mod_auth_anonymous does this now).

---
 core/hostmanager.lua | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/core/hostmanager.lua b/core/hostmanager.lua
index 251ae3a2..9e74cd6b 100644
--- a/core/hostmanager.lua
+++ b/core/hostmanager.lua
@@ -67,9 +67,6 @@ function activate(host, host_config)
 	if not host_config.core.component_module then -- host
 		host_session.type = "local";
 		host_session.sessions = {};
-		if configmanager.get(host, "core", "anonymous_login") then
-			host_session.disallow_s2s = (configmanager.get(host, "core", "disallow_s2s") ~= false);
-		end
 	else -- component
 		host_session.type = "component";
 	end
-- 
cgit v1.2.3


From 86cea8a5d8797089558309b92ffeeb34ff0ad08b Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Tue, 28 Dec 2010 09:59:27 +0500
Subject: prosody: Don't add a datamanager callback when anonymous_login=true
 (mod_auth_anonymous does this now).

---
 prosody | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/prosody b/prosody
index 07ec2bdb..7c819214 100755
--- a/prosody
+++ b/prosody
@@ -334,12 +334,6 @@ end
 function init_data_store()
 	local data_path = config.get("*", "core", "data_path") or CFG_DATADIR or "data";
 	require "util.datamanager".set_data_path(data_path);
-	require "util.datamanager".add_callback(function(username, host, datastore, data)
-		if config.get(host, "core", "anonymous_login") then
-			return false;
-		end
-		return username, host, datastore, data;
-	end);
 	require "core.storagemanager";
 end
 
-- 
cgit v1.2.3


From d057082fc6a397348da8bacfcec1af37e931af70 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 29 Dec 2010 18:45:31 +0500
Subject: util.sasl: Cache the calculated mechanisms set for SASL profiles
 (profile.mechanisms table).

---
 util/sasl.lua | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/util/sasl.lua b/util/sasl.lua
index 93b79a86..17d10b80 100644
--- a/util/sasl.lua
+++ b/util/sasl.lua
@@ -48,13 +48,17 @@ end
 
 -- create a new SASL object which can be used to authenticate clients
 function new(realm, profile)
-	local mechanisms = {};
-	for backend, f in pairs(profile) do
-		if backend_mechanism[backend] then
-			for _, mechanism in ipairs(backend_mechanism[backend]) do
-				mechanisms[mechanism] = true;
+	local mechanisms = profile.mechanisms;
+	if not mechanisms then
+		mechanisms = {};
+		for backend, f in pairs(profile) do
+			if backend_mechanism[backend] then
+				for _, mechanism in ipairs(backend_mechanism[backend]) do
+					mechanisms[mechanism] = true;
+				end
 			end
 		end
+		profile.mechanisms = mechanisms;
 	end
 	return setmetatable({ profile = profile, realm = realm, mechs = mechanisms }, method);
 end
-- 
cgit v1.2.3


From ee8892b9e5975b338fc77b938c35a3a271005836 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Mon, 3 Jan 2011 09:40:45 +0100
Subject: MUC: Fix a pair of missing :up()

---
 plugins/muc/muc.lib.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua
index f3e2dd52..7a069852 100644
--- a/plugins/muc/muc.lib.lua
+++ b/plugins/muc/muc.lib.lua
@@ -356,7 +356,7 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc
 					pr.attr.to = from;
 					pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
 						:tag("item", {affiliation=occupant.affiliation or "none", role='none'}):up()
-						:tag("status", {code='110'});
+						:tag("status", {code='110'}):up();
 					self:_route_stanza(pr);
 					if jid ~= new_jid then
 						pr = st.clone(occupant.sessions[new_jid])
@@ -454,7 +454,7 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc
 						if not is_merge then
 							self:broadcast_except_nick(pr, to);
 						end
-						pr:tag("status", {code='110'});
+						pr:tag("status", {code='110'}):up();
 						if self._data.whois == 'anyone' then
 							pr:tag("status", {code='100'}):up();
 						end
-- 
cgit v1.2.3


From 00524419cb1c35e6df4c16c6eec81cbabf6ccc96 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 16:37:57 +0000
Subject: net.adns: Log the DNS server that a query is sent to

---
 net/adns.lua | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/adns.lua b/net/adns.lua
index 2f7b6804..a3b07b09 100644
--- a/net/adns.lua
+++ b/net/adns.lua
@@ -78,7 +78,10 @@ function new_async_socket(sock, resolver)
 	handler.setpeername = function (_, ...) peername = (...); local ret = sock:setpeername(...); _:set_send(dummy_send); return ret; end
 	handler.connect = function (_, ...) return sock:connect(...) end
 	--handler.send = function (_, data) _:write(data);  return _.sendbuffer and _.sendbuffer(); end
-	handler.send = function (_, data) return sock:send(data); end
+	handler.send = function (_, data)
+		log("debug", "Sending DNS query to %s", sock:getpeername());
+		return sock:send(data);
+	end
 	return handler;
 end
 
-- 
cgit v1.2.3


From 73752efbfdb1411bd6137cca65baeb35ed0eb08d Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 17:10:56 +0000
Subject: usermanager: Change dummy provider method to return an error string
 also (method not implemented)

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

diff --git a/core/usermanager.lua b/core/usermanager.lua
index 2e64af8c..2b060cc0 100644
--- a/core/usermanager.lua
+++ b/core/usermanager.lua
@@ -24,9 +24,11 @@ local default_provider = "internal_plain";
 module "usermanager"
 
 function new_null_provider()
-	local function dummy() end;
+	local function dummy() return nil, "method not implemented"; end;
 	local function dummy_get_sasl_handler() return sasl_new(nil, {}); end
-	return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, { __index = function() return dummy; end });
+	return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, {
+		__index = function(self, method) return dummy; end
+	});
 end
 
 function initialize_host(host)
-- 
cgit v1.2.3


From f31871eb2e61b2ecc0555b4265d24e4bcd9d8f49 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 17:11:37 +0000
Subject: usermanager: Have methods not implemented in the active provider fall
 back to the null provider (later we can add support for chains of providers)

---
 core/usermanager.lua | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/core/usermanager.lua b/core/usermanager.lua
index 2b060cc0..d4a00244 100644
--- a/core/usermanager.lua
+++ b/core/usermanager.lua
@@ -31,6 +31,8 @@ function new_null_provider()
 	});
 end
 
+local provider_mt = { __index = new_null_provider() };
+
 function initialize_host(host)
 	local host_session = hosts[host];
 	if host_session.type ~= "local" then return; end
@@ -40,7 +42,7 @@ function initialize_host(host)
 		local auth_provider = config.get(host, "core", "authentication") or default_provider;
 		if config.get(host, "core", "anonymous_login") then auth_provider = "anonymous"; end -- COMPAT 0.7
 		if provider.name == auth_provider then
-			host_session.users = provider;
+			host_session.users = setmetatable(provider, provider_mt);
 		end
 		if host_session.users ~= nil and host_session.users.name ~= nil then
 			log("debug", "host '%s' now set to use user provider '%s'", host, host_session.users.name);
-- 
cgit v1.2.3


From c8f795214ca472ba66fb5efdf262f15083274c1f Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 17:11:51 +0000
Subject: usermanager: Add delete_user method

---
 core/usermanager.lua | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/core/usermanager.lua b/core/usermanager.lua
index d4a00244..5e2e41fc 100644
--- a/core/usermanager.lua
+++ b/core/usermanager.lua
@@ -83,6 +83,10 @@ function create_user(username, password, host)
 	return hosts[host].users.create_user(username, password);
 end
 
+function delete_user(username, host)
+	return hosts[host].users.delete_user(username);
+end
+
 function get_sasl_handler(host)
 	return hosts[host].users.get_sasl_handler();
 end
-- 
cgit v1.2.3


From 90562d1b6e7db93c5e2379959416809d98c89d4a Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 17:12:28 +0000
Subject: mod_auth_internal_*: Support for delete_user method

---
 plugins/mod_auth_internal_hashed.lua | 4 ++++
 plugins/mod_auth_internal_plain.lua  | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/plugins/mod_auth_internal_hashed.lua b/plugins/mod_auth_internal_hashed.lua
index ec8da9ab..3ce8c076 100644
--- a/plugins/mod_auth_internal_hashed.lua
+++ b/plugins/mod_auth_internal_hashed.lua
@@ -135,6 +135,10 @@ function new_hashpass_provider(host)
 		return datamanager.store(username, host, "accounts", {stored_key = stored_key_hex, server_key = server_key_hex, salt = salt, iteration_count = iteration_count});
 	end
 
+	function provider.delete_user(username)
+		return datamanager.store(username, host, "accounts", nil);
+	end
+
 	function provider.get_sasl_handler()
 		local realm = module:get_option("sasl_realm") or module.host;
 		local testpass_authentication_profile = {
diff --git a/plugins/mod_auth_internal_plain.lua b/plugins/mod_auth_internal_plain.lua
index 3721781b..ccaf8381 100644
--- a/plugins/mod_auth_internal_plain.lua
+++ b/plugins/mod_auth_internal_plain.lua
@@ -62,6 +62,10 @@ function new_default_provider(host)
 	function provider.create_user(username, password)
 		return datamanager.store(username, host, "accounts", {password = password});
 	end
+	
+	function provider.delete_user(username)
+		return datamanager.store(username, host, "accounts", nil);
+	end
 
 	function provider.get_sasl_handler()
 		local realm = module:get_option("sasl_realm") or module.host;
-- 
cgit v1.2.3


From 07a2dfbb1ea35dbb6f4c857b8a84406e09dc2432 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 17:15:47 +0000
Subject: mod_register: Add registration_compat config option to allow account
 remove requests addressed to='host' (defaults to true)

---
 plugins/mod_register.lua | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua
index 1df73297..abbb7c94 100644
--- a/plugins/mod_register.lua
+++ b/plugins/mod_register.lua
@@ -15,10 +15,13 @@ local usermanager_create_user = require "core.usermanager".create_user;
 local usermanager_set_password = require "core.usermanager".set_password;
 local os_time = os.time;
 local nodeprep = require "util.encodings".stringprep.nodeprep;
+local jid_bare = require "util.jid".bare;
+
+local compat = module:get_option_boolean("registration_compat", true);
 
 module:add_feature("jabber:iq:register");
 
-module:hook("iq/self/jabber:iq:register:query", function(event)
+local function handle_registration_stanza(event)
 	local session, stanza = event.origin, event.stanza;
 
 	local query = stanza.tags[1];
@@ -86,7 +89,17 @@ module:hook("iq/self/jabber:iq:register:query", function(event)
 		end
 	end
 	return true;
-end);
+end
+
+module:hook("iq/self/jabber:iq:register:query", handle_registration_stanza);
+if compat then
+	module:hook("iq/host/jabber:iq:register:query", function (event)
+		local session, stanza = event.origin, event.stanza;
+		if session.type == "c2s" and jid_bare(stanza.attr.to) == session.host then
+			return handle_registration_stanza(event);
+		end
+	end);
+end
 
 local recent_ips = {};
 local min_seconds_between_registrations = module:get_option("min_seconds_between_registrations");
-- 
cgit v1.2.3


From 55c8f50819e15b8a48194511c121420687a3942c Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 17:19:39 +0000
Subject: mod_register: Change to use new delete_user auth provider method

---
 plugins/mod_register.lua | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua
index abbb7c94..7373adad 100644
--- a/plugins/mod_register.lua
+++ b/plugins/mod_register.lua
@@ -13,6 +13,7 @@ local datamanager = require "util.datamanager";
 local usermanager_user_exists = require "core.usermanager".user_exists;
 local usermanager_create_user = require "core.usermanager".create_user;
 local usermanager_set_password = require "core.usermanager".set_password;
+local usermanager_delete_user = require "core.usermanager".delete_user;
 local os_time = os.time;
 local nodeprep = require "util.encodings".stringprep.nodeprep;
 local jid_bare = require "util.jid".bare;
@@ -36,11 +37,15 @@ local function handle_registration_stanza(event)
 		if query.tags[1] and query.tags[1].name == "remove" then
 			-- TODO delete user auth data, send iq response, kick all user resources with a <not-authorized/>, delete all user data
 			local username, host = session.username, session.host;
-			--session.send(st.error_reply(stanza, "cancel", "not-allowed"));
-			--return;
-			usermanager_set_password(username, nil, host); -- Disable account
-			-- FIXME the disabling currently allows a different user to recreate the account
-			-- we should add an in-memory account block mode when we have threading
+			
+			local ok, err = usermanager_delete_user(username, host);
+			
+			if not ok then
+				module:log("debug", "Removing user account %s@%s failed: %s", username, host, err);
+				session.send(st.error_reply(stanza, "cancel", "service-unavailable", err));
+				return true;
+			end
+			
 			session.send(st.reply(stanza));
 			local roster = session.roster;
 			for _, session in pairs(hosts[host].sessions[username].sessions) do -- disconnect all resources
@@ -63,7 +68,6 @@ local function handle_registration_stanza(event)
 			end
 			datamanager.store(username, host, "roster", nil);
 			datamanager.store(username, host, "privacy", nil);
-			datamanager.store(username, host, "accounts", nil); -- delete accounts datastore at the end
 			module:log("info", "User removed their account: %s@%s", username, host);
 			module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session });
 		else
@@ -180,4 +184,3 @@ module:hook("stanza/iq/jabber:iq:register:query", function(event)
 	end
 	return true;
 end);
-
-- 
cgit v1.2.3


From 18e42c9e081d3405b90abea5176b803da9d6077b Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 17:21:58 +0000
Subject: mod_register: Small code cleanup

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

diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua
index 7373adad..25c09dfa 100644
--- a/plugins/mod_register.lua
+++ b/plugins/mod_register.lua
@@ -71,12 +71,9 @@ local function handle_registration_stanza(event)
 			module:log("info", "User removed their account: %s@%s", username, host);
 			module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session });
 		else
-			local username = query:child_with_name("username");
-			local password = query:child_with_name("password");
+			local username = nodeprep(query:get_child("username"):get_text());
+			local password = query:get_child("password"):get_text();
 			if username and password then
-				-- FIXME shouldn't use table.concat
-				username = nodeprep(table.concat(username));
-				password = table.concat(password);
 				if username == session.username then
 					if usermanager_set_password(username, password, session.host) then
 						session.send(st.reply(stanza));
-- 
cgit v1.2.3


From 99ec1ccf1ecd17d55d1298906e94b50a2ac56034 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 21:18:35 +0000
Subject: prosody, prosodyctl: Create prosody object as a local before
 exporting as a global

---
 prosody    | 4 ++--
 prosodyctl | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/prosody b/prosody
index 7c819214..b093e4fd 100755
--- a/prosody
+++ b/prosody
@@ -32,8 +32,8 @@ if CFG_DATADIR then
 end
 
 -- Global 'prosody' object
-prosody = { events = require "util.events".new(); };
-local prosody = prosody;
+local prosody = { events = require "util.events".new(); };
+_G.prosody = prosody;
 
 -- Check dependencies
 local dependencies = require "util.dependencies";
diff --git a/prosodyctl b/prosodyctl
index 9630a9b8..dae9268a 100755
--- a/prosodyctl
+++ b/prosodyctl
@@ -32,14 +32,14 @@ if CFG_DATADIR then
 end
 
 -- Global 'prosody' object
-prosody = {
+local prosody = {
 	hosts = {};
 	events = require "util.events".new();
 	platform = "posix";
 	lock_globals = function () end;
 	unlock_globals = function () end;
 };
-local prosody = prosody;
+_G.prosody = prosody;
 
 local dependencies = require "util.dependencies";
 if not dependencies.check_dependencies() then
-- 
cgit v1.2.3


From e29ff95c8fb4573afe73894b6397f21a5bc42a99 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 21:19:28 +0000
Subject: prosody, prosodyctl: Filter out relative paths from package.(c)path
 when installed

---
 prosody    | 16 ++++++++++++++--
 prosodyctl | 16 ++++++++++++++--
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/prosody b/prosody
index b093e4fd..42c3acad 100755
--- a/prosody
+++ b/prosody
@@ -18,10 +18,22 @@ CFG_DATADIR=os.getenv("PROSODY_DATADIR");
 
 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 
+local function is_relative(path)
+	local path_sep = package.config:sub(1,1);
+        return ((path_sep == "/" and path:sub(1,1) ~= "/")
+	or (path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\")))
+end
+
 -- Tell Lua where to find our libraries
 if CFG_SOURCEDIR then
-	package.path = CFG_SOURCEDIR.."/?.lua;"..package.path;
-	package.cpath = CFG_SOURCEDIR.."/?.so;"..package.cpath;
+	local function filter_relative_paths(path)
+		if is_relative(path) then return ""; end
+	end
+	local function sanitise_paths(paths)
+		return (paths:gsub("[^;]+;?", filter_relative_paths):gsub(";;+", ";"));
+	end
+	package.path = sanitise_paths(CFG_SOURCEDIR.."/?.lua;"..package.path);
+	package.cpath = sanitise_paths(CFG_SOURCEDIR.."/?.so;"..package.cpath);
 end
 
 -- Substitute ~ with path to home directory in data path
diff --git a/prosodyctl b/prosodyctl
index dae9268a..18f430c5 100755
--- a/prosodyctl
+++ b/prosodyctl
@@ -18,10 +18,22 @@ CFG_DATADIR=os.getenv("PROSODY_DATADIR");
 
 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 
+local function is_relative(path)
+	local path_sep = package.config:sub(1,1);
+        return ((path_sep == "/" and path:sub(1,1) ~= "/")
+	or (path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\")))
+end
+
 -- Tell Lua where to find our libraries
 if CFG_SOURCEDIR then
-	package.path = CFG_SOURCEDIR.."/?.lua;"..package.path;
-	package.cpath = CFG_SOURCEDIR.."/?.so;"..package.cpath;
+	local function filter_relative_paths(path)
+		if is_relative(path) then return ""; end
+	end
+	local function sanitise_paths(paths)
+		return (paths:gsub("[^;]+;?", filter_relative_paths):gsub(";;+", ";"));
+	end
+	package.path = sanitise_paths(CFG_SOURCEDIR.."/?.lua;"..package.path);
+	package.cpath = sanitise_paths(CFG_SOURCEDIR.."/?.so;"..package.cpath);
 end
 
 -- Substitute ~ with path to home directory in data path
-- 
cgit v1.2.3


From 7745bdd7d6ca7871cb2fd3017500843c1d0b49ac Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Tue, 4 Jan 2011 21:38:14 +0000
Subject: mod_bosh: Fix for miscalculating inactivity, causing disconnects
 under a steady stream of traffic

---
 plugins/mod_bosh.lua | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua
index 58254169..b9152c9f 100644
--- a/plugins/mod_bosh.lua
+++ b/plugins/mod_bosh.lua
@@ -125,6 +125,12 @@ function handle_request(method, body, request)
 	
 	local session = sessions[request.sid];
 	if session then
+               -- Session was marked as inactive, since we have
+               -- a request open now, unmark it
+               if inactive_sessions[session] then
+                       inactive_sessions[session] = nil;
+               end
+
 		local r = session.requests;
 		log("debug", "Session %s has %d out of %d requests open", request.sid, #r, session.bosh_hold);
 		log("debug", "and there are %d things in the send_buffer", #session.send_buffer);
@@ -154,11 +160,6 @@ function handle_request(method, body, request)
 				request.reply_before = os_time() + session.bosh_wait;
 				waiting_requests[request] = true;
 			end
-			if inactive_sessions[session] then
-				-- Session was marked as inactive, since we have
-				-- a request open now, unmark it
-				inactive_sessions[session] = nil;
-			end
 		end
 		
 		return true; -- Inform httpserver we shall reply later
-- 
cgit v1.2.3


From b4faeea3ecf8004997da797453f1318daecf171f Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 5 Jan 2011 06:16:07 +0500
Subject: configmanager: Added rawget().

---
 core/configmanager.lua | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/core/configmanager.lua b/core/configmanager.lua
index b703bb8c..4cc3ef46 100644
--- a/core/configmanager.lua
+++ b/core/configmanager.lua
@@ -47,6 +47,15 @@ function get(host, section, key)
 	end
 	return nil;
 end
+function _M.rawget(host, section, key)
+	local hostconfig = rawget(config, host);
+	if hostconfig then
+		local sectionconfig = rawget(hostconfig, section);
+		if sectionconfig then
+			return rawget(sectionconfig, key);
+		end
+	end
+end
 
 local function set(config, host, section, key, value)
 	if host and section and key then
-- 
cgit v1.2.3


From 1e5dc701c82e6c19c58cf337647ac8dd5136c443 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 5 Jan 2011 06:16:27 +0500
Subject: modulemanager: Removed an unused variable.

---
 core/modulemanager.lua | 2 --
 1 file changed, 2 deletions(-)

diff --git a/core/modulemanager.lua b/core/modulemanager.lua
index 0af9a271..211b49b6 100644
--- a/core/modulemanager.lua
+++ b/core/modulemanager.lua
@@ -6,8 +6,6 @@
 -- COPYING file in the source package for more information.
 --
 
-local plugin_dir = CFG_PLUGINDIR or "./plugins/";
-
 local logger = require "util.logger";
 local log = logger.init("modulemanager");
 local config = require "core.configmanager";
-- 
cgit v1.2.3


From 3546ee5491d11577dd8e50051839385a30513933 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 5 Jan 2011 06:23:17 +0500
Subject: net.httpserver: Decode percent-encoded characters in URL path.

---
 net/httpserver.lua | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/httpserver.lua b/net/httpserver.lua
index 4c1200ac..4be62ced 100644
--- a/net/httpserver.lua
+++ b/net/httpserver.lua
@@ -119,6 +119,7 @@ local function request_reader(request, data, startpos)
 		local function success_cb(r)
 			for k,v in pairs(r) do request[k] = v; end
 			request.url = url_parse(request.path);
+			request.url.path = request.url.path and request.url.path:gsub("%%(%x%x)", function(x) return x.char(tonumber(x, 16)) end);
 			request.body = { request.body };
 			call_callback(request);
 		end
-- 
cgit v1.2.3


From 5e1f81a522812ebef0622a20b54a1add2c647cba Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 5 Jan 2011 06:23:58 +0500
Subject: mod_storage_sql: Removed unnecessary initialization of a variable.

---
 plugins/mod_storage_sql.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index 53f1ea0a..43967f47 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -27,7 +27,7 @@ local next = next;
 local setmetatable = setmetatable;
 local json = require "util.json";
 
-local connection = ...;
+local connection;
 local host,user,store = module.host;
 local params = module:get_option("sql");
 
-- 
cgit v1.2.3


From 1850c45665c6b5d4ccf4fd5138922db386a190e9 Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 5 Jan 2011 06:26:49 +0500
Subject: net.httpserver: Changed an unnecessary global access.

---
 net/httpserver.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/httpserver.lua b/net/httpserver.lua
index 4be62ced..6fd9b65e 100644
--- a/net/httpserver.lua
+++ b/net/httpserver.lua
@@ -20,7 +20,7 @@ local t_insert, t_concat = table.insert, table.concat;
 local s_match, s_gmatch = string.match, string.gmatch;
 local tonumber, tostring, pairs, ipairs, type = tonumber, tostring, pairs, ipairs, type;
 
-local urlencode = function (s) return s and (s:gsub("%W", function (c) return string.format("%%%02x", c:byte()); end)); end
+local urlencode = function (s) return s and (s:gsub("%W", function (c) return ("%%%02x"):format(c:byte()); end)); end
 
 local log = require "util.logger".init("httpserver");
 
-- 
cgit v1.2.3


From f3386d7519a96f68e79436a03a6c7c6a81cb758e Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 5 Jan 2011 06:34:23 +0500
Subject: net.httpserver: Removed unused import and variables.

---
 net/httpserver.lua | 2 --
 1 file changed, 2 deletions(-)

diff --git a/net/httpserver.lua b/net/httpserver.lua
index 6fd9b65e..d401f47c 100644
--- a/net/httpserver.lua
+++ b/net/httpserver.lua
@@ -7,7 +7,6 @@
 --
 
 
-local socket = require "socket"
 local server = require "net.server"
 local url_parse = require "socket.url".parse;
 local httpstream_new = require "util.httpstream".new;
@@ -17,7 +16,6 @@ local connlisteners_get = require "net.connlisteners".get;
 local listener;
 
 local t_insert, t_concat = table.insert, table.concat;
-local s_match, s_gmatch = string.match, string.gmatch;
 local tonumber, tostring, pairs, ipairs, type = tonumber, tostring, pairs, ipairs, type;
 
 local urlencode = function (s) return s and (s:gsub("%W", function (c) return ("%%%02x"):format(c:byte()); end)); end
-- 
cgit v1.2.3


From 19e5efd0caa093ae89dc81f1a5da5302767c539f Mon Sep 17 00:00:00 2001
From: Waqas Hussain <waqas20@gmail.com>
Date: Wed, 5 Jan 2011 06:56:36 +0500
Subject: mod_storage_sql: Catch Lua errors during SQL transactions, and
 rollback.

---
 plugins/mod_storage_sql.lua | 43 ++++++++++++++++++++++++++++++-------------
 1 file changed, 30 insertions(+), 13 deletions(-)

diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua
index 43967f47..3afbab1c 100644
--- a/plugins/mod_storage_sql.lua
+++ b/plugins/mod_storage_sql.lua
@@ -25,6 +25,7 @@ local tonumber = tonumber;
 local pairs = pairs;
 local next = next;
 local setmetatable = setmetatable;
+local xpcall = xpcall;
 local json = require "util.json";
 
 local connection;
@@ -115,10 +116,7 @@ local function commit(...)
 	return ...;
 end
 
-local keyval_store = {};
-keyval_store.__index = keyval_store;
-function keyval_store:get(username)
-	user,store = username,self.store;
+local function keyval_store_get()
 	local stmt, err = getsql("SELECT * FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=?");
 	if not stmt then return nil, err; end
 	
@@ -138,9 +136,7 @@ function keyval_store:get(username)
 	end
 	return commit(haveany and result or nil);
 end
-function keyval_store:set(username, data)
-	user,store = username,self.store;
-	-- start transaction
+local function keyval_store_set(data)
 	local affected, err = setsql("DELETE FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=?");
 	
 	if data and next(data) ~= nil then
@@ -165,10 +161,20 @@ function keyval_store:set(username, data)
 	return commit(true);
 end
 
-local map_store = {};
-map_store.__index = map_store;
-function map_store:get(username, key)
+local keyval_store = {};
+keyval_store.__index = keyval_store;
+function keyval_store:get(username)
+	user,store = username,self.store;
+	local success, ret, err = xpcall(keyval_store_get, debug.traceback);
+	if success then return ret, err; else return rollback(nil, ret); end
+end
+function keyval_store:set(username, data)
 	user,store = username,self.store;
+	local success, ret, err = xpcall(function() return keyval_store_set(data); end, debug.traceback);
+	if success then return ret, err; else return rollback(nil, ret); end
+end
+
+local function map_store_get(key)
 	local stmt, err = getsql("SELECT * FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", key or "");
 	if not stmt then return nil, err; end
 	
@@ -188,9 +194,7 @@ function map_store:get(username, key)
 	end
 	return commit(haveany and result[key] or nil);
 end
-function map_store:set(username, key, data)
-	user,store = username,self.store;
-	-- start transaction
+local function map_store_set(key, data)
 	local affected, err = setsql("DELETE FROM `Prosody` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", key or "");
 	
 	if data and next(data) ~= nil then
@@ -206,6 +210,19 @@ function map_store:set(username, key, data)
 	return commit(true);
 end
 
+local map_store = {};
+map_store.__index = map_store;
+function map_store:get(username, key)
+	user,store = username,self.store;
+	local success, ret, err = xpcall(function() return map_store_get(key); end, debug.traceback);
+	if success then return ret, err; else return rollback(nil, ret); end
+end
+function map_store:set(username, key, data)
+	user,store = username,self.store;
+	local success, ret, err = xpcall(function() return map_store_set(key, data); end, debug.traceback);
+	if success then return ret, err; else return rollback(nil, ret); end
+end
+
 local list_store = {};
 list_store.__index = list_store;
 function list_store:scan(username, from, to, jid, typ)
-- 
cgit v1.2.3


From 8bb1169606e0b30f820adf68d93027037015211d Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Thu, 6 Jan 2011 13:47:20 +0000
Subject: net.server_event: Log interface and port number when binding fails

---
 net/server_event.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/server_event.lua b/net/server_event.lua
index 122d80fc..058d51fe 100644
--- a/net/server_event.lua
+++ b/net/server_event.lua
@@ -726,7 +726,7 @@ local addserver = ( function( )
 		--vdebug( "creating new tcp server with following parameters:", addr or "nil", port or "nil", sslcfg or "nil", startssl or "nil")
 		local server, err = socket.bind( addr, port, cfg.ACCEPT_QUEUE )  -- create server socket
 		if not server then
-			debug( "creating server socket failed because:", err )
+			debug( "creating server socket on "..addr.." port "..port.." failed:", err )
 			return nil, err
 		end
 		local sslctx
-- 
cgit v1.2.3


From 43db72be07987925dce775f19bf944cdea30126d Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Thu, 6 Jan 2011 13:54:37 +0000
Subject: storagemanager: Log host in message when loading storage provider
 fails

---
 core/storagemanager.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/storagemanager.lua b/core/storagemanager.lua
index 43409960..49987112 100644
--- a/core/storagemanager.lua
+++ b/core/storagemanager.lua
@@ -48,7 +48,7 @@ local function load_driver(host, driver_name)
 	if driver_name ~= "internal" then
 		local ok, err = modulemanager.load(host, "storage_"..driver_name);
 		if not ok then
-			log("error", "Failed to load storage driver plugin %s: %s", driver_name, err);
+			log("error", "Failed to load storage driver plugin %s on %s: %s", driver_name, host, err);
 		end
 		return stores_available:get(host, driver_name);
 	else
-- 
cgit v1.2.3


From 267fa68a568821de651999d666e43e1933bd21a5 Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Thu, 6 Jan 2011 13:56:39 +0000
Subject: storagemanager: Add new "null" provider to get used when loading a
 driver or opening a store fails, instead of falling back to the default
 driver

---
 core/storagemanager.lua | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/core/storagemanager.lua b/core/storagemanager.lua
index 49987112..9f97e565 100644
--- a/core/storagemanager.lua
+++ b/core/storagemanager.lua
@@ -15,6 +15,19 @@ local prosody = prosody;
 
 module("storagemanager")
 
+local null_storage_method = function () return false, "no data storage active"; end
+local null_storage_driver = setmetatable(
+	{
+		name = "null",
+		open = function (self) return self; end
+	}, {
+		__index = function (self, method)
+			return null_storage_method;
+		end
+	}
+);
+
+--TODO: Move default driver to mod_auth_internal
 local default_driver_mt = { name = "internal" };
 default_driver_mt.__index = default_driver_mt;
 function default_driver_mt:open(store)
@@ -73,10 +86,13 @@ function open(host, store, typ)
 		if not driver then
 			if driver_name or (type(storage) == "string"
 			or type(storage) == "table" and storage[store]) then
-				log("warn", "Falling back to default driver for %s storage on %s", store, host);
+				log("warn", "Falling back to null driver for %s storage on %s", store, host);
+				driver_name = "null";
+				driver = null_storage_driver;
+			else
+				driver_name = "internal";
+				driver = load_driver(host, driver_name);
 			end
-			driver_name = "internal";
-			driver = load_driver(host, driver_name);
 		end
 	end
 	
@@ -85,7 +101,7 @@ function open(host, store, typ)
 		if err == "unsupported-store" then
 			log("debug", "Storage driver %s does not support store %s (%s), falling back to internal driver",
 				driver_name, store, typ);
-			ret = setmetatable({ host = host, store = store }, default_driver_mt); -- default to default driver
+			ret = null_storage_driver;
 			err = nil;
 		end
 	end
-- 
cgit v1.2.3


From cac05ef600cb92726706c193a53a51ad116e837a Mon Sep 17 00:00:00 2001
From: Matthew Wild <mwild1@gmail.com>
Date: Thu, 6 Jan 2011 14:01:57 +0000
Subject: storagemanager: Fix log message (s/internal/null/)

---
 core/storagemanager.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/storagemanager.lua b/core/storagemanager.lua
index 9f97e565..35fef503 100644
--- a/core/storagemanager.lua
+++ b/core/storagemanager.lua
@@ -99,7 +99,7 @@ function open(host, store, typ)
 	local ret, err = driver:open(store, typ);
 	if not ret then
 		if err == "unsupported-store" then
-			log("debug", "Storage driver %s does not support store %s (%s), falling back to internal driver",
+			log("debug", "Storage driver %s does not support store %s (%s), falling back to null driver",
 				driver_name, store, typ);
 			ret = null_storage_driver;
 			err = nil;
-- 
cgit v1.2.3