From 0d2d40e8829dc5ea9540644c3047c60805f989e0 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 18 Aug 2014 16:45:55 +0100 Subject: [PATCH] Start lua-settings implementation. --- src/plugins/lua/settings.lua | 209 +++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 src/plugins/lua/settings.lua diff --git a/src/plugins/lua/settings.lua b/src/plugins/lua/settings.lua new file mode 100644 index 000000000..bed01c4c9 --- /dev/null +++ b/src/plugins/lua/settings.lua @@ -0,0 +1,209 @@ +-- This plugin implements user dynamic settings +-- Settings documentation can be found here: +-- https://rspamd.com/doc/configuration/settings.html + +local set_section = rspamd_config:get_key("settings") +local settings = {} + +-- Functional utilities +local function filter(func, tbl) + local newtbl= {} + for i,v in pairs(tbl) do + if func(v) then + newtbl[i]=v + end + end + return newtbl +end + +-- Check limit for a task +local function check_settings(task) + +end + +-- Process settings based on their priority +local function process_settings_table(tbl) + local get_priority = function(elt) + local pri_tonum = function(p) + if p then + if type(p) == "number" then + return tonumber(p) + elseif type(p) == "string" then + if p == "high" then + return 3 + elseif p == "medium" then + return 2 + end + + end + + end + + return 1 + end + + return pri_tonum(elt['priority']) + end + + -- Check the setting element internal data + local process_setting_elt = function(elt) + -- Process IP address + local function process_ip(ip) + local out = {} + + if type(ip) == "table" then + for i,v in ipairs(ip) do + table.insert(out, process_ip(v)) + end + elseif type(ip) == "string" then + local slash = string.find(ip, '/') + + if not slash then + -- Just a plain IP address + local res = rspamd_ip.from_string(ip) + + if res:is_valid() then + table.insert(out, {res, 0}) + else + rspamd_logger.err("bad IP address: " .. ip) + return nil + end + else + local res = rspamd_ip.from_string(string.sub(ip, 1, slash)) + local mask = tonumber(string.sub(ip, slash + 1)) + + if res:is_valid() then + table.insert(out, {res, mask}) + else + rspamd_logger.err("bad IP address: " .. ip) + return nil + end + end + else + return nil + end + + return out + end + + local process_addr = function(addr) + local out = { + name = {}, + user = {}, + domain = {}, + regexp = {} + } + if type(addr) == "table" then + for i,v in ipairs(addr) do + table.insert(out, process_addr(v)) + end + elseif type(addr) == "string" then + if addr[1] == '/' then + -- It is a regexp + local re = rspamd_regexp.create(string.sub(addr, 2)) + if re then + out['regexp'] = re + setmetatable(out, { + __gc = function(t) t['regexp']:destroy() end + }) + else + rspamd_logger.err("bad regexp: " .. addr) + end + + elseif addr[1] == '@' then + -- It is a domain if form @domain + out['domain'] = string.sub(addr, 2) + else + -- Check user@domain parts + local at = string.find(addr, '@') + if at then + -- It is full address + out['name'] = addr + else + -- It is a user + out['user'] = addr + end + end + else + return nil + end + + return out + end + + + local out = { + ip = {}, + rcpt = {}, + from = {} + } + if elt['ip'] then + local ip = process_ip(elt['ip']) + + if ip then + table.insert(out['ip'], ip) + end + end + if elt['from'] then + local from = process_addr(elt['from']) + + if from then + table.insert(out['from'], from) + end + end + if elt['rcpt'] then + local rcpt = process_addr(elt['rcpt']) + + if rcpt then + table.insert(out['rcpt'], rcpt) + end + end + + return out + end + + -- filter trash in the input + local ft = filter( + function(elt) + if type(elt) == "table" then + return true + end + return false + end, tbl) + -- clear all settings + + for k,v in pairs(settings) do settings[k]=nil end + -- fill new settings by priority + for k,v in pairs(ft) do + local pri = get_priority(v) + if not settings[pri] then + settings[pri] = {} + end + local s = process_setting_elt(v) + if s then + settings[pri][k] = s + end + end +end + +-- Parse settings map from the ucl line +local function process_settings_map(string) + local ucl_parser = require "ucl.parser" + local res,err = ucl_parser:parse_string(string) + if not res then + rspamd_log.warn('cannot parse settings map: ' .. err) + else + process_settings_table(res) + end +end + +if type(set_section) == "string" then + -- Just a map of ucl + if rspamd_config:add_map(set_section, process_settings_map) then + rspamd_config:register_pre_filter(check_settings) + end +elseif type(set_section) == "table" then + if process_settings_table(set_section) then + rspamd_config:register_pre_filter(check_settings) + end +end \ No newline at end of file -- 2.39.5