diff --git a/.hgignore b/.hgignore index a893372fe5a8afd902af2524e252a68dee544029..51ec656eabcc9869cdf0b81bbea46a74c96ce271 100644 --- a/.hgignore +++ b/.hgignore @@ -48,4 +48,6 @@ Makefile.in **/Makefile.in src/sieve-bin/sievec -src/sieve-bin/sieve_test +src/sieve-bin/sieve-test +src/sieve-bin/sieve-exec + diff --git a/sieve/tests/redirect.sieve b/sieve/tests/redirect.sieve index 644a5246ef83d386e76e4c74fbbeea768ea2735b..57ced4ae3a0118a12555e20f12ad4ec9cabff8d3 100644 --- a/sieve/tests/redirect.sieve +++ b/sieve/tests/redirect.sieve @@ -1,6 +1,9 @@ if address :contains "to" "vestingbar" { redirect "stephan@example.com"; - stop; } +redirect "stephan@rename-it.nl"; +redirect "nico@example.nl"; +redirect "stephan@example.com"; + keep; diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index 5d06b2a3c765da9c9a7056e529fcc6aa9cbbc822..bda76c6e98a163c925f0658772f736453517418e 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -57,8 +57,8 @@ void sieve_binary_unref(struct sieve_binary **sbin) { if ( sbin != NULL && *sbin != NULL ) { pool_unref(&((*sbin)->pool)); + *sbin = NULL; } - *sbin = NULL; } inline sieve_size_t sieve_binary_get_code_size(struct sieve_binary *sbin) diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index 2f740922384b41f60431bbad33d5d7fe8eb61eed..b01d4a3448b0620394d7a360aeb9093c1af33eaa 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -237,10 +237,12 @@ bool sieve_interpreter_run bool is_topmost = ( *result == NULL ); sieve_interpreter_reset(interp); - if ( *result == NULL ) + if ( is_topmost ) *result = sieve_result_create(); - else + else { sieve_result_ref(*result); + printf("REF\n"); + } interp->runenv.msgdata = msgdata; interp->runenv.result = *result; interp->runenv.mailenv = menv; @@ -261,7 +263,6 @@ bool sieve_interpreter_run interp->runenv.mailenv = NULL; if ( is_topmost ) { - sieve_result_print(*result); sieve_result_execute(*result, msgdata, menv); } diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index d7a24d0fef4853659495d4012f02846f7b559784..30e49dc6ce228829faa6e24ccf8b432a4a9fe194 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -47,9 +47,11 @@ void sieve_result_ref(struct sieve_result *result) void sieve_result_unref(struct sieve_result **result) { if ( result != NULL && *result != NULL ) { - pool_unref(&((*result)->pool)); + pool_t pool = (*result)->pool; + pool_unref(&pool); + if ( pool == NULL ) + *result = NULL; } - *result = NULL; } inline pool_t sieve_result_pool(struct sieve_result *result) diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 798f8f19b56d49eceeb35e4aaf92b537021f0bd6..b3207056b719716975aeb414623b8b626dd251e4 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -80,7 +80,7 @@ static struct sieve_binary *sieve_generate(struct sieve_ast *ast) return result; } -struct sieve_binary *sieve_compile(int fd) +struct sieve_binary *sieve_compile(int fd, bool verbose) { struct sieve_binary *result; struct sieve_error_handler *ehandler; @@ -91,19 +91,23 @@ struct sieve_binary *sieve_compile(int fd) /* Parse */ - printf("Parsing sieve script...\n"); + if ( verbose ) + printf("Parsing sieve script...\n"); if ( (ast = sieve_parse(fd, ehandler)) == NULL ) { printf("Parse failed.\n"); return NULL; } - printf("Parse successful.\n"); - sieve_ast_unparse(ast); - + if ( verbose ) { + printf("Parse successful.\n"); + sieve_ast_unparse(ast); + } + /* Validate */ - printf("Validating script...\n"); + if ( verbose ) + printf("Validating script...\n"); if ( !sieve_validate(ast, ehandler) ) { printf("Validation failed.\n"); @@ -112,11 +116,13 @@ struct sieve_binary *sieve_compile(int fd) return NULL; } - printf("Validation successful.\n"); - + if ( verbose ) + printf("Validation successful.\n"); + /* Generate */ - printf("Generating script...\n"); + if ( verbose ) + printf("Generating script...\n"); if ( (result=sieve_generate(ast)) == NULL ) { printf("Script generation failed.\n"); @@ -124,8 +130,9 @@ struct sieve_binary *sieve_compile(int fd) sieve_ast_unref(&ast); return NULL; } - - printf("Script generation successful.\n"); + + if ( verbose ) + printf("Script generation successful.\n"); /* Cleanup */ sieve_ast_unref(&ast); @@ -142,23 +149,42 @@ void sieve_dump(struct sieve_binary *binary) sieve_interpreter_free(interpreter); } + +bool sieve_test + (struct sieve_binary *binary, const struct sieve_message_data *msgdata) +{ + struct sieve_result *sres = sieve_result_create(); + struct sieve_interpreter *interp = sieve_interpreter_create(binary); + bool result = TRUE; + + printf("Code Execute:\n\n"); + result = sieve_interpreter_run(interp, msgdata, NULL, &sres); + if ( result ) { + printf("Script executed successfully.\n\n"); + sieve_result_print(sres); + } + + sieve_interpreter_free(interp); + sieve_result_unref(&sres); + return result; +} + bool sieve_execute (struct sieve_binary *binary, const struct sieve_message_data *msgdata, - const struct sieve_mail_environment *menv) + const struct sieve_mail_environment *menv) { struct sieve_result *sres = NULL; - struct sieve_interpreter *interpreter = sieve_interpreter_create(binary); + struct sieve_interpreter *interp = sieve_interpreter_create(binary); bool result = TRUE; printf("Code Execute:\n\n"); - if ( !sieve_interpreter_run(interpreter, msgdata, menv, &sres) ) { - result = FALSE; - } + result = sieve_interpreter_run(interp, msgdata, menv, &sres); - sieve_interpreter_free(interpreter); - + sieve_interpreter_free(interp); sieve_result_unref(&sres); return result; } + + diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h index 7610fcdbef4e212be234323a441510f67094889e..6f70a0dd488e5e4baa48c06ed419906ff4b77e98 100644 --- a/src/lib-sieve/sieve.h +++ b/src/lib-sieve/sieve.h @@ -26,8 +26,10 @@ struct sieve_mail_environment { bool sieve_init(const char *plugins); void sieve_deinit(void); -struct sieve_binary *sieve_compile(int fd); +struct sieve_binary *sieve_compile(int fd, bool verbose); void sieve_dump(struct sieve_binary *binary); +bool sieve_test + (struct sieve_binary *binary, const struct sieve_message_data *msgdata); bool sieve_execute (struct sieve_binary *binary, const struct sieve_message_data *msgdata, const struct sieve_mail_environment *menv); diff --git a/src/sieve-bin/Makefile.am b/src/sieve-bin/Makefile.am index e6efa88a869604175926fbd2b0d830656abe28ca..daed7c64582d89d25cce5e929273c89f10ff5eb5 100644 --- a/src/sieve-bin/Makefile.am +++ b/src/sieve-bin/Makefile.am @@ -1,4 +1,4 @@ -bin_PROGRAMS = sievec sieve_test +bin_PROGRAMS = sievec sieve-test sieve-exec AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib-sieve \ @@ -13,6 +13,7 @@ AM_CPPFLAGS = \ sievec_LDFLAGS = -export-dynamic -Wl,--start-group sieve_test_LDFLAGS = -export-dynamic -Wl,--start-group +sieve_exec_LDFLAGS = -export-dynamic -Wl,--start-group libs = \ $(top_srcdir)/src/lib-sieve/libsieve.la \ @@ -34,13 +35,27 @@ ldadd = \ sievec_LDADD = $(ldadd) sieve_test_LDADD = $(ldadd) +sieve_exec_LDADD = $(ldadd) sievec_DEPENDENCIES = $(libs) sieve_test_DEPENDENCIES = $(libs) +sieve_exec_DEPENDENCIES = $(libs) + +common_sources = \ + bin-common.c \ + mail-raw.c sievec_SOURCES = \ sievec.c sieve_test_SOURCES = \ - sieve_test.c + $(common_sources) \ + sieve-test.c + +sieve_exec_SOURCES = \ + $(common_sources) \ + sieve-exec.c +noinst_HEADERS = \ + bin-common.h \ + mail-raw.h diff --git a/src/sieve-bin/bin-common.c b/src/sieve-bin/bin-common.c new file mode 100644 index 0000000000000000000000000000000000000000..268da6d754e5ea5a801e6c5978332565a15d0085 --- /dev/null +++ b/src/sieve-bin/bin-common.c @@ -0,0 +1,47 @@ +/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "lib-signals.h" +#include "ioloop.h" +#include "hostpid.h" + +#include "sieve.h" +#include "bin-common.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> + +static struct ioloop *ioloop; + +static void sig_die(int signo, void *context ATTR_UNUSED) +{ + /* warn about being killed because of some signal, except SIGINT (^C) + which is too common at least while testing :) */ + if (signo != SIGINT) + i_warning("Killed with signal %d", signo); + io_loop_stop(ioloop); +} + +void bin_init(void) +{ + lib_init(); + ioloop = io_loop_create(); + + lib_signals_init(); + lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL); + lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL); + lib_signals_ignore(SIGPIPE, TRUE); + lib_signals_ignore(SIGALRM, FALSE); +} + +void bin_deinit(void) +{ + lib_signals_deinit(); + + io_loop_destroy(&ioloop); + lib_deinit(); +} + diff --git a/src/sieve-bin/bin-common.h b/src/sieve-bin/bin-common.h new file mode 100644 index 0000000000000000000000000000000000000000..ecacac4f41a5a75e27f430df784f6c44a2df98c6 --- /dev/null +++ b/src/sieve-bin/bin-common.h @@ -0,0 +1,7 @@ +#ifndef __BIN_COMMON_H +#define __BIN_COMMON_H + +void bin_init(void); +void bin_deinit(void); + +#endif /* __BIN_COMMON_H */ diff --git a/src/sieve-bin/mail-raw.c b/src/sieve-bin/mail-raw.c new file mode 100644 index 0000000000000000000000000000000000000000..a426eb19c0185953b0c7c39fb7999c19f9c11753 --- /dev/null +++ b/src/sieve-bin/mail-raw.c @@ -0,0 +1,180 @@ +/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ + +/* This file was gratefully stolen from dovecot/src/deliver/deliver.c and altered + * to suit our needs. So, this contains lots and lots of duplicated code. + * The sieve_test program needs to read an email message from stdin and it needs + * to build a struct mail (to be fed to the sieve library). Deliver does something + * similar already, so that source was a basis for this test binary. + */ + +#include "lib.h" +#include "istream.h" +#include "istream-seekable.h" +#include "fd-set-nonblock.h" +#include "str.h" +#include "str-sanitize.h" +#include "strescape.h" +#include "message-address.h" +#include "raw-storage.h" +#include "mail-namespace.h" + +#include "mail-raw.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> + +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +/* Hideous .... */ + +extern struct mail_storage raw_storage; +void mail_storage_register_all(void) { + mail_storage_class_register(&raw_storage); +} + +extern struct mailbox_list fs_mailbox_list; +void index_mailbox_list_init(void); +void mailbox_list_register_all(void) { + mailbox_list_register(&fs_mailbox_list); + index_mailbox_list_init(); +} + +/* After buffer grows larger than this, create a temporary file to /tmp + where to read the mail. */ +#define MAIL_MAX_MEMORY_BUFFER (1024*128) + +static struct istream *create_raw_stream(int fd) +{ + struct istream *input, *input2, *input_list[2]; + const unsigned char *data; + size_t i, size; + int ret; + + fd_set_nonblock(fd, FALSE); + + input = i_stream_create_fd(fd, 4096, FALSE); + input->blocking = TRUE; + /* If input begins with a From-line, drop it */ + ret = i_stream_read_data(input, &data, &size, 5); + if (ret > 0 && size >= 5 && memcmp(data, "From ", 5) == 0) { + /* skip until the first LF */ + i_stream_skip(input, 5); + while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) { + for (i = 0; i < size; i++) { + if (data[i] == '\n') + break; + } + if (i != size) { + i_stream_skip(input, i + 1); + break; + } + i_stream_skip(input, size); + } + } + + if (input->v_offset == 0) { + input2 = input; + i_stream_ref(input2); + } else { + input2 = i_stream_create_limit(input, input->v_offset, + (uoff_t)-1); + } + i_stream_unref(&input); + + input_list[0] = input2; input_list[1] = NULL; + input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER, + "/tmp/dovecot.deliver."); + i_stream_unref(&input2); + return input; +} + +static pool_t namespaces_pool; +static struct mail_namespace *raw_ns; + +void mail_raw_init(void) +{ + const char *user, *error; + struct passwd *pw; + uid_t process_euid; + + mail_storage_init(); + mail_storage_register_all(); + mailbox_list_register_all(); + + process_euid = geteuid(); + pw = getpwuid(process_euid); + if (pw != NULL) { + user = t_strdup(pw->pw_name); + } else { + i_fatal("Couldn't lookup our username (uid=%s)", + dec2str(process_euid)); + } + + namespaces_pool = pool_alloconly_create("namespaces", 1024); + + raw_ns = mail_namespaces_init_empty(namespaces_pool); + raw_ns->flags |= NAMESPACE_FLAG_INTERNAL; + if (mail_storage_create(raw_ns, "raw", "/tmp", user, + 0, FILE_LOCK_METHOD_FCNTL, &error) < 0) + i_fatal("Couldn't create internal raw storage: %s", error); +} + +struct mail_raw *mail_raw_open(int fd) +{ + pool_t pool; + struct raw_mailbox *raw_box; + struct mail_raw *mailr; + + pool = pool_alloconly_create("mail_raw", 1024); + mailr = p_new(pool, struct mail_raw, 1); + mailr->pool = pool; + + mailr->input = create_raw_stream(fd); + + mailr->box = mailbox_open(raw_ns->storage, + "Dovecot Raw Mail", mailr->input, MAILBOX_OPEN_NO_INDEX_FILES); + + if (mailr->box == NULL) + i_fatal("Can't open mail stream as raw"); + + if (mailbox_sync(mailr->box, 0, 0, NULL) < 0) { + enum mail_error error; + + i_fatal("Can't sync raw mail: %s", + mail_storage_get_last_error(raw_ns->storage, &error)); + } + raw_box = (struct raw_mailbox *) mailr->box; + raw_box->envelope_sender = DEFAULT_ENVELOPE_SENDER; + + mailr->trans = mailbox_transaction_begin(mailr->box, 0); + mailr->mail = mail_alloc(mailr->trans, 0, NULL); + mail_set_seq(mailr->mail, 1); + + /* */ + i_stream_seek(mailr->input, 0); + + return mailr; +} + +void mail_raw_close(struct mail_raw *mailr) +{ + i_stream_unref(&mailr->input); + + mail_free(&mailr->mail); + mailbox_transaction_rollback(&mailr->trans); + mailbox_close(&mailr->box); + + pool_unref(&mailr->pool); +} + +void mail_raw_deinit(void) +{ + mail_namespaces_deinit(&raw_ns); + mail_storage_deinit(); + + pool_unref(&namespaces_pool); +} + diff --git a/src/sieve-bin/mail-raw.h b/src/sieve-bin/mail-raw.h new file mode 100644 index 0000000000000000000000000000000000000000..3848cc1e4a1a9f4694d37ca968e8c98f32b14df9 --- /dev/null +++ b/src/sieve-bin/mail-raw.h @@ -0,0 +1,18 @@ +#ifndef __MAIL_RAW_H +#define __MAIL_RAW_H + +struct mail_raw { + pool_t pool; + struct mail *mail; + + struct istream *input; + struct mailbox *box; + struct mailbox_transaction_context *trans; +}; + +void mail_raw_init(void); +struct mail_raw *mail_raw_open(int fd); +void mail_raw_close(struct mail_raw *mailr); +void mail_raw_deinit(void); + +#endif /* __MAIL_RAW_H */ diff --git a/src/sieve-bin/sieve-exec.c b/src/sieve-bin/sieve-exec.c new file mode 100644 index 0000000000000000000000000000000000000000..20ef24afe128ad730a2f4d1db80d1c49dc82d91c --- /dev/null +++ b/src/sieve-bin/sieve-exec.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ + +#include "lib.h" + +#include "bin-common.h" +#include "mail-raw.h" +#include "sieve.h" + +#include <stdio.h> +#include <stdlib.h> + +#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail" +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +static int sieve_send_rejection +(const struct sieve_message_data *msgdata ATTR_UNUSED, + const char *recipient, const char *reason) +{ + i_info("<<NOT PERFORMED>> Rejected mail to %s with reason \"%s\"\n", + recipient, reason); + return 0; +} + +static int sieve_send_forward +(const struct sieve_message_data *msgdata ATTR_UNUSED, + const char *forwardto) +{ + i_info("<<NOT PERFORMED>> Forwarded mail to %s.", forwardto); + return 0; +} + +int main(int argc, char **argv) +{ + int fd; + struct mail_raw *mailr; + struct sieve_binary *sbin; + struct sieve_message_data msgdata; + struct sieve_mail_environment mailenv; + + bin_init(); + + if ( argc < 2 ) { + printf( "Usage: sieve_test <filename>\n"); + exit(1); + } + + /* Compile sieve script */ + + if ( (fd = open(argv[1], O_RDONLY)) < 0 ) { + perror("open()"); + exit(1); + } + + printf("Parsing sieve script '%s'...\n", argv[1]); + + if ( !sieve_init("") ) { + printf("Failed to initialize sieve implementation\n"); + exit(1); + } + + if ( (sbin = sieve_compile(fd, FALSE)) == NULL ) { + printf("Failed to compile sieve script\n"); + exit(1); + } + + (void) sieve_dump(sbin); + + close(fd); + + mail_raw_init(); + + mailr = mail_raw_open(0); + + /* Collect necessary message data */ + memset(&msgdata, 0, sizeof(msgdata)); + msgdata.mail = mailr->mail; + msgdata.return_path = "nico@example.com"; + msgdata.to_address = "sirius+sieve@rename-it.nl"; + msgdata.auth_user = "stephan"; + (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); + + memset(&mailenv, 0, sizeof(mailenv)); + mailenv.send_forward = sieve_send_forward; + mailenv.send_rejection = sieve_send_rejection; + + /* Run */ + sieve_execute(sbin, &msgdata, &mailenv); + + sieve_deinit(); + + mail_raw_close(mailr); + + mail_raw_deinit(); + bin_deinit(); + return 0; +} diff --git a/src/sieve-bin/sieve-test.c b/src/sieve-bin/sieve-test.c new file mode 100644 index 0000000000000000000000000000000000000000..e4c67ca51eb5b6c4f8ffd80be177348df432bd70 --- /dev/null +++ b/src/sieve-bin/sieve-test.c @@ -0,0 +1,74 @@ +/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ + +#include "lib.h" + +#include "bin-common.h" +#include "mail-raw.h" +#include "sieve.h" + +#include <stdio.h> +#include <stdlib.h> + +#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail" +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +int main(int argc, char **argv) +{ + int fd; + struct mail_raw *mailr; + struct sieve_binary *sbin; + struct sieve_message_data msgdata; + + bin_init(); + + if ( argc < 2 ) { + printf( "Usage: sieve_test <filename>\n"); + exit(1); + } + + /* Compile sieve script */ + + if ( (fd = open(argv[1], O_RDONLY)) < 0 ) { + perror("open()"); + exit(1); + } + + printf("Parsing sieve script '%s'...\n", argv[1]); + + if ( !sieve_init("") ) { + printf("Failed to initialize sieve implementation\n"); + exit(1); + } + + if ( (sbin = sieve_compile(fd, TRUE)) == NULL ) { + printf("Failed to compile sieve script\n"); + exit(1); + } + + (void) sieve_dump(sbin); + + close(fd); + + mail_raw_init(); + + mailr = mail_raw_open(0); + + /* Collect necessary message data */ + memset(&msgdata, 0, sizeof(msgdata)); + msgdata.mail = mailr->mail; + msgdata.return_path = "nico@example.com"; + msgdata.to_address = "sirius+sieve@rename-it.nl"; + msgdata.auth_user = "stephan"; + (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); + + /* Run the test */ + (void) sieve_test(sbin, &msgdata); + + sieve_deinit(); + + mail_raw_close(mailr); + + mail_raw_deinit(); + bin_deinit(); + return 0; +} diff --git a/src/sieve-bin/sieve_test.c b/src/sieve-bin/sieve_test.c deleted file mode 100644 index cea391d5d5f30c32089dd07c3e923fdf77f8890d..0000000000000000000000000000000000000000 --- a/src/sieve-bin/sieve_test.c +++ /dev/null @@ -1,282 +0,0 @@ -/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ - -/* This file was gratefully stolen from dovecot/src/deliver/deliver.c and altered - * to suit our needs. So, this contains lots and lots of duplicated code. - * The sieve_test program needs to read an email message from stdin and it needs - * to build a struct mail (to be fed to the sieve library). Deliver does something - * similar already, so that source was a basis for this test binary. - */ - -#include "lib.h" -#include "lib-signals.h" -#include "file-lock.h" -#include "array.h" -#include "ioloop.h" -#include "hostpid.h" -#include "home-expand.h" -#include "env-util.h" -#include "fd-set-nonblock.h" -#include "istream.h" -#include "istream-seekable.h" -#include "str.h" -#include "str-sanitize.h" -#include "strescape.h" -#include "message-address.h" -#include "message-header-parser.h" -#include "istream-header-filter.h" -#include "raw-storage.h" -#include "mail-namespace.h" - -#include "sieve.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <pwd.h> -#include <syslog.h> - -#define DEFAULT_AUTH_SOCKET_PATH PKG_RUNDIR"/auth-master" -#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail" -#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" - -/* Hideous .... */ - -extern struct mail_storage raw_storage; -void mail_storage_register_all(void) { - mail_storage_class_register(&raw_storage); -} - -extern struct mailbox_list fs_mailbox_list; -void index_mailbox_list_init(void); -void mailbox_list_register_all(void) { - mailbox_list_register(&fs_mailbox_list); - index_mailbox_list_init(); -} - -/* After buffer grows larger than this, create a temporary file to /tmp - where to read the mail. */ -#define MAIL_MAX_MEMORY_BUFFER (1024*128) - -/* FIXME: these two should be in some context struct instead of as globals.. */ -static const char *default_mailbox_name = NULL; - -static struct ioloop *ioloop; - -static void sig_die(int signo, void *context ATTR_UNUSED) -{ - /* warn about being killed because of some signal, except SIGINT (^C) - which is too common at least while testing :) */ - if (signo != SIGINT) - i_warning("Killed with signal %d", signo); - io_loop_stop(ioloop); -} - -static struct istream *create_raw_stream(int fd) -{ - struct istream *input, *input2, *input_list[2]; - const unsigned char *data; - size_t i, size; - int ret; - - fd_set_nonblock(fd, FALSE); - - input = i_stream_create_fd(fd, 4096, FALSE); - input->blocking = TRUE; - /* If input begins with a From-line, drop it */ - ret = i_stream_read_data(input, &data, &size, 5); - if (ret > 0 && size >= 5 && memcmp(data, "From ", 5) == 0) { - /* skip until the first LF */ - i_stream_skip(input, 5); - while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) { - for (i = 0; i < size; i++) { - if (data[i] == '\n') - break; - } - if (i != size) { - i_stream_skip(input, i + 1); - break; - } - i_stream_skip(input, size); - } - } - - if (input->v_offset == 0) { - input2 = input; - i_stream_ref(input2); - } else { - input2 = i_stream_create_limit(input, input->v_offset, - (uoff_t)-1); - } - i_stream_unref(&input); - - input_list[0] = input2; input_list[1] = NULL; - input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER, - "/tmp/dovecot.deliver."); - i_stream_unref(&input2); - return input; -} - -static void sieve_test - (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_mail_environment *mailenv) -{ - if ( sieve_execute(sbin, msgdata, mailenv) ) { - printf("Script executed to an end succesfully.\n"); - } -} - -static int sieve_send_rejection -(const struct sieve_message_data *msgdata ATTR_UNUSED, - const char *recipient, const char *reason) -{ - i_info("<<NOT PERFORMED>> Rejected mail to %s with reason \"%s\"\n", - recipient, reason); - return 0; -} - -static int sieve_send_forward -(const struct sieve_message_data *msgdata ATTR_UNUSED, - const char *forwardto) -{ - i_info("<<NOT PERFORMED>> Forwarded mail to %s.", forwardto); - return 0; -} - -int main(int argc, char **argv) -{ - const char *envelope_sender = DEFAULT_ENVELOPE_SENDER; - const char *mailbox = "INBOX"; - const char *user, *error; - struct mail_namespace *raw_ns; - struct mail_storage *storage; - struct mailbox *box; - struct raw_mailbox *raw_box; - struct istream *input; - struct mailbox_transaction_context *t; - struct mail *mail; - struct passwd *pw; - uid_t process_euid; - pool_t namespace_pool; - int fd; - struct sieve_binary *sbin; - struct sieve_message_data msgdata; - struct sieve_mail_environment mailenv; - - lib_init(); - ioloop = io_loop_create(); - - lib_signals_init(); - lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL); - lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL); - lib_signals_ignore(SIGPIPE, TRUE); - lib_signals_ignore(SIGALRM, FALSE); - - if ( argc < 2 ) { - printf( "Usage: sieve_test <filename>\n"); - exit(1); - } - - /* Compile sieve script */ - - if ( (fd = open(argv[1], O_RDONLY)) < 0 ) { - perror("open()"); - exit(1); - } - - printf("Parsing sieve script '%s'...\n", argv[1]); - - if ( !sieve_init("") ) { - printf("Failed to initialize sieve implementation\n"); - exit(1); - } - - if ( (sbin = sieve_compile(fd)) == NULL ) { - printf("Failed to compile sieve script\n"); - exit(1); - } - - (void) sieve_dump(sbin); - - close(fd); - - /* we're non-root. get our username and possibly our home. */ - process_euid = geteuid(); - pw = getpwuid(process_euid); - if (pw != NULL) { - user = t_strdup(pw->pw_name); - } else { - i_fatal("Couldn't lookup our username (uid=%s)", - dec2str(process_euid)); - } - - mail_storage_init(); - mail_storage_register_all(); - mailbox_list_register_all(); - - namespace_pool = pool_alloconly_create("namespaces", 1024); - - raw_ns = mail_namespaces_init_empty(namespace_pool); - raw_ns->flags |= NAMESPACE_FLAG_INTERNAL; - if (mail_storage_create(raw_ns, "raw", "/tmp", user, - 0, FILE_LOCK_METHOD_FCNTL, &error) < 0) - i_fatal("Couldn't create internal raw storage: %s", error); - input = create_raw_stream(0); - box = mailbox_open(raw_ns->storage, "Dovecot Delivery Mail", input, - MAILBOX_OPEN_NO_INDEX_FILES); - if (box == NULL) - i_fatal("Can't open delivery mail as raw"); - - if (mailbox_sync(box, 0, 0, NULL) < 0) { - enum mail_error error; - - i_fatal("Can't sync delivery mail: %s", - mail_storage_get_last_error(raw_ns->storage, &error)); - } - raw_box = (struct raw_mailbox *)box; - raw_box->envelope_sender = envelope_sender; - - t = mailbox_transaction_begin(box, 0); - mail = mail_alloc(t, 0, NULL); - mail_set_seq(mail, 1); - - storage = NULL; - default_mailbox_name = mailbox; - - /* */ - i_stream_seek(input, 0); - - /* Collect necessary message data */ - memset(&msgdata, 0, sizeof(msgdata)); - msgdata.mail = mail; - msgdata.return_path = "nico@example.com"; - msgdata.to_address = "sirius+sieve@rename-it.nl"; - msgdata.auth_user = "stephan"; - (void)mail_get_first_header(mail, "Message-ID", &msgdata.id); - - memset(&mailenv, 0, sizeof(mailenv)); - mailenv.send_forward = sieve_send_forward; - mailenv.send_rejection = sieve_send_rejection; - - /* Run the test */ - sieve_test(sbin, &msgdata, &mailenv); - - sieve_deinit(); - - i_stream_unref(&input); - - mail_free(&mail); - mailbox_transaction_rollback(&t); - mailbox_close(&box); - - mail_namespaces_deinit(&raw_ns); - - mail_storage_deinit(); - - lib_signals_deinit(); - - io_loop_destroy(&ioloop); - lib_deinit(); - - return 0; -} diff --git a/src/sieve-bin/sievec.c b/src/sieve-bin/sievec.c index 0292a34b8b8c3aab624e97c853877225ff56e948..e455e65ddc8cbcd4c6f7434f12d6b2355209ff03 100644 --- a/src/sieve-bin/sievec.c +++ b/src/sieve-bin/sievec.c @@ -35,7 +35,7 @@ int main(int argc, char **argv) { printf("Parsing sieve script '%s'...\n", argv[1]); if ( sieve_init("") ) { - sbin = sieve_compile(fd); + sbin = sieve_compile(fd, TRUE); if ( sbin != NULL ) (void) sieve_dump(sbin);