/* This file is part of Mailfromd. -*- c -*-
Copyright (C) 2007-2020 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
MF_BUILTIN_MODULE
#include
#include
#include "msg.h"
static void
_sieve_text_action_log(mu_sieve_machine_t mach,
const char *action, const char *fmt, va_list ap)
{
mu_stream_t stream;
eval_environ_t env = mu_sieve_get_data (mach);
const char *id;
mu_sieve_get_diag_stream(mach, &stream);
mu_stream_printf(stream, "\033s<%d>", MU_LOG_NOTICE);
id = mailfromd_msgid(env_get_context(env));
if (id && id[0])
/* ID includes trailing semicolon */
mu_stream_printf(stream, "%s", id);
mu_stream_printf(stream, "%s", action);
if (fmt && fmt[0]) {
mu_stream_printf(stream, "; ");
mu_stream_vprintf(stream, fmt, ap);
}
mu_stream_printf(stream, "\n");
}
static void
_sieve_file_action_log(mu_sieve_machine_t mach,
const char *action, const char *fmt, va_list ap)
{
mu_stream_t stream;
eval_environ_t env = mu_sieve_get_data(mach);
struct mu_locus_range locus;
_sieve_text_action_log(mach, action, fmt, ap);
mu_sieve_get_diag_stream(mach, &stream);
env_get_locus(env, &locus);
mu_stream_printf(stream, "\033f<%lu>%s\033l<%u>\033s<%d>\033O<%d>%s\n",
(unsigned long) strlen(locus.beg.mu_file),
locus.beg.mu_file,
locus.beg.mu_line,
MU_LOG_NOTICE,
MU_LOGMODE_LOCUS|MU_LOGMODE_SEVERITY,
_("sieve called from here"));
}
static void
mach_cleanup(void *ptr)
{
mu_sieve_machine_t mach = ptr;
mu_sieve_machine_destroy(&mach);
}
static void
modify_debug_flags(mu_debug_level_t set, mu_debug_level_t clr)
{
mu_debug_level_t lev;
mu_debug_get_category_level(mu_sieve_debug_handle, &lev);
mu_debug_set_category_level(mu_sieve_debug_handle, (lev & ~clr) | set);
}
MF_DEFUN(sieve, NUMBER, NUMBER nmsg, STRING script, OPTIONAL, NUMBER flags,
STRING file, NUMBER line, NUMBER col)
{
mu_sieve_machine_t mach;
int rc;
int retval = 0;
int f = MF_OPTVAL(flags);
mu_attribute_t attr;
mu_message_t msg;
const char *s;
rc = mu_sieve_machine_create(&mach);
MF_ASSERT(rc == 0, mfe_failure,
_("failed to initialize sieve machine: %s"),
mu_strerror(rc));
MF_DCL_CLEANUP(mach, mach_cleanup);
if (f & MF_SIEVE_DEBUG_TRACE)
modify_debug_flags(MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE4), 0);
if (f & MF_SIEVE_DEBUG_INSTR)
modify_debug_flags(MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE9), 0);
mu_sieve_set_environ(mach, "location", "MTA");
mu_sieve_set_environ(mach, "phase", "pre");
s = env_get_macro(env, "client_addr");
if (s)
mu_sieve_set_environ(mach, "remote-ip", s);
s = env_get_macro(env, "client_ptr");
if (s)
mu_sieve_set_environ(mach, "remote-host", s);
mu_sieve_set_data(mach, env);
if (f & MF_SIEVE_TEXT) {
struct mu_locus_range locus = MU_LOCUS_RANGE_INITIALIZER;
struct mu_locus_point pt;
env_get_locus(env, &locus);
if (f & MF_SIEVE_LOG)
mu_sieve_set_logger(mach, _sieve_text_action_log);
pt.mu_file = MF_OPTVAL(file, locus.beg.mu_file);
pt.mu_line = MF_OPTVAL(line, locus.beg.mu_line);
pt.mu_col = MF_OPTVAL(col, locus.beg.mu_col);
rc = mu_sieve_compile_text(mach, script, strlen(script), &pt);
} else {
if (f & MF_SIEVE_LOG)
mu_sieve_set_logger(mach, _sieve_file_action_log);
rc = mu_sieve_compile(mach, script);
}
MF_ASSERT(rc == 0,
mfe_failure,
_("compilation of Sieve script %s failed"),
script);
msg = bi_message_from_descr(env, nmsg);
mu_message_get_attribute(msg, &attr);
mu_attribute_unset_deleted(attr);
rc = mu_sieve_message(mach, msg);
MF_ASSERT(rc == 0,
mfe_failure,
_("sieving failed: %s"),
mu_strerror(rc));
retval = !(mu_attribute_is_deleted(attr) == 0);
MF_RETURN(retval);
}
END