changeset 965:d4e24fb289c0

mod_firewall: Improve zone handling, make it more efficient, and support dynamic dependencies in the compiler. ENTERING and LEAVING conditions now work at expected (not matching stanzas flowing within a zone).
author Matthew Wild <mwild1@gmail.com>
date Fri, 05 Apr 2013 19:21:46 +0100
parents 04e85eb3dfef
children a65df6e97d94
files mod_firewall/conditions.lib.lua mod_firewall/mod_firewall.lua
diffstat 2 files changed, 27 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/mod_firewall/conditions.lib.lua	Fri Apr 05 19:20:05 2013 +0100
+++ b/mod_firewall/conditions.lib.lua	Fri Apr 05 19:21:46 2013 +0100
@@ -61,21 +61,24 @@
 function condition_handlers.TYPE(type)
 	return compile_comparison_list("(type or (name == 'message' and 'chat') or (name == 'presence' and 'available'))", type), { "type", "name" };
 end
+
+local function zone_check(zone, which)
+	local which_not = which == "from" and "to" or "from";
+	return ("(zone_%s[%s_host] or zone_%s[%s] or zone_%s[bare_%s]) "
+		.."and not(zone_%s[%s_host] or zone_%s[%s] or zone_%s[%s])"
+		)
+		:format(zone, which, zone, which, zone, which,
+		zone, which_not, zone, which_not, zone, which_not), {
+			"split_to", "split_from", "bare_to", "bare_from", "zone:"..zone
+		};
 end
 
 function condition_handlers.ENTERING(zone)
-	return ("(zones[%q] and (zones[%q][to_host] or "
-		.."zones[%q][to] or "
-		.."zones[%q][bare_to]))"
-		)
-		:format(zone, zone, zone, zone), { "split_to", "bare_to" };
+	return zone_check(zone, "to");
 end
 
 function condition_handlers.LEAVING(zone)
-	return ("zones[%q] and (zones[%q][from_host] or "
-		.."(zones[%q][from] or "
-		.."zones[%q][bare_from]))")
-		:format(zone, zone, zone, zone), { "split_from", "bare_from" };
+	return zone_check(zone, "from");
 end
 
 function condition_handlers.PAYLOAD(payload_ns)
--- a/mod_firewall/mod_firewall.lua	Fri Apr 05 19:20:05 2013 +0100
+++ b/mod_firewall/mod_firewall.lua	Fri Apr 05 19:21:46 2013 +0100
@@ -72,9 +72,14 @@
 	};
 	is_admin = { global_code = [[local is_admin = require "core.usermanager".is_admin]]};
 	core_post_stanza = { global_code = [[local core_post_stanza = prosody.core_post_stanza]] };
+	zone = { global_code = function (zone)
+		assert(zone:match("^%a[%w_]*$"), "Invalid zone name: "..zone);
+		return ("local zone_%s = zones[%q] or {};"):format(zone, zone);
+	end };
 };
 
 local function include_dep(dep, code)
+	local dep, dep_param = dep:match("^([^:]+):?(.*)$");
 	local dep_info = available_deps[dep];
 	if not dep_info then
 		module:log("error", "Dependency not found: %s", dep);
@@ -91,10 +96,18 @@
 		include_dep(dep_dep, code);
 	end
 	if dep_info.global_code then
-		table.insert(code.global_header, dep_info.global_code);
+		if dep_param ~= "" then
+			table.insert(code.global_header, dep_info.global_code(dep_param));
+		else
+			table.insert(code.global_header, dep_info.global_code);
+		end
 	end
 	if dep_info.local_code then
-		table.insert(code, "\n\t-- "..dep.."\n\t"..dep_info.local_code.."\n\n\t");
+		if dep_param ~= "" then
+			table.insert(code, "\n\t-- "..dep.."\n\t"..dep_info.local_code(dep_param).."\n\n\t");
+		else
+			table.insert(code, "\n\t-- "..dep.."\n\t"..dep_info.local_code.."\n\n\t");
+		end
 	end
 	code.included_deps[dep] = true;
 end