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).
--- 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