diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 157f2d0eadcf59b8c4347c808184e67627efbe7b..7b9da9eb5e2b8669a554d0c1c91cc15bc9617ff1 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -1,10 +1,12 @@ #include "lib.h" +#include "str-sanitize.h" #include "sieve-commands.h" #include "sieve-commands-private.h" #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" +#include "sieve-result.h" /* Forward declarations */ @@ -46,6 +48,24 @@ const struct sieve_opcode cmd_redirect_opcode = { cmd_redirect_opcode_execute }; +/* Redirect action */ + +static void act_redirect_print + (const struct sieve_action *action, void *context); +static int act_redirect_execute + (const struct sieve_action *action, const struct sieve_action_exec_env *aenv, + void *context); + +struct act_redirect_context { + const char *to_address; +}; + +const struct sieve_action act_redirect = { + "redirect", + act_redirect_print, + act_redirect_execute +}; + /* Validation */ static bool cmd_redirect_validate @@ -94,14 +114,16 @@ static bool cmd_redirect_opcode_dump } /* - * Execution + * Intepretation */ static bool cmd_redirect_opcode_execute (const struct sieve_opcode *opcode ATTR_UNUSED, const struct sieve_runtime_env *renv, sieve_size_t *address) { + struct act_redirect_context *act; string_t *redirect; + pool_t pool; t_push(); @@ -111,7 +133,45 @@ static bool cmd_redirect_opcode_execute } printf(">> REDIRECT \"%s\"\n", str_c(redirect)); - + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_redirect_context, 1); + act->to_address = p_strdup(pool, str_c(redirect)); + + sieve_result_add_action(renv->result, &act_redirect, (void *) act); + t_pop(); return TRUE; } + +/* + * Action + */ + +static void act_redirect_print +(const struct sieve_action *action ATTR_UNUSED, void *context) +{ + struct act_redirect_context *ctx = (struct act_redirect_context *) context; + + printf("* redirect message to: %s\n", ctx->to_address); +} + +static int act_redirect_execute +(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *context) +{ + const struct sieve_message_data *msgdata = aenv->msgdata; + struct act_redirect_context *ctx = (struct act_redirect_context *) context; + int res; + + if ((res = aenv->mailenv-> + send_forward(msgdata, ctx->to_address)) == 0) { + i_info("msgid=%s: forwarded to <%s>", + msgdata->id == NULL ? "" : str_sanitize(msgdata->id, 80), + str_sanitize(ctx->to_address, 80)); + } + + return res; +} + + diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index 669a268e14ab00a36a3a1f46db78e7b196e660e5..2f740922384b41f60431bbad33d5d7fe8eb61eed 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -231,14 +231,19 @@ bool sieve_interpreter_execute_operation } bool sieve_interpreter_run -(struct sieve_interpreter *interp, struct sieve_message_data *msgdata, - struct sieve_result *result) +(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, + const struct sieve_mail_environment *menv, struct sieve_result **result) { + bool is_topmost = ( *result == NULL ); sieve_interpreter_reset(interp); + if ( *result == NULL ) + *result = sieve_result_create(); + else + sieve_result_ref(*result); interp->runenv.msgdata = msgdata; - interp->runenv.result = result; - sieve_result_ref(result); + interp->runenv.result = *result; + interp->runenv.mailenv = menv; while ( !interp->stopped && interp->pc < sieve_binary_get_code_size(interp->runenv.sbin) ) { @@ -246,16 +251,22 @@ bool sieve_interpreter_run if ( !sieve_interpreter_execute_operation(interp) ) { printf("Execution aborted.\n"); - sieve_result_unref(&result); + sieve_result_unref(result); return FALSE; } } interp->runenv.result = NULL; interp->runenv.msgdata = NULL; + interp->runenv.mailenv = NULL; + + if ( is_topmost ) { + sieve_result_print(*result); + sieve_result_execute(*result, msgdata, menv); + } + + sieve_result_unref(result); - sieve_result_unref(&result); - return TRUE; } diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index 0f0f5fee6583fbf8b1b4fdae720740f2a76870fe..5d4e0a5f8c8c0d4f5acb409a3b915c6fe5439576 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -17,6 +17,7 @@ struct sieve_runtime_env { struct sieve_interpreter *interp; struct sieve_binary *sbin; const struct sieve_message_data *msgdata; + const struct sieve_mail_environment *mailenv; struct sieve_result *result; }; @@ -59,7 +60,7 @@ void sieve_interpreter_dump_code(struct sieve_interpreter *interp); bool sieve_interpreter_execute_operation(struct sieve_interpreter *interp); bool sieve_interpreter_run -(struct sieve_interpreter *interp, struct sieve_message_data *msgdata, - struct sieve_result *result); +(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, + const struct sieve_mail_environment *menv, struct sieve_result **result); #endif /* __SIEVE_INTERPRETER_H */ diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index 15e34c851be4786d795c7f4caa321bd2086b80d7..d7a24d0fef4853659495d4012f02846f7b559784 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -3,8 +3,10 @@ #include "sieve-result.h" +#include <stdio.h> + struct sieve_result_action { - struct sieve_action *action; + const struct sieve_action *action; void *context; struct sieve_result_action *prev, *next; @@ -13,6 +15,7 @@ struct sieve_result_action { struct sieve_result { pool_t pool; + struct sieve_action_exec_env action_env; struct sieve_result_action *first_action; struct sieve_result_action *last_action; @@ -27,7 +30,7 @@ struct sieve_result *sieve_result_create(void) pool = pool_alloconly_create("sieve_result", 4096); result = p_new(pool, struct sieve_result, 1); result->pool = pool; - + result->first_action = NULL; result->last_action = NULL; @@ -49,9 +52,13 @@ void sieve_result_unref(struct sieve_result **result) *result = NULL; } +inline pool_t sieve_result_pool(struct sieve_result *result) +{ + return result->pool; +} void sieve_result_add_action - (struct sieve_result *result, struct sieve_action *action, void *context) +(struct sieve_result *result, const struct sieve_action *action, void *context) { struct sieve_result_action *raction; @@ -74,15 +81,18 @@ void sieve_result_add_action } } -bool sieve_result_dump(struct sieve_result *result) +bool sieve_result_print(struct sieve_result *result) { struct sieve_result_action *rac = result->first_action; - while ( rac != NULL ) { - if ( rac->action->dump != NULL ) { - + printf("\nPerformed actions:\n"); + while ( rac != NULL ) { + const struct sieve_action *act = rac->action; + + if ( act->print != NULL ) { + act->print(act, rac->context); } else { - printf("ACTION: %s (no further information)\n", rac->action->name); + printf("* %s\n", act->name); } rac = rac->next; } @@ -90,17 +100,25 @@ bool sieve_result_dump(struct sieve_result *result) return TRUE; } -bool sieve_result_execute(struct sieve_result *result) -{ - struct sieve_result_action *raction = result->first_action; +bool sieve_result_execute + (struct sieve_result *result, const struct sieve_message_data *msgdata, + const struct sieve_mail_environment *menv) +{ + struct sieve_result_action *rac = result->first_action; + + result->action_env.msgdata = msgdata; + result->action_env.mailenv = menv; - while ( raction != NULL ) { - if ( raction->action->execute != NULL ) { - + printf("\n"); + while ( rac != NULL ) { + const struct sieve_action *act = rac->action; + + if ( act->execute != NULL ) { + (void) act->execute(act, &result->action_env, rac->context); } else { - i_warning("Action %s performs absolutely nothing.", raction->action->name); + i_warning("Action %s performs absolutely nothing.", act->name); } - raction = raction->next; + rac = rac->next; } return TRUE; diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h index 197a431081fbe526ce80d41445308265a5864000..6790cad49570abad2f3c0e9fee185e08e3caa831 100644 --- a/src/lib-sieve/sieve-result.h +++ b/src/lib-sieve/sieve-result.h @@ -1,28 +1,38 @@ #ifndef __SIEVE_RESULT_H #define __SIEVE_RESULT_H -#include "sieve-interpreter.h" +#include "sieve-common.h" struct sieve_result; +struct sieve_action_exec_env { + const struct sieve_message_data *msgdata; + const struct sieve_mail_environment *mailenv; +}; + struct sieve_action { const char *name; + void (*print) + (const struct sieve_action *action, void *context); int (*execute) - (struct sieve_interpreter *interpreter, struct sieve_result *result, void *context); - int (*dump) - (struct sieve_interpreter *interpreter, struct sieve_result *result, void *context); + (const struct sieve_action *action, + const struct sieve_action_exec_env *aenv, void *context); }; struct sieve_result *sieve_result_create(void); void sieve_result_ref(struct sieve_result *result); void sieve_result_unref(struct sieve_result **result); +inline pool_t sieve_result_pool(struct sieve_result *result); void sieve_result_add_action - (struct sieve_result *result, struct sieve_action *action, void *context); + (struct sieve_result *result, const struct sieve_action *action, + void *context); -bool sieve_result_dump(struct sieve_result *result); +bool sieve_result_print(struct sieve_result *result); -bool sieve_result_execute(struct sieve_result *result); +bool sieve_result_execute + (struct sieve_result *result, const struct sieve_message_data *msgdata, + const struct sieve_mail_environment *menv); #endif diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 9c0d4eb76a76aadfe92a7879a31e35ed3d2d0114..798f8f19b56d49eceeb35e4aaf92b537021f0bd6 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -144,14 +144,15 @@ void sieve_dump(struct sieve_binary *binary) } bool sieve_execute - (struct sieve_binary *binary, struct sieve_message_data *msgdata) + (struct sieve_binary *binary, const struct sieve_message_data *msgdata, + const struct sieve_mail_environment *menv) { - struct sieve_result *sres = sieve_result_create(); + struct sieve_result *sres = NULL; struct sieve_interpreter *interpreter = sieve_interpreter_create(binary); bool result = TRUE; printf("Code Execute:\n\n"); - if ( !sieve_interpreter_run(interpreter, msgdata, sres) ) { + if ( !sieve_interpreter_run(interpreter, msgdata, menv, &sres) ) { result = FALSE; } diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h index beb591927f479b596e7eb89ceb9f757010b750a9..7610fcdbef4e212be234323a441510f67094889e 100644 --- a/src/lib-sieve/sieve.h +++ b/src/lib-sieve/sieve.h @@ -11,6 +11,16 @@ struct sieve_message_data { const char *return_path; const char *to_address; const char *auth_user; + const char *id; +}; + +struct sieve_mail_environment { + /* Interface for sending mail (callbacks if you like) */ + int (*send_rejection) + (const struct sieve_message_data *msgdata, const char *recipient, + const char *reason); + int (*send_forward) + (const struct sieve_message_data *msgdata, const char *forwardto); }; bool sieve_init(const char *plugins); @@ -19,6 +29,7 @@ void sieve_deinit(void); struct sieve_binary *sieve_compile(int fd); void sieve_dump(struct sieve_binary *binary); bool sieve_execute - (struct sieve_binary *binary, struct sieve_message_data *msgdata); + (struct sieve_binary *binary, const struct sieve_message_data *msgdata, + const struct sieve_mail_environment *menv); #endif diff --git a/src/sieve-bin/Makefile.am b/src/sieve-bin/Makefile.am index df92ad1828c5d231135d8d69777ef548f20d7ceb..e6efa88a869604175926fbd2b0d830656abe28ca 100644 --- a/src/sieve-bin/Makefile.am +++ b/src/sieve-bin/Makefile.am @@ -8,7 +8,8 @@ AM_CPPFLAGS = \ -I$(dovecot_incdir)/src/lib-index \ -I$(dovecot_incdir)/src/lib-storage \ -I$(dovecot_incdir)/src/lib-storage/index \ - -I$(dovecot_incdir)/src/lib-storage/index/raw + -I$(dovecot_incdir)/src/lib-storage/index/raw \ + -I$(dovecot_incdir)/src/deliver sievec_LDFLAGS = -export-dynamic -Wl,--start-group sieve_test_LDFLAGS = -export-dynamic -Wl,--start-group @@ -41,5 +42,5 @@ sievec_SOURCES = \ sievec.c sieve_test_SOURCES = \ - sieve_test.c + sieve_test.c diff --git a/src/sieve-bin/sieve_test.c b/src/sieve-bin/sieve_test.c index 3ebdc4dc1707caeeeaaf5689de557fba73a7fb86..cea391d5d5f30c32089dd07c3e923fdf77f8890d 100644 --- a/src/sieve-bin/sieve_test.c +++ b/src/sieve-bin/sieve_test.c @@ -118,23 +118,31 @@ static struct istream *create_raw_stream(int fd) } static void sieve_test - (struct sieve_binary *sbin, struct sieve_message_data *msgdata) + (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, + const struct sieve_mail_environment *mailenv) { - const char *const *headers; - - printf("HEADERS\n"); - if (mail_get_headers_utf8(msgdata->mail, "from", &headers) >= 0) { - int i; - for ( i = 0; headers[i] != NULL; i++ ) { - printf("HEADER: From: %s\n", headers[i]); - } - } - - if ( sieve_execute(sbin, msgdata) ) { + 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; @@ -153,6 +161,7 @@ int main(int argc, char **argv) int fd; struct sieve_binary *sbin; struct sieve_message_data msgdata; + struct sieve_mail_environment mailenv; lib_init(); ioloop = io_loop_create(); @@ -237,14 +246,22 @@ int main(int argc, char **argv) /* */ 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"; - sieve_test(sbin, &msgdata); + (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(); - //ret = deliver_save(ns, &storage, mailbox, mail, 0, NULL); i_stream_unref(&input);