comparison mod_firewall/mod_firewall.lua @ 2518:0e1054c19f9d

mod_firewall: More meta! Allow simple functions to be applied to $<> expressions
author Matthew Wild <mwild1@gmail.com>
date Sun, 19 Feb 2017 21:06:57 +0000
parents 3990b1bca308
children c6fd8975704b
comparison
equal deleted inserted replaced
2517:3990b1bca308 2518:0e1054c19f9d
45 -- Returns the input if it is safe to be used as a variable name, otherwise nil 45 -- Returns the input if it is safe to be used as a variable name, otherwise nil
46 function idsafe(name) 46 function idsafe(name)
47 return name:match("^%a[%w_]*$") 47 return name:match("^%a[%w_]*$")
48 end 48 end
49 49
50 local meta_funcs = {
51 bare = function (code)
52 return "jid_bare("..code..")", {"jid_bare"};
53 end;
54 node = function (code)
55 return "(jid_split("..code.."))", {"jid_split"};
56 end;
57 host = function (code)
58 return "(select(2, jid_split("..code..")))", {"jid_split"};
59 end;
60 resource = function (code)
61 return "(select(3, jid_split("..code..")))", {"jid_split"};
62 end;
63 };
64
50 -- Run quoted (%q) strings through this to allow them to contain code. e.g.: LOG=Received: $(stanza:top_tag()) 65 -- Run quoted (%q) strings through this to allow them to contain code. e.g.: LOG=Received: $(stanza:top_tag())
51 function meta(s, extra) 66 function meta(s, deps, extra)
52 return (s:gsub("$(%b())", function (expr) 67 return (s:gsub("$(%b())", function (expr)
53 expr = expr:gsub("\\(.)", "%1"); 68 expr = expr:gsub("\\(.)", "%1");
54 return [["..tostring(]]..expr..[[).."]]; 69 return [["..tostring(]]..expr..[[).."]];
55 end) 70 end)
56 :gsub("$(%b<>)", function (expr) 71 :gsub("$(%b<>)", function (expr)
57 expr = expr:sub(2,-2); 72 expr = expr:sub(2,-2);
58 local default = expr:match("||([^|]+)$"); 73 local func_chain = expr:match("|[%w|]+$");
59 if default then 74 if func_chain then
60 expr = expr:sub(1, -(#default+2)); 75 expr = expr:sub(1, -1-#func_chain);
76 end
77 local code;
78 if expr:match("^@") then
79 -- Skip stanza:find() for simple attribute lookup
80 local attr_name = expr:sub(2);
81 if deps and (attr_name == "to" or attr_name == "from" or attr_name == "type") then
82 -- These attributes may be cached in locals
83 code = attr_name;
84 table.insert(deps, attr_name);
85 else
86 code = "stanza.attr["..("%q"):format(attr_name).."]";
87 end
61 else 88 else
62 default = "<undefined>"; 89 code = "(stanza:find("..("%q"):format(expr)..") or "..("%q"):format("<undefined>")..")";
63 end 90 end
64 if expr:match("^@") then 91 if func_chain then
65 return "\"..(stanza.attr["..("%q"):format(expr:sub(2)).."] or "..("%q"):format(default)..")..\""; 92 for func_name in func_chain:gmatch("|(%w+)") do
66 end 93 if code == "to" or code == "from" then
67 return "\"..(stanza:find("..("%q"):format(expr)..") or "..("%q"):format(default)..")..\""; 94 if func_name == "bare" then
95 code = "bare_"..code;
96 table.insert(deps, code);
97 elseif func_name == "node" or func_name == "host" or func_name == "resource" then
98 table.insert(deps, "split_"..code);
99 code = code.."_"..func_name;
100 end
101 else
102 assert(meta_funcs[func_name], "unknown function: "..func_name);
103 local new_code, new_deps = meta_funcs[func_name](code);
104 code = new_code;
105 if new_deps and #new_deps > 0 then
106 assert(deps, "function not supported here: "..func_name);
107 for _, dep in ipairs(new_deps) do
108 table.insert(deps, dep);
109 end
110 end
111 end
112 end
113 end
114 return "\"..(("..code..") or \"<undefined>\")..\"";
68 end) 115 end)
69 :gsub("$$(%a+)", extra or {}) 116 :gsub("$$(%a+)", extra or {})
70 :gsub([[^""%.%.]], "") 117 :gsub([[^""%.%.]], "")
71 :gsub([[%.%.""$]], "")); 118 :gsub([[%.%.""$]], ""));
72 end 119 end