diff --git a/doc/man/sieve-test.1 b/doc/man/sieve-test.1 index 4955f1d5ce6ed4132d6f17ea992191b5c6361f1c..a2de66c1ddcb49b29db1ab96d981148bfc00113c 100644 --- a/doc/man/sieve-test.1 +++ b/doc/man/sieve-test.1 @@ -2,8 +2,8 @@ .SH NAME sieve-test \- Sieve script tester for the Dovecot secure IMAP server .SH SYNOPSIS -sieve-test [\fB-r\fR \fIrecipient-address\fR] [\fB-s\fR \fIenvelope-sender\fR] [\fB-m\fR \fImailbox\fR] [\fB-d\fR \fIdump-file\fR] [\fB-c\fR] [\fB-t\fR] -[\fB-x\fR "\fIextension extension ...\fR"] \fIscript-file\fR \fImail-file\fR +sieve-test [\fB-r\fR \fIrecipient-address\fR] [\fB-f\fR \fIenvelope-sender\fR] [\fB-m\fR \fImailbox\fR] [\fB-d\fR \fIdump-file\fR] [\fB-c\fR] [\fB-t\fR] [\fB-x\fR "\fIextension extension ...\fR"] [\fB-s\fR \fIscript-file\fR] +\fIscript-file\fR \fImail-file\fR .SH DESCRIPTION .PP The \fBsieve-test\fP command is part of the Sieve implementation for the Dovecot secure @@ -27,7 +27,7 @@ the e-mail message to filter. The envelope recipient address. This is what Sieve's envelope test will compare to when the "to" envelope part is requested. .TP -\fB-s\fP \fIenvelope-sender\fP +\fB-f\fP \fIenvelope-sender\fP The envelope sender. This is what Sieve's envelope test will compare to when the "from" envelope part is requested. .TP @@ -51,6 +51,11 @@ Enable simple trace debugging; prints all encountered byte code instructions on \fB-x\fP "\fIextension extension ...\fP" Set the available extensions. The parameter is a space-separated list of the active extensions. Unknown extensions are ignored, but a warning is produced. +.TP +\fB-s\fP \fIscript-file\fP (not implemented) +Specify additional scripts to be executed before the main script. Multiple \fB-s\fP arguments are +allowed and the specified scripts are executed sequentially in the order specified at the command +line. .SH AUTHOR .PP The Sieve implementation for Dovecot was written by Stephan Bosch <stephan@rename-it.nl>. diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 0c8398c4dfcb2654333d9be536bd167e5c453002..ca2b21b2c524772344b0d59dcf1cab307764de00 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -355,7 +355,7 @@ static bool act_redirect_commit str_sanitize(ctx->to_address, 128)); /* Indicate that message was successfully forwarded */ - aenv->estatus->message_forwarded = TRUE; + aenv->exec_status->message_forwarded = TRUE; /* Cancel implicit keep */ *keep = FALSE; diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c index 01da24a36084d20724735418a6367e7bb617d10b..aa80745f8415e539f4e9f61d54efc362d431c26f 100644 --- a/src/lib-sieve/plugins/imapflags/tag-flags.c +++ b/src/lib-sieve/plugins/imapflags/tag-flags.c @@ -217,31 +217,31 @@ static struct seff_flags_context *seff_flags_get_implicit_context ctx = p_new(pool, struct seff_flags_context, 1); p_array_init(&ctx->keywords, pool, 2); - t_push(); + T_BEGIN { - /* Unpack */ - ext_imapflags_get_implicit_flags_init(&flit, result); - while ( (flag=ext_imapflags_iter_get_flag(&flit)) != NULL ) { - if (flag != NULL && *flag != '\\') { - /* keyword */ - const char *keyword = p_strdup(pool, flag); - array_append(&ctx->keywords, &keyword, 1); - } else { - /* system flag */ - if (flag == NULL || strcasecmp(flag, "\\flagged") == 0) - ctx->flags |= MAIL_FLAGGED; - else if (strcasecmp(flag, "\\answered") == 0) - ctx->flags |= MAIL_ANSWERED; - else if (strcasecmp(flag, "\\deleted") == 0) - ctx->flags |= MAIL_DELETED; - else if (strcasecmp(flag, "\\seen") == 0) - ctx->flags |= MAIL_SEEN; - else if (strcasecmp(flag, "\\draft") == 0) - ctx->flags |= MAIL_DRAFT; + /* Unpack */ + ext_imapflags_get_implicit_flags_init(&flit, result); + while ( (flag=ext_imapflags_iter_get_flag(&flit)) != NULL ) { + if (flag != NULL && *flag != '\\') { + /* keyword */ + const char *keyword = p_strdup(pool, flag); + array_append(&ctx->keywords, &keyword, 1); + } else { + /* system flag */ + if (flag == NULL || strcasecmp(flag, "\\flagged") == 0) + ctx->flags |= MAIL_FLAGGED; + else if (strcasecmp(flag, "\\answered") == 0) + ctx->flags |= MAIL_ANSWERED; + else if (strcasecmp(flag, "\\deleted") == 0) + ctx->flags |= MAIL_DELETED; + else if (strcasecmp(flag, "\\seen") == 0) + ctx->flags |= MAIL_SEEN; + else if (strcasecmp(flag, "\\draft") == 0) + ctx->flags |= MAIL_DRAFT; + } } - } - t_pop(); + } T_END; return ctx; } diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 25f136dfd7f223f568797f462826cff41710aaf0..d9b65881bff429609e91209af62aa2acd4e130ed 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -496,8 +496,7 @@ bool ext_include_execute_include if ( result > 0 ) { /* Create interpreter for top-level included script (first sub-interpreter) */ - subinterp = sieve_interpreter_create - (renv->sbin, ehandler, renv->trace_stream); + subinterp = sieve_interpreter_create(renv->sbin, ehandler); if ( subinterp != NULL ) { curctx = ext_include_interpreter_context_init_child @@ -506,7 +505,7 @@ bool ext_include_execute_include /* Activate and start the top-level included script */ result = ( sieve_interpreter_start (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, renv->result, - renv->estatus, &interrupted) == 1 ); + &interrupted) == 1 ); } else result = SIEVE_EXEC_BIN_CORRUPT; } @@ -555,8 +554,7 @@ bool ext_include_execute_include if ( result > 0 ) { /* Create sub-interpreter */ - subinterp = sieve_interpreter_create - (renv->sbin, ehandler, renv->trace_stream); + subinterp = sieve_interpreter_create(renv->sbin, ehandler); if ( subinterp != NULL ) { curctx = ext_include_interpreter_context_init_child @@ -567,7 +565,7 @@ bool ext_include_execute_include curctx->returned = FALSE; result = ( sieve_interpreter_start (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, - renv->result, renv->estatus, &interrupted) == 1 ); + renv->result, &interrupted) == 1 ); } else result = SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index 110678ebbe86cd06e62c188a34292cd40942ac4f..c544cb79352a97199f44ab8c22a95694b6343e6f 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -176,7 +176,7 @@ static void act_store_get_storage_error static struct mailbox *act_store_mailbox_open (const struct sieve_action_exec_env *aenv, struct mail_namespace *ns, const char *folder) { - struct mail_storage **storage = &(aenv->estatus->last_storage); + struct mail_storage **storage = &(aenv->exec_status->last_storage); enum mailbox_open_flags open_flags = MAILBOX_OPEN_FAST | MAILBOX_OPEN_KEEP_RECENT | MAILBOX_OPEN_SAVEONLY | MAILBOX_OPEN_POST_SESSION; @@ -288,12 +288,12 @@ static bool act_store_execute /* Mark attempt to store in default mailbox */ if ( strcmp(trans->context->folder, SIEVE_SCRIPT_DEFAULT_MAILBOX(aenv->scriptenv)) == 0 ) - aenv->estatus->tried_default_save = TRUE; + aenv->exec_status->tried_default_save = TRUE; /* Mark attempt to use storage. Can only get here when all previous actions * succeeded. */ - aenv->estatus->last_storage = trans->namespace->storage; + aenv->exec_status->last_storage = trans->namespace->storage; /* Start mail transaction */ trans->mail_trans = mailbox_transaction_begin @@ -388,7 +388,7 @@ static bool act_store_commit /* Mark attempt to use storage. Can only get here when all previous actions * succeeded. */ - aenv->estatus->last_storage = trans->namespace->storage; + aenv->exec_status->last_storage = trans->namespace->storage; /* Free mail object for stored message */ if ( trans->dest_mail != NULL ) @@ -399,7 +399,7 @@ static bool act_store_commit /* Note the fact that the message was stored at least once */ if ( status ) - aenv->estatus->message_saved = TRUE; + aenv->exec_status->message_saved = TRUE; /* Log our status */ act_store_log_status(trans, aenv, FALSE, status); diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h index 47aca68e60031b01597ab4c5df89867fc1ab057c..65a3228b5996cdfad8eb75c4049977bcae076b2b 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -19,7 +19,7 @@ struct sieve_action_exec_env { struct sieve_result *result; const struct sieve_message_data *msgdata; const struct sieve_script_env *scriptenv; - struct sieve_exec_status *estatus; + struct sieve_exec_status *exec_status; }; const char *sieve_action_get_location(const struct sieve_action_exec_env *aenv); diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index de524d20e0bdbe0c1a161dca5284ba1a50795481..8a580016e71af8fd0bcf1279c51e84cc7b0e871b 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -60,13 +60,12 @@ struct sieve_interpreter { /* Start address of current operation */ sieve_size_t current_op_addr; - /* Runtime environment environment */ + /* Runtime environment */ struct sieve_runtime_env runenv; }; struct sieve_interpreter *sieve_interpreter_create -(struct sieve_binary *sbin, struct sieve_error_handler *ehandler, - struct ostream *trace_stream) +(struct sieve_binary *sbin, struct sieve_error_handler *ehandler) { unsigned int i, ext_count; bool success = TRUE; @@ -83,7 +82,6 @@ struct sieve_interpreter *sieve_interpreter_create interp->runenv.interp = interp; interp->runenv.sbin = sbin; - interp->runenv.trace_stream = trace_stream; interp->runenv.script = sieve_binary_script(sbin); sieve_binary_ref(sbin); @@ -478,8 +476,7 @@ int sieve_interpreter_continue int sieve_interpreter_start (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_message_context *msgctx, - struct sieve_result *result, struct sieve_exec_status *estatus, - bool *interrupted) + struct sieve_result *result, bool *interrupted) { const struct sieve_interpreter_extension_reg *extrs; unsigned int ext_count, i; @@ -487,7 +484,12 @@ int sieve_interpreter_start interp->runenv.msgdata = msgdata; interp->runenv.result = result; interp->runenv.scriptenv = senv; - interp->runenv.estatus = estatus; + interp->runenv.trace_stream = senv->trace_stream; + + if ( senv->exec_status == NULL ) + interp->runenv.exec_status = p_new(interp->pool, struct sieve_exec_status, 1); + else + interp->runenv.exec_status = senv->exec_status; if ( msgctx == NULL ) interp->runenv.msgctx = sieve_message_context_create(); @@ -508,36 +510,16 @@ int sieve_interpreter_start int sieve_interpreter_run (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result **result, - struct sieve_exec_status *estatus) + const struct sieve_script_env *senv, struct sieve_result *result) { - bool is_topmost = ( *result == NULL ); int ret = 0; - - sieve_interpreter_reset(interp); - - /* Reset execution status */ - memset(estatus, 0, sizeof(*estatus)); - if ( is_topmost ) - *result = sieve_result_create(interp->ehandler); - else { - sieve_result_ref(*result); - } + sieve_interpreter_reset(interp); + sieve_result_ref(result); - ret = sieve_interpreter_start - (interp, msgdata, senv, NULL, *result, estatus, NULL); - - if ( ret >= 0 && is_topmost ) { - if ( ret > 0 ) - ret = sieve_result_execute(*result, msgdata, senv, estatus); - else { - if ( !sieve_result_implicit_keep(*result, msgdata, senv, estatus) ) - return SIEVE_EXEC_KEEP_FAILED; - } - } + ret = sieve_interpreter_start(interp, msgdata, senv, NULL, result, NULL); - sieve_result_unref(result); + sieve_result_unref(&result); return ret; } diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index f677d9507d7c5c7d8aa247103fd663fb3437d0ca..c2d53b28ca959cd1c612dd1b59b9a210654342c1 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -32,9 +32,8 @@ struct sieve_runtime_env { struct sieve_binary *sbin; struct sieve_result *result; - - struct sieve_exec_status *estatus; - + + struct sieve_exec_status *exec_status; struct ostream *trace_stream; }; @@ -43,8 +42,7 @@ struct sieve_runtime_env { */ struct sieve_interpreter *sieve_interpreter_create - (struct sieve_binary *sbin, struct sieve_error_handler *ehandler, - struct ostream *trace_stream); + (struct sieve_binary *sbin, struct sieve_error_handler *ehandler); void sieve_interpreter_free(struct sieve_interpreter **interp); /* @@ -162,11 +160,9 @@ int sieve_interpreter_continue int sieve_interpreter_start (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_message_context *msgctx, - struct sieve_result *result, struct sieve_exec_status *estatus, - bool *interrupted); + struct sieve_result *result, bool *interrupted); int sieve_interpreter_run (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result **result, - struct sieve_exec_status *estatus); + const struct sieve_script_env *senv, 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 7e2467c5815e43bcf989aefa1d25165fad97be5f..4f22c853aa60869ec723687e9e93e3b5eb3b62be 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -71,7 +71,6 @@ struct sieve_result { struct sieve_action_exec_env action_env; const struct sieve_action *keep_action; - bool keep; unsigned int action_count; struct sieve_result_action *first_action; @@ -101,7 +100,6 @@ struct sieve_result *sieve_result_create result->action_env.result = result; result->keep_action = &act_store; - result->keep = FALSE; result->action_count = 0; result->first_action = NULL; @@ -179,7 +177,8 @@ void sieve_result_error va_list args; va_start(args, fmt); - sieve_verror(aenv->result->ehandler, sieve_action_get_location(aenv), fmt, args); + sieve_verror(aenv->result->ehandler, sieve_action_get_location(aenv), fmt, + args); va_end(args); } @@ -189,7 +188,8 @@ void sieve_result_warning va_list args; va_start(args, fmt); - sieve_vwarning(aenv->result->ehandler, sieve_action_get_location(aenv), fmt, args); + sieve_vwarning(aenv->result->ehandler, sieve_action_get_location(aenv), fmt, + args); va_end(args); } @@ -199,7 +199,8 @@ void sieve_result_log va_list args; va_start(args, fmt); - sieve_vinfo(aenv->result->ehandler, sieve_action_get_location(aenv), fmt, args); + sieve_vinfo(aenv->result->ehandler, sieve_action_get_location(aenv), fmt, + args); va_end(args); } @@ -575,12 +576,16 @@ void sieve_result_seffect_printf bool sieve_result_print (struct sieve_result *result, const struct sieve_script_env *senv, - struct ostream *stream) + struct ostream *stream, bool *keep) { struct sieve_result_print_env penv; bool implicit_keep = TRUE; struct sieve_result_action *rac; + if ( keep != NULL ) *keep = FALSE; + + /* Prepare environment */ + penv.result = result; penv.stream = stream; penv.scriptenv = senv; @@ -588,14 +593,16 @@ bool sieve_result_print sieve_result_printf(&penv, "\nPerformed actions:\n\n"); rac = result->first_action; while ( rac != NULL ) { - bool keep = TRUE; + bool impl_keep = TRUE; struct sieve_result_side_effect *rsef; const struct sieve_side_effect *sef; const struct sieve_action *act = rac->data.action; + if ( rac->keep && keep != NULL ) *keep = TRUE; + if ( act != NULL ) { if ( act->print != NULL ) - act->print(act, &penv, rac->data.context, &keep); + act->print(act, &penv, rac->data.context, &impl_keep); else sieve_result_action_printf(&penv, act->name); } else { @@ -612,14 +619,17 @@ bool sieve_result_print while ( rsef != NULL ) { sef = rsef->seffect; if ( sef->print != NULL ) - sef->print(sef, rac->data.action, &penv, rsef->context, &keep); + sef->print(sef, rac->data.action, &penv, rsef->context, &impl_keep); rsef = rsef->next; } - implicit_keep = implicit_keep && keep; + implicit_keep = implicit_keep && impl_keep; + rac = rac->next; } + if ( implicit_keep && keep != NULL ) *keep = TRUE; + sieve_result_printf (&penv, "\nImplicit keep: %s\n", implicit_keep ? "yes" : "no"); @@ -714,37 +724,59 @@ static bool _sieve_result_implicit_keep bool sieve_result_implicit_keep (struct sieve_result *result, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus) + const struct sieve_script_env *senv) { + struct sieve_exec_status dummy_status; + result->action_env.msgdata = msgdata; result->action_env.scriptenv = senv; - result->action_env.estatus = estatus; + result->action_env.exec_status = + ( senv->exec_status == NULL ? &dummy_status : senv->exec_status ); return _sieve_result_implicit_keep(result, TRUE); } +void sieve_result_mark_executed(struct sieve_result *result) +{ + struct sieve_result_action *first_action, *rac; + + first_action = ( result->last_attempted_action == NULL ? + result->first_action : result->last_attempted_action ); + result->last_attempted_action = result->last_action; + + rac = first_action; + while ( rac != NULL ) { + rac->data.executed = TRUE; + + rac = rac->next; + } +} + int sieve_result_execute (struct sieve_result *result, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus) -{ + const struct sieve_script_env *senv, bool *keep) +{ + struct sieve_exec_status dummy_status; bool implicit_keep = TRUE; bool success = TRUE, commit_ok; struct sieve_result_action *rac, *first_action; struct sieve_result_action *last_attempted; + if ( keep != NULL ) *keep = FALSE; + /* Prepare environment */ result->action_env.msgdata = msgdata; result->action_env.scriptenv = senv; - result->action_env.estatus = estatus; + result->action_env.exec_status = + ( senv->exec_status == NULL ? &dummy_status : senv->exec_status ); /* Make notice of this attempt */ first_action = ( result->last_attempted_action == NULL ? result->first_action : result->last_attempted_action ); result->last_attempted_action = result->last_action; - result->keep = FALSE; - + /* * Transaction start */ @@ -822,17 +854,17 @@ int sieve_result_execute const struct sieve_side_effect *sef; if ( success ) { - bool keep = TRUE; + bool impl_keep = TRUE; rac->data.executed = TRUE; - if ( rac->keep ) result->keep = TRUE; + if ( rac->keep && keep != NULL ) *keep = TRUE; /* Skip non-action (inactive keep) */ if ( act == NULL ) continue; if ( act->commit != NULL ) commit_ok = act->commit - (act, &result->action_env, rac->tr_context, &keep) && commit_ok; + (act, &result->action_env, rac->tr_context, &impl_keep) && commit_ok; /* Execute post_commit event of side effects */ rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL; @@ -841,11 +873,11 @@ int sieve_result_execute if ( sef->post_commit != NULL ) sef->post_commit (sef, act, &result->action_env, rsef->context, rac->tr_context, - &keep); + &impl_keep); rsef = rsef->next; } - implicit_keep = implicit_keep && keep; + implicit_keep = implicit_keep && impl_keep; } else { /* Skip non-action (inactive keep) */ if ( act == NULL ) continue; @@ -868,7 +900,7 @@ int sieve_result_execute rac = rac->next; } - if ( implicit_keep ) result->keep = TRUE; + if ( implicit_keep && keep != NULL ) *keep = TRUE; /* Return value indicates whether the caller should attempt an implicit keep * of its own. So, if the above transaction fails, but the implicit keep below @@ -937,11 +969,6 @@ const struct sieve_action *sieve_result_iterate_next return NULL; } -bool sieve_result_keep(struct sieve_result *result) -{ - return result->keep; -} - /* * Side effects list */ diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h index 0e961bd12ba2ee999a42f18489ae77778240149d..41dff38f5bf164ca9a4a9bdb4683577d27e5b5be 100644 --- a/src/lib-sieve/sieve-result.h +++ b/src/lib-sieve/sieve-result.h @@ -59,7 +59,7 @@ void sieve_result_seffect_printf bool sieve_result_print (struct sieve_result *result, const struct sieve_script_env *senv, - struct ostream *stream); + struct ostream *stream, bool *keep); /* * Error handling @@ -97,11 +97,13 @@ int sieve_result_add_keep bool sieve_result_implicit_keep (struct sieve_result *result, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus); + const struct sieve_script_env *senv); + +void sieve_result_mark_executed(struct sieve_result *result); int sieve_result_execute (struct sieve_result *result, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus); + const struct sieve_script_env *senv, bool *keep); /* * Result evaluation @@ -114,8 +116,6 @@ struct sieve_result_iterate_context *sieve_result_iterate_init const struct sieve_action *sieve_result_iterate_next (struct sieve_result_iterate_context *rictx, bool *keep, void **context); -bool sieve_result_keep(struct sieve_result *result); - /* * Side effects list */ diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h index b884ef7dd91ba98479931c60c3931d85756cd42d..28c4abe768cbe5dac269cca5ea07f80facf1d234 100644 --- a/src/lib-sieve/sieve-types.h +++ b/src/lib-sieve/sieve-types.h @@ -62,6 +62,12 @@ struct sieve_script_env { (const void *id, size_t id_size, const char *user); void (*duplicate_mark) (const void *id, size_t id_size, const char *user, time_t time); + + /* Execution status record */ + struct sieve_exec_status *exec_status; + + /* Trace stream */ + struct ostream *trace_stream; }; #define SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) \ diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 0cf07733a4a4aace1e21e09b8507ffad2251a4b2..7b8e78762da52d6a2da2bc6cf748ac9dce4d5982 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -243,28 +243,37 @@ void sieve_dump(struct sieve_binary *sbin, struct ostream *stream) int sieve_test (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus, - struct ostream *stream, struct sieve_error_handler *ehandler, - struct ostream *trace_stream) + const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, + struct ostream *stream) { - struct sieve_result *sres = sieve_result_create(ehandler); - struct sieve_interpreter *interp = - sieve_interpreter_create(sbin, ehandler, trace_stream); + struct sieve_result *result; + struct sieve_interpreter *interp; int ret = 0; - if ( interp == NULL ) + /* Create interpreter */ + if ( (interp=sieve_interpreter_create(sbin, ehandler)) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; /* Reset execution status */ - memset(estatus, 0, sizeof(*estatus)); - - ret = sieve_interpreter_run(interp, msgdata, senv, &sres, estatus); + if ( senv->exec_status != NULL ) + memset(senv->exec_status, 0, sizeof(*senv->exec_status)); + /* Create result object */ + result = sieve_result_create(ehandler); + + /* Run interpreter */ + ret = sieve_interpreter_run(interp, msgdata, senv, result); + + /* Free interpreter */ + sieve_interpreter_free(&interp); + + /* Print result if successful */ if ( ret > 0 ) - ret = sieve_result_print(sres, senv, stream); + ret = sieve_result_print(result, senv, stream, NULL); + + /* Cleanup */ + sieve_result_unref(&result); - sieve_interpreter_free(&interp); - sieve_result_unref(&sres); return ret; } @@ -274,22 +283,47 @@ int sieve_test int sieve_execute (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus, - struct sieve_error_handler *ehandler, struct ostream *trace_stream) + const struct sieve_script_env *senv, struct sieve_error_handler *ehandler) { - struct sieve_result *sres = NULL; - struct sieve_interpreter *interp = - sieve_interpreter_create(sbin, ehandler, trace_stream); + struct sieve_result *result; + struct sieve_interpreter *interp; int ret = 0; - if ( interp == NULL ) + /* Create the interpreter */ + if ( (interp=sieve_interpreter_create(sbin, ehandler)) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; /* Reset execution status */ - memset(estatus, 0, sizeof(*estatus)); + if ( senv->exec_status != NULL ) + memset(senv->exec_status, 0, sizeof(*senv->exec_status)); + + /* Create result object */ + result = sieve_result_create(ehandler); - ret = sieve_interpreter_run(interp, msgdata, senv, &sres, estatus); - + /* Run the interpreter */ + ret = sieve_interpreter_run(interp, msgdata, senv, result); + + /* Free the interpreter */ sieve_interpreter_free(&interp); + + /* Evaluate status and execute the result: + * Strange situations, e.g. currupt binaries, must be handled by the caller. + * In that case no implicit keep is attempted, because the situation may be + * resolved. + */ + if ( ret >= 0 ) { + if ( ret > 0 ) + /* Execute result */ + ret = sieve_result_execute(result, msgdata, senv, NULL); + else { + /* Perform implicit keep if script failed with a normal runtime error */ + if ( !sieve_result_implicit_keep(result, msgdata, senv) ) + ret = SIEVE_EXEC_KEEP_FAILED; + } + } + + /* Cleanup */ + sieve_result_unref(&result); + return ret; } diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h index 7acb85ca0bb1477f6ac3583c84c64f8193a14229..cf0cd20a67fcaa4ab6763e21516cb93925593b0e 100644 --- a/src/lib-sieve/sieve.h +++ b/src/lib-sieve/sieve.h @@ -98,9 +98,8 @@ void sieve_dump(struct sieve_binary *sbin, struct ostream *stream); */ int sieve_test (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus, - struct ostream *stream, struct sieve_error_handler *ehandler, - struct ostream *trace_stream); + const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, + struct ostream *stream); /* * Script execution @@ -112,7 +111,6 @@ int sieve_test */ int sieve_execute (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_exec_status *estatus, - struct sieve_error_handler *ehandler, struct ostream *trace_stream); + const struct sieve_script_env *senv, struct sieve_error_handler *ehandler); #endif diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c index c9edf3dacdbc2dd49f5a829c6d8f088ce06c9f45..9a88212e915b17ea49b13b5bc44721d93dae2b40 100644 --- a/src/plugins/lda-sieve/lda-sieve-plugin.c +++ b/src/plugins/lda-sieve/lda-sieve-plugin.c @@ -174,13 +174,14 @@ static int lda_sieve_run scriptenv.smtp_close = lda_sieve_smtp_close; scriptenv.duplicate_mark = duplicate_mark; scriptenv.duplicate_check = duplicate_check; + scriptenv.exec_status = &estatus; /* Execute the script */ if ( debug ) sieve_sys_info("executing compiled script %s", script_path); - ret = sieve_execute(sbin, &msgdata, &scriptenv, &estatus, ehandler, NULL); + ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler); /* Record status */ @@ -218,7 +219,7 @@ static int lda_sieve_run /* Execute again */ - ret = sieve_execute(sbin, &msgdata, &scriptenv, &estatus, ehandler, NULL); + ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler); /* Record status */ diff --git a/src/sieve-tools/sieve-exec.c b/src/sieve-tools/sieve-exec.c index 584d17298836ddc3547816c9340506fd9743c4c3..912ed5a5759010d95f6d4bc9b60970e1ee803360 100644 --- a/src/sieve-tools/sieve-exec.c +++ b/src/sieve-tools/sieve-exec.c @@ -70,7 +70,7 @@ static void duplicate_mark static void print_help(void) { printf( -"Usage: sieve-exec [-r <recipient address>][-s <envelope sender>]\n" +"Usage: sieve-exec [-r <recipient address>][-f <envelope sender>]\n" " [-m <mailbox>][-d <dump filename>][-l <mail location>]\n" " <scriptfile> <mailfile>\n" ); @@ -105,11 +105,11 @@ int main(int argc, char **argv) if (i == argc) i_fatal("Missing -r argument"); recipient = argv[i]; - } else if (strcmp(argv[i], "-s") == 0) { + } else if (strcmp(argv[i], "-f") == 0) { /* envelope sender */ i++; if (i == argc) - i_fatal("Missing -s argument"); + i_fatal("Missing -f argument"); sender = argv[i]; } else if (strcmp(argv[i], "-m") == 0) { /* default mailbox (keep box) */ @@ -209,12 +209,13 @@ int main(int argc, char **argv) scriptenv.smtp_close = sieve_smtp_close; scriptenv.duplicate_mark = duplicate_mark; scriptenv.duplicate_check = duplicate_check; + scriptenv.exec_status = &estatus; ehandler = sieve_stderr_ehandler_create(0); sieve_error_handler_accept_infolog(ehandler, TRUE); /* Run */ - switch ( sieve_execute(sbin, &msgdata, &scriptenv, &estatus, ehandler, NULL) ) { + switch ( sieve_execute(sbin, &msgdata, &scriptenv, ehandler) ) { case SIEVE_EXEC_OK: i_info("final result: success"); break; diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c index 41faf336444cc9b22a2b068bc42f4d95d26bd17d..6cfd40ad3fef9315e6509b812a8df72de0ece5c7 100644 --- a/src/sieve-tools/sieve-test.c +++ b/src/sieve-tools/sieve-test.c @@ -3,6 +3,7 @@ #include "lib.h" #include "ostream.h" +#include "array.h" #include "mail-namespace.h" #include "mail-storage.h" @@ -37,9 +38,10 @@ static void print_help(void) # define SVTRACE #endif printf( -"Usage: sieve-test [-r <recipient address>] [-s <envelope sender>]\n" +"Usage: sieve-test [-r <recipient address>] [-f <envelope sender>]\n" " [-m <mailbox>] [-d <dump filename>] [-x <extensions>]\n" -" [-c]"SVTRACE" <scriptfile> <mailfile>\n" +" [-s <scriptfile>] [-c]"SVTRACE"\n" +" <scriptfile> <mailfile>\n" ); } @@ -49,25 +51,29 @@ static void print_help(void) int main(int argc, char **argv) { - const char *scriptfile, *recipient, *sender, *mailbox, *dumpfile, *mailfile, + ARRAY_DEFINE(scriptfiles, const char *); + const char *scriptfile, *recipient, *sender, *mailbox, *dumpfile, *mailfile, *extensions; const char *user; int i; struct mail_raw *mailr; - struct sieve_binary *sbin; + struct sieve_binary *main_sbin; struct sieve_message_data msgdata; struct sieve_script_env scriptenv; struct sieve_exec_status estatus; struct sieve_error_handler *ehandler; struct ostream *teststream; bool force_compile = FALSE; - int ret; bool trace = FALSE; - struct ostream *trace_stream = FALSE; + int ret; + + sieve_tool_init(); + + t_array_init(&scriptfiles, 16); /* Parse arguments */ - scriptfile = recipient = sender = mailbox = dumpfile = mailfile = - extensions = NULL; + scriptfile = recipient = sender = mailbox = dumpfile = mailfile = extensions + = NULL; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-r") == 0) { /* recipient address */ @@ -75,11 +81,11 @@ int main(int argc, char **argv) if (i == argc) i_fatal("Missing -r argument"); recipient = argv[i]; - } else if (strcmp(argv[i], "-s") == 0) { + } else if (strcmp(argv[i], "-f") == 0) { /* envelope sender */ i++; if (i == argc) - i_fatal("Missing -s argument"); + i_fatal("Missing -f argument"); sender = argv[i]; } else if (strcmp(argv[i], "-m") == 0) { /* default mailbox (keep box) */ @@ -99,12 +105,22 @@ int main(int argc, char **argv) if (i == argc) i_fatal("Missing -x argument"); extensions = argv[i]; + } else if (strcmp(argv[i], "-s") == 0) { + const char *file; + + /* scriptfile executed before main script */ + i++; + if (i == argc) + i_fatal("Missing -s argument"); + + file = t_strdup(argv[i]); + array_append(&scriptfiles, &file, 1); } else if (strcmp(argv[i], "-c") == 0) { - /* force compile */ + /* force compile */ force_compile = TRUE; #ifdef SIEVE_RUNTIME_TRACE } else if (strcmp(argv[i], "-t") == 0) { - /* runtime trace */ + /* runtime trace */ trace = TRUE; #endif } else if ( scriptfile == NULL ) { @@ -127,22 +143,20 @@ int main(int argc, char **argv) i_fatal("Missing <mailfile> argument"); } - sieve_tool_init(); - if ( extensions != NULL ) { sieve_set_extensions(extensions); } - /* Compile sieve script */ + /* Compile main sieve script */ if ( force_compile ) { - sbin = sieve_tool_script_compile(scriptfile); - (void) sieve_save(sbin, NULL); + main_sbin = sieve_tool_script_compile(scriptfile); + (void) sieve_save(main_sbin, NULL); } else { - sbin = sieve_tool_script_open(scriptfile); + main_sbin = sieve_tool_script_open(scriptfile); } /* Dump script */ - sieve_tool_dump_binary_to(sbin, dumpfile); + sieve_tool_dump_binary_to(main_sbin, dumpfile); user = sieve_tool_get_user(); @@ -169,31 +183,36 @@ int main(int argc, char **argv) msgdata.auth_user = user; (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); + /* Create stream for test and trace output */ + + teststream = o_stream_create_fd(1, 0, FALSE); + + /* Compose script environment */ memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.default_mailbox = "INBOX"; + scriptenv.default_mailbox = mailbox; scriptenv.username = user; + scriptenv.trace_stream = ( trace ? teststream : NULL ); + scriptenv.exec_status = &estatus; + /* Create error handler */ ehandler = sieve_stderr_ehandler_create(0); - teststream = o_stream_create_fd(1, 0, FALSE); - - if ( trace ) - trace_stream = teststream; - else - trace_stream = NULL; - /* Run the test */ - ret = sieve_test - (sbin, &msgdata, &scriptenv, &estatus, teststream, ehandler, trace_stream); + + if ( array_count(&scriptfiles) == 0 ) { + ret = sieve_test(main_sbin, &msgdata, &scriptenv, ehandler, teststream); - if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { - i_info("Corrupt binary deleted."); - (void) unlink(sieve_binary_path(sbin)); + if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { + i_info("Corrupt binary deleted."); + (void) unlink(sieve_binary_path(main_sbin)); + } + } else { + } o_stream_destroy(&teststream); - sieve_close(&sbin); + sieve_close(&main_sbin); sieve_error_handler_unref(&ehandler); /* De-initialize raw mail object */ diff --git a/src/testsuite/testsuite-result.c b/src/testsuite/testsuite-result.c index d9ba34380b0737c0a21954bf0e2e8e4e472e915c..18ecd3862de34e03984bb1b48394f108f1d3ac93 100644 --- a/src/testsuite/testsuite-result.c +++ b/src/testsuite/testsuite-result.c @@ -53,7 +53,6 @@ struct sieve_result_iterate_context *testsuite_result_iterate_init(void) bool testsuite_result_execute(const struct sieve_runtime_env *renv) { struct sieve_script_env scriptenv; - struct sieve_exec_status estatus; int ret; if ( _testsuite_result == NULL ) { @@ -78,7 +77,7 @@ bool testsuite_result_execute(const struct sieve_runtime_env *renv) /* Execute the result */ ret=sieve_result_execute - (_testsuite_result, renv->msgdata, &scriptenv, &estatus); + (_testsuite_result, renv->msgdata, &scriptenv, NULL); return ( ret > 0 ); } @@ -91,7 +90,7 @@ void testsuite_result_print out = o_stream_create_fd(1, 0, FALSE); o_stream_send_str(out, "\n--"); - sieve_result_print(_testsuite_result, renv->scriptenv, out); + sieve_result_print(_testsuite_result, renv->scriptenv, out, NULL); o_stream_send_str(out, "--\n\n"); o_stream_destroy(&out); diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c index 8134e17777ca21dc6f616010660459ca4928ebd7..6573c154b494e4ffc66c55e30c0ebb2b2d8041cc 100644 --- a/src/testsuite/testsuite-script.c +++ b/src/testsuite/testsuite-script.c @@ -67,7 +67,6 @@ bool testsuite_script_compile(const char *script_path) bool testsuite_script_run(const struct sieve_runtime_env *renv) { struct sieve_script_env scriptenv; - struct sieve_exec_status estatus; struct sieve_result *result; struct sieve_interpreter *interp; int ret; @@ -96,13 +95,13 @@ bool testsuite_script_run(const struct sieve_runtime_env *renv) /* Execute the script */ interp=sieve_interpreter_create - (_testsuite_compiled_script, testsuite_log_ehandler, NULL); + (_testsuite_compiled_script, testsuite_log_ehandler); if ( interp == NULL ) return SIEVE_EXEC_BIN_CORRUPT; ret = sieve_interpreter_run - (interp, renv->msgdata, &scriptenv, &result, &estatus); + (interp, renv->msgdata, &scriptenv, result); sieve_interpreter_free(&interp); diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 66c96bdbfac344fd2214621283bf15363be69add..ea2b80dcf1b971fa3d9891956d164212c2c86d21 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -66,45 +66,6 @@ static void print_help(void) ); } -static int testsuite_run -(struct sieve_binary *sbin, const struct sieve_script_env *scriptenv, - bool trace) -{ - struct sieve_exec_status estatus; - struct sieve_error_handler *ehandler = sieve_stderr_ehandler_create(0); - struct sieve_result *sres = sieve_result_create(ehandler); - struct sieve_interpreter *interp; - int ret = 0; - - if ( trace ) { - struct ostream *tstream = o_stream_create_fd(1, 0, FALSE); - - interp = sieve_interpreter_create(sbin, ehandler, tstream); - - if ( interp != NULL ) - ret = sieve_interpreter_run - (interp, &testsuite_msgdata, scriptenv, &sres, &estatus); - - o_stream_destroy(&tstream); - } else { - interp=sieve_interpreter_create(sbin, ehandler, NULL); - - if ( interp != NULL ) - ret = sieve_interpreter_run - (interp, &testsuite_msgdata, scriptenv, &sres, &estatus); - } - - if ( interp != NULL ) - sieve_interpreter_free(&interp); - else - ret = SIEVE_EXEC_BIN_CORRUPT; - - sieve_result_unref(&sres); - sieve_error_handler_unref(&ehandler); - - return ret; -} - int main(int argc, char **argv) { const char *scriptfile, *dumpfile; @@ -113,6 +74,7 @@ int main(int argc, char **argv) struct sieve_binary *sbin; const char *sieve_dir; struct sieve_script_env scriptenv; + struct sieve_error_handler *ehandler; bool trace = FALSE; /* Parse arguments */ @@ -177,9 +139,11 @@ int main(int argc, char **argv) memset(&scriptenv, 0, sizeof(scriptenv)); scriptenv.default_mailbox = "INBOX"; scriptenv.username = user; + scriptenv.trace_stream = ( trace ? o_stream_create_fd(1, 0, FALSE) : NULL ); /* Run the test */ - ret = testsuite_run(sbin, &scriptenv, trace); + ehandler = sieve_stderr_ehandler_create(0); + ret = sieve_execute(sbin, &testsuite_msgdata, &scriptenv, ehandler); switch ( ret ) { case SIEVE_EXEC_OK: @@ -196,6 +160,10 @@ int main(int argc, char **argv) } sieve_close(&sbin); + sieve_error_handler_unref(&ehandler); + + if ( scriptenv.trace_stream != NULL ) + o_stream_unref(&scriptenv.trace_stream); /* De-initialize message environment */ testsuite_message_deinit();