Software /
code /
prosody-modules
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 |
parent | 2517:3990b1bca308 |
child | 2520: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 |