Browse Source

[Project] Settings: Add expression aliases

tags/2.0
Vsevolod Stakhov 4 years ago
parent
commit
a2748a06d9
1 changed files with 58 additions and 27 deletions
  1. 58
    27
      src/plugins/lua/settings.lua

+ 58
- 27
src/plugins/lua/settings.lua View File

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

Loading…
Cancel
Save