commit a2748a0: [Project] Settings: Add expression aliases
Vsevolod Stakhov
vsevolod at highsecure.ru
Tue Jun 25 17:42:04 UTC 2019
Author: Vsevolod Stakhov
Date: 2019-06-25 18:37:09 +0100
URL: https://github.com/rspamd/rspamd/commit/a2748a06d9e4c50ac31e2c2669ef2cd8b882b662
[Project] Settings: Add expression aliases
---
src/plugins/lua/settings.lua | 85 ++++++++++++++++++++++++++++++--------------
1 file changed, 58 insertions(+), 27 deletions(-)
diff --git a/src/plugins/lua/settings.lua b/src/plugins/lua/settings.lua
index f269a4018..4b129db0f 100644
--- a/src/plugins/lua/settings.lua
+++ b/src/plugins/lua/settings.lua
@@ -261,7 +261,7 @@ local function check_settings(task)
if not input then return false end
if elt.check(input) then
- matched[#matched] = atom
+ matched[#matched + 1] = atom
return 1.0
end
else
@@ -302,8 +302,8 @@ local function check_settings(task)
for _,s in ipairs(settings[pri]) do
local matched = {}
- lua_util.debugm(N, task, "check for settings element %s; %s",
- s.name, s.rule.expression)
+ lua_util.debugm(N, task, "check for settings element %s",
+ s.name)
local result = check_specific_setting(s.rule, matched)
-- Can use xor here but more complicated for reading
if result then
@@ -702,6 +702,41 @@ local function process_settings_table(tbl, allow_ids, mempool)
}
end
+ local aliases = {}
+ -- This function is used to convert compound condition with
+ -- generic type and specific part (e.g. `header`, `Content-Transfer-Encoding`)
+ -- to a set of usable check elements:
+ -- `generic:specific` - most common part
+ -- `generic:<order>` - e.g. `header:1` for the first header
+ -- `generic:safe` - replace unsafe stuff with safe + lowercase
+ -- also aliases entry is set to avoid implicit expression
+ local function process_compound_condition(cond, generic, specific)
+ local full_key = generic .. ':' .. specific
+ checks[full_key] = cond
+
+ -- Try numeric key
+ for i=1,1000 do
+ local num_key = generic .. ':' .. tostring(i)
+ if not checks[num_key] then
+ checks[num_key] = cond
+ aliases[num_key] = true
+ break
+ end
+ end
+
+ local safe_key = generic .. ':' ..
+ specific:gsub('[:%-+&|><]', '_')
+ :gsub('%(', '[')
+ :gsub('%)', ']')
+ :lower()
+
+ if not checks[safe_key] then
+ checks[safe_key] = cond
+ aliases[safe_key] = true
+ end
+
+ return safe_key
+ end
-- Headers are tricky:
-- We create an closure with extraction function depending on header name
-- We also inserts it into `checks` table as an atom in form header:<hname>
@@ -714,30 +749,30 @@ local function process_settings_table(tbl, allow_ids, mempool)
if type(v) == 'string' then
local re = rspamd_regexp.create(v)
if re then
- checks[table_element .. ':'..k] = {
+ local cond = {
check = function(values)
return fun.any(function(c) return re:match(c) end, values)
end,
extract = extractor_func(k),
}
-
+ local skey = process_compound_condition(cond, table_element,
+ k)
lua_util.debugm(N, rspamd_config, 'added %s condition to "%s": %s =~ %s',
- table_element, name, k, v)
+ skey, name, k, v)
end
elseif type(v) == 'boolean' then
- checks[table_element .. ':'..k] = {
+ local cond = {
check = function(values)
- return fun.any(function(c)
- if c and v then return true end
- if not c or not v then return true end
- return false
- end, values)
+ if #values == 0 then return (not v) end
+ return v
end,
extract = extractor_func(k),
}
- lua_util.debugm(N, rspamd_config, 'added %s condition to "%s": %s =~ %s',
- table_element, name, k, v)
+ local skey = process_compound_condition(cond, table_element,
+ k)
+ lua_util.debugm(N, rspamd_config, 'added %s condition to "%s": %s == %s',
+ skey, name, k, v)
else
rspamd_logger.errx(rspamd_config, 'invalid %s %s = %s', table_element, k, v)
end
@@ -756,25 +791,18 @@ local function process_settings_table(tbl, allow_ids, mempool)
return function(task)
local rh = task:get_header_full(hname)
if rh then
- return fun.map(function(h) return h.decoded end, rh)
+ return fun.totable(fun.map(function(h) return h.decoded end, rh))
end
return {}
end
end)
if elt['selector'] then
- local sel = selectors_cache[name]
- if not sel then
- sel = lua_selectors.create_selector_closure(rspamd_config, elt.selector,
- elt.delimiter or "")
-
- if sel then
- selectors_cache[name] = sel
- end
- end
+ local sel = lua_selectors.create_selector_closure(rspamd_config, elt.selector,
+ elt.delimiter or "")
if sel then
- checks['selector:' .. name] = {
+ local cond = {
check = function(values)
return fun.any(function(c)
return c
@@ -782,8 +810,9 @@ local function process_settings_table(tbl, allow_ids, mempool)
end,
extract = sel,
}
+ local skey = process_compound_condition(cond, 'selector', elt.selector)
lua_util.debugm(N, rspamd_config, 'added selector condition to "%s": %s',
- name, sel)
+ name, skey)
end
end
@@ -808,8 +837,10 @@ local function process_settings_table(tbl, allow_ids, mempool)
local s = ' && '
-- By De Morgan laws
if inverse then s = ' || ' end
+ -- Exclude aliases and join all checks by key
local expr_str = table.concat(fun.totable(fun.map(function(k, _)
- return k end, checks)), s)
+ return k end,
+ fun.filter(function(k, _) return not aliases[k] end, checks))), s)
if inverse then
expr_str = string.format('!(%s)', expr_str)
More information about the Commits
mailing list