]> source.dussan.org Git - rspamd.git/commitdiff
Start spamassasin rules reader plugin.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 16 Feb 2015 17:40:49 +0000 (17:40 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 16 Feb 2015 17:40:49 +0000 (17:40 +0000)
src/plugins/lua/spamassassin.lua [new file with mode: 0644]

diff --git a/src/plugins/lua/spamassassin.lua b/src/plugins/lua/spamassassin.lua
new file mode 100644 (file)
index 0000000..d62675a
--- /dev/null
@@ -0,0 +1,129 @@
+--[[
+Copyright (c) 2015, Vsevolod Stakhov <vsevolod@highsecure.ru>
+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