From: Vsevolod Stakhov Date: Mon, 16 Feb 2015 17:40:49 +0000 (+0000) Subject: Start spamassasin rules reader plugin. X-Git-Tag: 0.9.0~688 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=77d6faa3917c58e9f50a2a929f9504989eb8b376;p=rspamd.git Start spamassasin rules reader plugin. --- diff --git a/src/plugins/lua/spamassassin.lua b/src/plugins/lua/spamassassin.lua new file mode 100644 index 000000000..d62675af4 --- /dev/null +++ b/src/plugins/lua/spamassassin.lua @@ -0,0 +1,129 @@ +--[[ +Copyright (c) 2015, Vsevolod Stakhov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +]]-- + +-- This plugin is intended to read and parse spamassassin rules with regexp +-- rules. SA plugins or statistics are not supported + +local rspamd_logger = require "rspamd_logger" +local rspamd_regexp = require "rspamd_regexp" +local _ = require "fun" +--local dumper = require 'pl.pretty'.dump +local rules = {} +local section = rspamd_config:get_key("spamassassin") + +local function split(str) + local result = {} + + for token in string.gmatch(str, "[^%s]+") do + table.insert(result, token) + end + + return result +end + +local function process_sa_conf(f) + local cur_rule = {} + local valid_rule = false + + local function insert_cur_rule() + -- We have previous rule valid + rules[cur_rule['symbol']] = cur_rule + cur_rule = {} + valid_rule = false + end + + local function words_to_re(words, start) + return table.concat(_.totable(_.drop_n(start, words)), " "); + end + + for l in f:lines() do + (function () + if string.len(l) == 0 or + _.nth(1, _.drop_while(function(c) return c == ' ' end, _.iter(l))) == '#' then + return + end + + local slash = string.find(l, '/') + + words = _.totable(_.filter(function(w) return w ~= "" end, _.iter(split(l)))) + if words[1] == "header" and slash then + -- header SYMBOL Header ~= /regexp/ + if valid_rule then + insert_cur_rule() + end + cur_rule['type'] = 'header' + cur_rule['symbol'] = words[2] + cur_rule['header'] = words[3] + cur_rule['re_expr'] = words_to_re(words, 4) + cur_rule['re'] = rspamd_regexp.create_cached(cur_rule['re_expr']) + if cur_rule['re'] then valid_rule = true end + elseif words[1] == "body" and slash then + -- body SYMBOL /regexp/ + if valid_rule then + insert_cur_rule() + end + cur_rule['type'] = 'part' + cur_rule['symbol'] = words[2] + cur_rule['re_expr'] = words_to_re(words, 2) + cur_rule['re'] = rspamd_regexp.create_cached(cur_rule['re_expr']) + if cur_rule['re'] then valid_rule = true end + elseif words[1] == "rawbody" and slash then + -- body SYMBOL /regexp/ + if valid_rule then + insert_cur_rule() + end + cur_rule['type'] = 'message' + cur_rule['symbol'] = words[2] + cur_rule['re_expr'] = words_to_re(words, 2) + cur_rule['re'] = rspamd_regexp.create_cached(cur_rule['re_expr']) + if cur_rule['re'] then valid_rule = true end + elseif words[1] == "meta" then + -- meta SYMBOL expression + if valid_rule then + insert_cur_rule() + end + cur_rule['type'] = 'meta' + cur_rule['symbol'] = words[2] + cur_rule['meta'] = words_to_re(words, 2) + if cur_rule['meta'] then valid_rule = true end + elseif words[1] == "describe" and valid_rule then + cur_rule['description'] = words_to_re(words, 1) + end + end)() + end + if valid_rule then + insert_cur_rule() + end +end + +if type(section) == "table" then + for _,fn in pairs(section) do + f = io.open(fn, "r") + if f then + process_sa_conf(f) + end + end +end \ No newline at end of file