1/* This file is part of Mailfromd. -*- c -*- 2 Copyright (C) 2007-2021 Sergey Poznyakoff 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17MF_BUILTIN_MODULE 18 19#include <mailutils/mailutils.h> 20#include <mflib/sieve.h> 21#include "msg.h" 22 23static void 24_sieve_text_action_log(mu_sieve_machine_t mach, 25 const char *action, const char *fmt, va_list ap) 26{ 27 mu_stream_t stream; 28 eval_environ_t env = mu_sieve_get_data (mach); 29 const char *id; 30 31 mu_sieve_get_diag_stream(mach, &stream); 32 mu_stream_printf(stream, "\033s<%d>", MU_LOG_NOTICE); 33 id = mailfromd_msgid(env_get_context(env)); 34 if (id && id[0]) 35 /* ID includes trailing semicolon */ 36 mu_stream_printf(stream, "%s", id); 37 mu_stream_printf(stream, "%s", action); 38 if (fmt && fmt[0]) { 39 mu_stream_printf(stream, "; "); 40 mu_stream_vprintf(stream, fmt, ap); 41 } 42 mu_stream_printf(stream, "\n"); 43} 44 45static void 46_sieve_file_action_log(mu_sieve_machine_t mach, 47 const char *action, const char *fmt, va_list ap) 48{ 49 mu_stream_t stream; 50 eval_environ_t env = mu_sieve_get_data(mach); 51 struct mu_locus_range locus; 52 53 _sieve_text_action_log(mach, action, fmt, ap); 54 55 mu_sieve_get_diag_stream(mach, &stream); 56 env_get_locus(env, &locus); 57 mu_stream_printf(stream, "\033f<%lu>%s\033l<%u>\033s<%d>\033O<%d>%s\n", 58 (unsigned long) strlen(locus.beg.mu_file), 59 locus.beg.mu_file, 60 locus.beg.mu_line, 61 MU_LOG_NOTICE, 62 MU_LOGMODE_LOCUS|MU_LOGMODE_SEVERITY, 63 _("sieve called from here")); 64} 65 66static void 67mach_cleanup(void *ptr) 68{ 69 mu_sieve_machine_t mach = ptr; 70 mu_sieve_machine_destroy(&mach); 71} 72 73static void 74modify_debug_flags(mu_debug_level_t set, mu_debug_level_t clr) 75{ 76 mu_debug_level_t lev; 77 78 mu_debug_get_category_level(mu_sieve_debug_handle, &lev); 79 mu_debug_set_category_level(mu_sieve_debug_handle, (lev & ~clr) | set); 80} 81 82MF_DEFUN(sieve, NUMBER, NUMBER nmsg, STRING script, OPTIONAL, NUMBER flags, 83 STRING file, NUMBER line, NUMBER col) 84{ 85 mu_sieve_machine_t mach; 86 int rc; 87 int retval = 0; 88 int f = MF_OPTVAL(flags); 89 mu_attribute_t attr; 90 mu_message_t msg; 91 const char *s; 92 93 rc = mu_sieve_machine_create(&mach); 94 MF_ASSERT(rc == 0, mfe_failure, 95 _("failed to initialize sieve machine: %s"), 96 mu_strerror(rc)); 97 MF_DCL_CLEANUP(mach, mach_cleanup); 98 99 if (f & MF_SIEVE_DEBUG_TRACE) 100 modify_debug_flags(MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE4), 0); 101 if (f & MF_SIEVE_DEBUG_INSTR) 102 modify_debug_flags(MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE9), 0); 103 104 mu_sieve_set_environ(mach, "location", "MTA"); 105 mu_sieve_set_environ(mach, "phase", "pre"); 106 s = env_get_macro(env, "client_addr"); 107 if (s) 108 mu_sieve_set_environ(mach, "remote-ip", s); 109 s = env_get_macro(env, "client_ptr"); 110 if (s) 111 mu_sieve_set_environ(mach, "remote-host", s); 112 113 mu_sieve_set_data(mach, env); 114 115 if (f & MF_SIEVE_TEXT) { 116 struct mu_locus_range locus = MU_LOCUS_RANGE_INITIALIZER; 117 struct mu_locus_point pt; 118 119 env_get_locus(env, &locus); 120 if (f & MF_SIEVE_LOG) 121 mu_sieve_set_logger(mach, _sieve_text_action_log); 122 pt.mu_file = MF_OPTVAL(file, locus.beg.mu_file); 123 pt.mu_line = MF_OPTVAL(line, locus.beg.mu_line); 124 pt.mu_col = MF_OPTVAL(col, locus.beg.mu_col); 125 rc = mu_sieve_compile_text(mach, script, strlen(script), &pt); 126 } else { 127 if (f & MF_SIEVE_LOG) 128 mu_sieve_set_logger(mach, _sieve_file_action_log); 129 rc = mu_sieve_compile(mach, script); 130 } 131 132 MF_ASSERT(rc == 0, 133 mfe_failure, 134 _("compilation of Sieve script %s failed"), 135 script); 136 137 msg = bi_message_from_descr(env, nmsg); 138 139 mu_message_get_attribute(msg, &attr); 140 mu_attribute_unset_deleted(attr); 141 rc = mu_sieve_message(mach, msg); 142 MF_ASSERT(rc == 0, 143 mfe_failure, 144 _("sieving failed: %s"), 145 mu_strerror(rc)); 146 retval = !(mu_attribute_is_deleted(attr) == 0); 147 148 MF_RETURN(retval); 149} 150END 151 152