Software /
code /
prosody-modules
Diff
mod_firewall/conditions.lib.lua @ 947:c91cac3b823f
mod_firewall: General stanza filtering plugin with a declarative rule-based syntax
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 03 Apr 2013 16:11:20 +0100 |
child | 954:bec5b6e2eab8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_firewall/conditions.lib.lua Wed Apr 03 16:11:20 2013 +0100 @@ -0,0 +1,94 @@ +local condition_handlers = {}; + +local jid = require "util.jid"; + +-- Return a code string for a condition that checks whether the contents +-- of variable with the name 'name' matches any of the values in the +-- comma/space/pipe delimited list 'values'. +local function compile_comparison_list(name, values) + local conditions = {}; + for value in values:gmatch("[^%s,|]+") do + table.insert(conditions, ("%s == %q"):format(name, value)); + end + return table.concat(conditions, " or "); +end + +function condition_handlers.KIND(kind) + return compile_comparison_list("name", kind), { "name" }; +end + +local wildcard_equivs = { ["*"] = ".*", ["?"] = "." }; + +local function compile_jid_match_part(part, match) + if not match then + return part.." == nil" + end + local pattern = match:match("<(.*)>"); + -- TODO: Support Lua pattern matching (main issue syntax... << >>?) + if pattern then + if pattern ~= "*" then + return ("%s:match(%q)"):format(part, pattern:gsub(".", wildcard_equivs)); + end + else + return ("%s == %q"):format(part, match); + end +end + +local function compile_jid_match(which, match_jid) + local match_node, match_host, match_resource = jid.split(match_jid); + local conditions = { + compile_jid_match_part(which.."_node", match_node); + compile_jid_match_part(which.."_host", match_host); + match_resource and compile_jid_match_part(which.."_resource", match_resource) or nil; + }; + return table.concat(conditions, " and "); +end + +function condition_handlers.TO(to) + return compile_jid_match("to", to), { "split_to" }; +end + +function condition_handlers.FROM(from) + return compile_jid_match("from", from), { "split_from" }; +end + +function condition_handlers.TYPE(type) + return compile_comparison_list("type", type), { "type" }; +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" }; +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" }; +end + +function condition_handlers.PAYLOAD(payload_ns) + return ("stanza:get_child(nil, %q)"):format(payload_ns); +end + +function condition_handlers.FROM_GROUP(group_name) + return ("group_contains(%q, bare_from)"):format(group_name), { "group_contains", "bare_from" }; +end + +function condition_handlers.TO_GROUP(group_name) + return ("group_contains(%q, bare_to)"):format(group_name), { "group_contains", "bare_to" }; +end + +function condition_handlers.FROM_ADMIN_OF(host) + return ("is_admin(bare_from, %s)"):format(host ~= "*" and host or nil), { "is_admin", "bare_from" }; +end + +function condition_handlers.TO_ADMIN_OF(host) + return ("is_admin(bare_to, %s)"):format(host ~= "*" and host or nil), { "is_admin", "bare_to" }; +end + +return condition_handlers;