/* 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