/* This file is part of mailfromd. -*- c -*- Copyright (C) 2007, 2008 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 . */ #include #define MF_SIEVE_LOG 0x01 #define MF_SIEVE_DEBUG_TRACE 0x02 #define MF_SIEVE_DEBUG_INSTR 0x04 #define MF_SIEVE_DEBUG_MAILUTILS 0x08 #define MF_SIEVE_DEBUG_PROT 0x10 #if MAILUTILS_VERSION_NUMBER < 1290 static int _mu_debug_printer(mu_debug_t unused, size_t level, const char *fmt, va_list ap) { vlogmsg((level == MU_DEBUG_ERROR) ? LOG_ERR : LOG_DEBUG, fmt, ap); return 0; } typedef size_t mu_log_level_t; #else static int _mu_debug_printer(void *unused, mu_log_level_t level, const char *msg) { logmsg((level == MU_DEBUG_ERROR) ? LOG_ERR : LOG_DEBUG, "%s", msg); return 0; } #endif static int _sieve_debug_printer (void *unused, const char *fmt, va_list ap) { vlogmsg(LOG_DEBUG, fmt, ap); return 0; } static void _sieve_action_log (void *unused, const mu_sieve_locus_t *locus, size_t msgno, mu_message_t msg, const char *action, const char *fmt, va_list ap) { logmsg(LOG_INFO, "%s:%lu: %s", locus->source_file, (unsigned long) locus->source_line, action); } static int _sieve_parse_error (void *unused, const char *filename, int lineno, const char *fmt, va_list ap) { if (filename) { char *newfmt = NULL; asprintf(&newfmt, "%s:%lu: %s", filename, (unsigned long)lineno, fmt); vlogmsg(LOG_ERR, newfmt, ap); free(newfmt); } else vlogmsg(LOG_ERR, fmt, ap); } /* FIXME (mailutils): Cannot use mu_stream_to_message because it ignores envelope line */ int mf_stream_to_message(mu_stream_t stream, mu_message_t *msg) { int rc; mu_mailbox_t mbox; size_t n; mu_stream_flush (stream); rc = mu_mailbox_create (&mbox, "/dev/null"); if (rc) return rc; rc = mu_mailbox_open (mbox, MU_STREAM_RDWR); if (rc) return rc; mu_stream_seek(stream, 0, SEEK_SET); rc = mu_mailbox_set_stream (mbox, stream); if (rc) return rc; rc = mu_mailbox_messages_count (mbox, &n); if (rc) return rc; return mu_mailbox_get_message (mbox, 1, msg); } MF_STATE(eom) MF_CAPTURE MF_DEFUN(sieve, NUMBER, STRING script, OPTIONAL, NUMBER dbg) { mu_sieve_machine_t mach; mu_debug_t mudebug = NULL; mu_log_level_t debug_flags = 0; /* FIXME: Init */ int sieve_debug_flags = 0; int sieve_log = 0; int rc = mu_sieve_machine_init(&mach, NULL); int retval = 0; int f = MF_OPTVAL(dbg); MF_ASSERT(rc == 0, mfe_failure, _("Failed to initialize sieve machine: %s"), mu_strerror(rc)); mu_sieve_set_debug(mach, _sieve_debug_printer); if (f) { if (f & MF_SIEVE_DEBUG_TRACE) sieve_debug_flags |= MU_SIEVE_DEBUG_TRACE; if (f & MF_SIEVE_DEBUG_INSTR) sieve_debug_flags |= MU_SIEVE_DEBUG_INSTR; if (f & MF_SIEVE_DEBUG_MAILUTILS) debug_flags |= MU_DEBUG_TRACE; if (f & MF_SIEVE_DEBUG_PROT) debug_flags |= MU_DEBUG_PROT; if (f & MF_SIEVE_LOG) sieve_log = 1; } if (debug_flags) { rc = mu_debug_create(&mudebug, NULL); MF_ASSERT(rc == 0, mfe_failure, _("Cannot create debug object: %s"), mu_strerror(rc)); mu_debug_set_level(mudebug, debug_flags); mu_debug_set_print(mudebug, _mu_debug_printer, NULL); } #if MAILUTILS_VERSION_NUMBER < 1290 mu_sieve_set_debug_level(mach, mudebug, sieve_debug_flags); #else mu_sieve_set_debug_level(mach, sieve_debug_flags); mu_sieve_set_debug_object(mach, mudebug); #endif mu_sieve_set_parse_error(mach, _sieve_parse_error); if (sieve_log) mu_sieve_set_logger(mach, _sieve_action_log); rc = mu_sieve_compile(mach, script); if (rc == 0){ mu_stream_t mstr = env_get_stream(env); mu_attribute_t attr; mu_message_t msg; rc = mf_stream_to_message(mstr, &msg); if (rc) { mu_sieve_machine_destroy(&mach); MF_THROW(mfe_failure, _("Cannot translate stream to message: %s"), mu_strerror (rc)); } mu_message_get_attribute(msg, &attr); mu_attribute_unset_deleted(attr); rc = mu_sieve_message(mach, msg); if (rc == 0) retval = !(mu_attribute_is_deleted(attr) == 0); /*mu_message_destroy(&msg, mu_message_get_owner(msg));*/ if (rc) { mu_sieve_machine_destroy(&mach); MF_THROW(mfe_failure, _("Sieving failed: %s"), mu_strerror(rc)); } } else { mu_sieve_machine_destroy(&mach); MF_THROW(mfe_failure, _("Compilation of Sieve script %s failed"), script); } mu_sieve_machine_destroy(&mach); MF_RETURN(retval); } END MF_INIT