aboutsummaryrefslogtreecommitdiffstats
path: root/lualib
diff options
context:
space:
mode:
Diffstat (limited to 'lualib')
-rw-r--r--lualib/lua_mime.lua18
-rw-r--r--lualib/rspamadm/mime.lua54
-rw-r--r--lualib/rspamadm/statistics_dump.lua71
3 files changed, 127 insertions, 16 deletions
diff --git a/lualib/lua_mime.lua b/lualib/lua_mime.lua
index f84cc4d4e..a57c2181e 100644
--- a/lualib/lua_mime.lua
+++ b/lualib/lua_mime.lua
@@ -581,6 +581,24 @@ exports.message_to_ucl = function(task)
result.size = task:get_size()
result.digest = task:get_digest()
+ result.headers = task:get_headers(true) or {}
+
+ local parts = task:get_parts() or {}
+ result.parts = {}
+ for _,part in ipairs(parts) do
+ local l = part:get_length()
+ if l > 0 then
+ local p = {}
+ p.size = l
+ p.type = string.format('%s/%s', part:get_type())
+ p.detected_type = string.format('%s/%s', part:get_detected_type())
+ p.filename = part:get_filename()
+ p.content = part:get_content()
+ p.headers = part:get_headers(true) or {}
+ table.insert(result.parts, p)
+ end
+ end
+
return result
end
diff --git a/lualib/rspamadm/mime.lua b/lualib/rspamadm/mime.lua
index 0faeeca78..0864af3fb 100644
--- a/lualib/rspamadm/mime.lua
+++ b/lualib/rspamadm/mime.lua
@@ -41,7 +41,9 @@ parser:mutex(
parser:flag "-j --json"
:description "JSON output",
parser:flag "-U --ucl"
- :description "UCL output"
+ :description "UCL output",
+ parser:flag "-M --messagepack"
+ :description "MessagePack output"
)
parser:flag "-C --compact"
:description "Use compact format"
@@ -194,6 +196,22 @@ sign:option "-o --output"
}
:default 'message'
+local dump = parser:command "dump"
+ :description "Dumps a raw message in different formats"
+dump:argument "file"
+ :description "File to process"
+ :argname "<file>"
+ :args "+"
+-- Duplicate format for convenience
+dump:mutex(
+ parser:flag "-j --json"
+ :description "JSON output",
+ parser:flag "-U --ucl"
+ :description "UCL output",
+ parser:flag "-M --messagepack"
+ :description "MessagePack output"
+)
+
local function load_config(opts)
local _r,err = rspamd_config:load_ucl(opts['config'])
@@ -239,16 +257,22 @@ local function maybe_print_fname(opts, fname)
end
end
+local function output_fmt(opts)
+ local fmt = 'json'
+ if opts.compact then fmt = 'json-compact' end
+ if opts.ucl then fmt = 'ucl' end
+ if opts.messagepack then fmt = 'msgpack' end
+
+ return fmt
+end
+
-- Print elements in form
-- filename -> table of elements
local function print_elts(elts, opts, func)
local fun = require "fun"
if opts.json or opts.ucl then
- local fmt = 'json'
- if opts.compact then fmt = 'json-compact' end
- if opts.ucl then fmt = 'ucl' end
- io.write(ucl.to_format(elts, fmt))
+ io.write(ucl.to_format(elts, output_fmt(opts)))
else
fun.each(function(fname, elt)
@@ -849,6 +873,24 @@ local function sign_handler(opts)
end
end
+local function dump_handler(opts)
+ load_config(opts)
+ rspamd_url.init(rspamd_config:get_tld_path())
+
+ for _,fname in ipairs(opts.file) do
+ local task = load_task(opts, fname)
+
+ if opts.ucl or opts.json or opts.messagepack then
+ local ucl_object = lua_mime.message_to_ucl(task)
+ io.write(ucl.to_format(ucl_object, output_fmt(opts)))
+ else
+ task:get_content():save_in_file(1)
+ end
+
+ task:destroy() -- No automatic dtor
+ end
+end
+
local function handler(args)
local opts = parser:parse(args)
@@ -870,6 +912,8 @@ local function handler(args)
modify_handler(opts)
elseif command == 'sign' then
sign_handler(opts)
+ elseif command == 'dump' then
+ dump_handler(opts)
else
parser:error('command %s is not implemented', command)
end
diff --git a/lualib/rspamadm/statistics_dump.lua b/lualib/rspamadm/statistics_dump.lua
index 7b1dc581e..aa461a92a 100644
--- a/lualib/rspamadm/statistics_dump.lua
+++ b/lualib/rspamadm/statistics_dump.lua
@@ -19,6 +19,10 @@ local rspamd_logger = require "rspamd_logger"
local argparse = require "argparse"
local rspamd_zstd = require "rspamd_zstd"
local rspamd_text = require "rspamd_text"
+local rspamd_util = require "rspamd_util"
+local rspamd_cdb = require "rspamd_cdb"
+local lua_util = require "lua_util"
+local rspamd_i64 = require "rspamd_int64"
local ucl = require "ucl"
local N = "statistics_dump"
@@ -41,8 +45,12 @@ parser:option "-c --config"
-- Extract subcommand
local dump = parser:command "dump d"
:description "Dump bayes statistics"
-dump:flag "-j --json"
- :description "Json output"
+dump:mutex(
+ dump:flag "-j --json"
+ :description "Json output",
+ dump:flag "-C --cdb"
+ :description "CDB output"
+)
dump:flag "-c --compress"
:description "Compress output"
dump:option "-b --batch-size"
@@ -51,6 +59,7 @@ dump:option "-b --batch-size"
:convert(tonumber)
:default(1000)
+
-- Restore
local restore = parser:command "restore r"
:description "Restore bayes statistics"
@@ -166,10 +175,12 @@ local function redis_map_zip(ar)
return data
end
--- Used to clear plain numeric tables
+-- Used to clear tables
local clear_fcn = table.clear or function(tbl)
- local l = #tbl
- for i=1,l do tbl[i] = nil end
+ local keys = lua_util.keys(tbl)
+ for _,k in ipairs(keys) do
+ tbl[k] = nil
+ end
end
local compress_ctx
@@ -192,7 +203,27 @@ local function dump_out(out, opts, last)
end
end
-local function dump_pattern(conn, pattern, opts, out)
+local function dump_cdb(out, opts, last, pattern)
+ local results = out[pattern]
+
+ if not out.cdb_builder then
+ -- First invocation
+ out.cdb_builder = rspamd_cdb.build(string.format('%s.cdb', pattern))
+ out.cdb_builder:add('_lrnspam', rspamd_i64.fromstring(results.learns_spam or '0'))
+ out.cdb_builder:add('_lrnham_', rspamd_i64.fromstring(results.learns_ham or '0'))
+ end
+
+ for _,o in ipairs(results.elts) do
+ out.cdb_builder:add(o.key, o.value)
+ end
+
+ if last then
+ out.cdb_builder:finalize()
+ out.cdb_builder = nil
+ end
+end
+
+local function dump_pattern(conn, pattern, opts, out, key)
local cursor = 0
repeat
@@ -232,8 +263,16 @@ local function dump_pattern(conn, pattern, opts, out)
-- Output keeping track of the commas
for i,d in ipairs(tokens) do
if cursor == 0 and i == #tokens or not opts.json then
- out[#out + 1] = rspamd_logger.slog('"%s": %s\n', d.key,
- ucl.to_format(d.data, "json-compact"))
+ if opts.cdb then
+ table.insert(out[key].elts, {
+ key = rspamd_i64.fromstring(string.match(d.key, '%d+')),
+ value = rspamd_util.pack('ff', tonumber(d.data["S"] or '0') or 0,
+ tonumber(d.data["H"] or '0'))
+ })
+ else
+ out[#out + 1] = rspamd_logger.slog('"%s": %s\n', d.key,
+ ucl.to_format(d.data, "json-compact"))
+ end
else
out[#out + 1] = rspamd_logger.slog('"%s": %s,\n', d.key,
ucl.to_format(d.data, "json-compact"))
@@ -247,8 +286,15 @@ local function dump_pattern(conn, pattern, opts, out)
-- Do not write the last chunk of out as it will be processed afterwards
if not cursor == 0 then
- dump_out(out, opts, false)
- clear_fcn(out)
+ if opts.cdb then
+ dump_out(out, opts, false)
+ clear_fcn(out)
+ else
+ dump_cdb(out, opts, false, key)
+ out[key].elts = {}
+ end
+ elseif opts.cdb then
+ dump_cdb(out, opts, true, key)
end
until cursor == 0
@@ -289,11 +335,14 @@ local function dump_handler(opts)
if opts.json then
out[#out + 1] = string.format('{"pattern": "%s", "meta": %s, "elts": {\n',
k, ucl.to_format(redis_map_zip(additional_keys), 'json-compact'))
+ elseif opts.cdb then
+ out[k] = redis_map_zip(additional_keys)
+ out[k].elts = {}
else
out[#out + 1] = string.format('"%s": %s\n', k,
ucl.to_format(redis_map_zip(additional_keys), 'json-compact'))
end
- dump_pattern(conn, pat, opts, out)
+ dump_pattern(conn, pat, opts, out, k)
patterns_seen[pat] = true
end
end