diff --git a/README b/README index 64d543fd22fc8154657b6a161eaf6cae1f97b3d7..9b99d71591652424592bd46a68bcbbec66dac660 100644 --- a/README +++ b/README @@ -77,8 +77,8 @@ Extensions and their implementation status: relational: full regex: full, but suboptimal vacation: validation, generation and interpretation; no execution - imapflags: flag management works, but flags are not stored (no :flags) - copy: copy tag is activated for redirect and fileinto, nothing else + imapflags: flag management works, but flags are not stored + copy: full include: planned (* first leave out variables support) variables: planned (* also amend previously implemented extensions) body: planned diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c index e03bd1f0398d304869b6a6698a6d83d8e75f80e1..d165b8228190ab2e553cce4cdb4c2e57cff0b91b 100644 --- a/src/lib-sieve/cmd-discard.c +++ b/src/lib-sieve/cmd-discard.c @@ -43,6 +43,24 @@ const struct sieve_opcode cmd_discard_opcode = { opc_discard_execute }; +/* discard action */ + +static void act_discard_print + (const struct sieve_action *action, void *context, bool *keep); +static bool act_discard_commit +(const struct sieve_action *action, + const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep); + +const struct sieve_action act_discard = { + "discard", + NULL, NULL, + act_discard_print, + NULL, NULL, + act_discard_commit, + NULL +}; + + /* * Generation */ @@ -67,9 +85,30 @@ static bool opc_discard_execute { printf(">> DISCARD\n"); - sieve_result_cancel_implicit_keep(renv->result); - + (void) sieve_result_add_action(renv, &act_discard, NULL, NULL); + return TRUE; } +/* + * Action + */ + +static void act_discard_print +(const struct sieve_action *action ATTR_UNUSED, void *context ATTR_UNUSED, + bool *keep) +{ + printf("* discard\n"); + + *keep = FALSE; +} + +static bool act_discard_commit +(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv ATTR_UNUSED, + void *tr_context ATTR_UNUSED, bool *keep) +{ + *keep = FALSE; + return TRUE; +} diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c index 7c59309087a87953105e985dfd2b4a6e5e797af1..87b369562cdc6eea1111aa22b224491d13dbfa69 100644 --- a/src/lib-sieve/cmd-keep.c +++ b/src/lib-sieve/cmd-keep.c @@ -66,7 +66,6 @@ static bool opc_keep_execute sieve_size_t *address ATTR_UNUSED) { struct sieve_side_effects_list *slist = NULL; - bool added = FALSE; printf(">> KEEP\n"); @@ -74,13 +73,10 @@ static bool opc_keep_execute return FALSE; if ( renv->mailenv != NULL && renv->mailenv->inbox != NULL ) - added = sieve_act_store_add_to_result(renv, slist, renv->mailenv->inbox); + (void) sieve_act_store_add_to_result(renv, slist, renv->mailenv->inbox); else - added = sieve_act_store_add_to_result(renv, slist, "INBOX"); + (void) sieve_act_store_add_to_result(renv, slist, "INBOX"); - if ( added ) - sieve_result_cancel_implicit_keep(renv->result); - return TRUE; } diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 9325e830525a7eeeac23092896b08b7f4509c910..2ceb9d5209262acc843d352444e6e93b582c39d3 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -55,10 +55,10 @@ static bool act_redirect_check_duplicate (const struct sieve_runtime_env *renv, const struct sieve_action *action1, void *context1, void *context2); static void act_redirect_print - (const struct sieve_action *action, void *context); + (const struct sieve_action *action, void *context, bool *keep); static bool act_redirect_commit (const struct sieve_action *action ATTR_UNUSED, - const struct sieve_action_exec_env *aenv, void *tr_context); + const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep); struct act_redirect_context { const char *to_address; @@ -154,8 +154,7 @@ static bool cmd_redirect_opcode_execute act = p_new(pool, struct act_redirect_context, 1); act->to_address = p_strdup(pool, str_c(redirect)); - if ( sieve_result_add_action(renv, &act_redirect, slist, (void *) act) ) - sieve_result_cancel_implicit_keep(renv->result); + (void) sieve_result_add_action(renv, &act_redirect, slist, (void *) act); t_pop(); return TRUE; @@ -180,16 +179,18 @@ static bool act_redirect_check_duplicate } static void act_redirect_print -(const struct sieve_action *action ATTR_UNUSED, void *context) +(const struct sieve_action *action ATTR_UNUSED, void *context, bool *keep) { struct act_redirect_context *ctx = (struct act_redirect_context *) context; printf("* redirect message to: %s\n", ctx->to_address); + + *keep = FALSE; } static bool act_redirect_commit (const struct sieve_action *action ATTR_UNUSED, - const struct sieve_action_exec_env *aenv, void *tr_context) + const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep) { const struct sieve_message_data *msgdata = aenv->msgdata; struct act_redirect_context *ctx = (struct act_redirect_context *) tr_context; @@ -200,6 +201,8 @@ static bool act_redirect_commit i_info("msgid=%s: forwarded to <%s>", msgdata->id == NULL ? "" : str_sanitize(msgdata->id, 80), str_sanitize(ctx->to_address, 80)); + + *keep = FALSE; return TRUE; } diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c index 1789151a85cf02f008b57b65602f074099f5e160..052fd577a06fc34e61d14fe70a99c14475704fc4 100644 --- a/src/lib-sieve/ext-fileinto.c +++ b/src/lib-sieve/ext-fileinto.c @@ -162,8 +162,7 @@ static bool ext_fileinto_opcode_execute printf(">> FILEINTO \"%s\"\n", str_c(folder)); - if ( sieve_act_store_add_to_result(renv, slist, str_c(folder)) ) - sieve_result_cancel_implicit_keep(renv->result); + (void) sieve_act_store_add_to_result(renv, slist, str_c(folder)); t_pop(); return TRUE; diff --git a/src/lib-sieve/plugins/copy/ext-copy.c b/src/lib-sieve/plugins/copy/ext-copy.c index 11c21d7386f21fb6e5000b8fed8571f39993366a..d1b23be25b2edaf3d23da83e68e7bb2d53580681 100644 --- a/src/lib-sieve/plugins/copy/ext-copy.c +++ b/src/lib-sieve/plugins/copy/ext-copy.c @@ -3,8 +3,8 @@ * * Authors: Stephan Bosch * Specification: RFC 3894 - * Implementation: - * Status: under development + * Implementation: full + * Status: experimental, largely untested * */ @@ -52,6 +52,9 @@ static bool ext_copy_load(int ext_id) const struct sieve_side_effect_extension ext_copy_side_effect; +void seff_copy_print + (const struct sieve_side_effect *seffect, const struct sieve_action *action, + void *se_context, bool *keep); bool seff_copy_pre_execute (const struct sieve_side_effect *seffect, const struct sieve_action *action, const struct sieve_action_exec_env *aenv, void **se_context, @@ -59,7 +62,7 @@ bool seff_copy_pre_execute bool seff_copy_post_commit (const struct sieve_side_effect *seffect, const struct sieve_action *action, const struct sieve_action_exec_env *aenv, void *se_context, - void *tr_context); + void *tr_context, bool *keep); const struct sieve_side_effect copy_side_effect = { "copy", @@ -67,8 +70,8 @@ const struct sieve_side_effect copy_side_effect = { &ext_copy_side_effect, 0, - seff_copy_pre_execute, - NULL, + seff_copy_print, + NULL, NULL, seff_copy_post_commit, NULL }; @@ -122,21 +125,24 @@ static const struct sieve_argument copy_tag = { /* Side effect execution */ -bool seff_copy_pre_execute -(const struct sieve_side_effect *seffect, const struct sieve_action *action, - const struct sieve_action_exec_env *aenv, void **se_context, - void *tr_context) +void seff_copy_print + (const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + void *se_context ATTR_UNUSED, bool *keep) { - printf(" + implicit keep preserved\n"); - return TRUE; + printf(" + preserve implicit keep\n"); + + *keep = TRUE; } bool seff_copy_post_commit - (const struct sieve_side_effect *seffect, const struct sieve_action *action, - const struct sieve_action_exec_env *aenv, void *se_context, - void *tr_context) +(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action *action, + const struct sieve_action_exec_env *aenv ATTR_UNUSED, + void *se_context ATTR_UNUSED, void *tr_context ATTR_UNUSED, bool *keep) { - printf(" + implicit keep restored\n"); + i_info("implicit keep preserved after %s action.", action->name); + *keep = TRUE; return TRUE; } diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index 1d41439d6cc3249d0e0bd6f9930061519d1170b1..48e9b4c55d008d95f182b08428eee5a36b37429d 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -126,7 +126,7 @@ static bool act_store_check_duplicate const struct sieve_action *action1 ATTR_UNUSED, void *context1, void *context2); static void act_store_print - (const struct sieve_action *action ATTR_UNUSED, void *context); + (const struct sieve_action *action ATTR_UNUSED, void *context, bool *keep); static bool act_store_start (const struct sieve_action *action, @@ -136,7 +136,7 @@ static bool act_store_execute const struct sieve_action_exec_env *aenv, void *tr_context); static bool act_store_commit (const struct sieve_action *action, - const struct sieve_action_exec_env *aenv, void *tr_context); + const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep); static void act_store_rollback (const struct sieve_action *action, const struct sieve_action_exec_env *aenv, void *tr_context, bool success); @@ -184,11 +184,13 @@ static bool act_store_check_duplicate } static void act_store_print -(const struct sieve_action *action ATTR_UNUSED, void *context) +(const struct sieve_action *action ATTR_UNUSED, void *context, bool *keep) { struct act_store_context *ctx = (struct act_store_context *) context; printf("* store message in folder: %s\n", ctx->folder); + + *keep = FALSE; } /* Store transaction */ @@ -274,7 +276,7 @@ static void act_store_log_status mailbox_name = str_sanitize(mailbox_get_name(trans->box), 80); if (!rolled_back && status) { - i_info("msgid=%s: saved mail to %s", msgid, mailbox_name); + i_info("msgid=%s: stored mail into mailbox '%s'", msgid, mailbox_name); } else { const char *errstr; enum mail_error error; @@ -285,15 +287,16 @@ static void act_store_log_status errstr = mail_storage_get_last_error(trans->namespace->storage, &error); if ( status ) - i_info("msgid=%s: save to %s aborted.", msgid, mailbox_name); + i_info("msgid=%s: store into mailbox '%s' aborted.", msgid, mailbox_name); else - i_info("msgid=%s: save failed to %s: %s", msgid, mailbox_name, errstr); + i_info("msgid=%s: failed to store into mailbox '%s': %s", + msgid, mailbox_name, errstr); } } static bool act_store_commit (const struct sieve_action *action ATTR_UNUSED, - const struct sieve_action_exec_env *aenv, void *tr_context) + const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep) { struct act_store_transaction *trans = (struct act_store_transaction *) tr_context; @@ -301,6 +304,8 @@ static bool act_store_commit act_store_log_status(trans, aenv->msgdata, FALSE, status); + *keep = !status; + if ( trans->box != NULL ) mailbox_close(&trans->box); diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h index 75058cf4cea949f9d7a16047097560f849ea2f15..57d804042d96bde35af5d39d5d1935da2520ed84 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -26,7 +26,7 @@ struct sieve_action { void *context1); void (*print) - (const struct sieve_action *action, void *context); + (const struct sieve_action *action, void *context, bool *keep); bool (*start) (const struct sieve_action *action, @@ -37,7 +37,7 @@ struct sieve_action { const struct sieve_action_exec_env *aenv, void *tr_context); bool (*commit) (const struct sieve_action *action, - const struct sieve_action_exec_env *aenv, void *tr_context); + const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep); void (*rollback) (const struct sieve_action *action, const struct sieve_action_exec_env *aenv, void *tr_context, bool success); @@ -54,6 +54,10 @@ struct sieve_side_effect { const struct sieve_side_effect_extension *extension; unsigned int ext_code; + void (*print) + (const struct sieve_side_effect *seffect, const struct sieve_action *action, + void *se_context, bool *keep); + bool (*pre_execute) (const struct sieve_side_effect *seffect, const struct sieve_action *action, const struct sieve_action_exec_env *aenv, void **se_context, @@ -65,7 +69,7 @@ struct sieve_side_effect { bool (*post_commit) (const struct sieve_side_effect *seffect, const struct sieve_action *action, const struct sieve_action_exec_env *aenv, void *se_context, - void *tr_context); + void *tr_context, bool *keep); void (*rollback) (const struct sieve_side_effect *seffect, const struct sieve_action *action, const struct sieve_action_exec_env *aenv, void *se_context, diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index ae5d8043e9ef89afdddc0efb097512fc3039770c..93cd5c518a5a31c3eb5e7b737160483134c702c7 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -38,8 +38,6 @@ struct sieve_result { struct sieve_action_exec_env action_env; struct sieve_result_action *first_action; struct sieve_result_action *last_action; - - unsigned int implicit_keep:1; }; struct sieve_result *sieve_result_create(void) @@ -54,8 +52,6 @@ struct sieve_result *sieve_result_create(void) result->first_action = NULL; result->last_action = NULL; - - result->implicit_keep = TRUE; return result; } @@ -80,11 +76,6 @@ inline pool_t sieve_result_pool(struct sieve_result *result) return result->pool; } -void sieve_result_cancel_implicit_keep(struct sieve_result *result) -{ - result->implicit_keep = FALSE; -} - bool sieve_result_add_action (const struct sieve_runtime_env *renv, const struct sieve_action *action, struct sieve_side_effects_list *seffects, @@ -146,21 +137,38 @@ bool sieve_result_add_action bool sieve_result_print(struct sieve_result *result) { + bool implicit_keep = TRUE; struct sieve_result_action *rac = result->first_action; printf("\nPerformed actions:\n"); while ( rac != NULL ) { + bool keep = TRUE; const struct sieve_action *act = rac->action; + struct sieve_result_side_effect *rsef; + const struct sieve_side_effect *sef; + if ( act->print != NULL ) { - act->print(act, rac->context); + act->print(act, rac->context, &keep); } else { printf("* %s\n", act->name); } + + /* Print side effects */ + rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL; + while ( rsef != NULL ) { + sef = rsef->seffect; + if ( sef->print != NULL ) + sef->print + (sef, act, rsef->context, &keep); + rsef = rsef->next; + } + + implicit_keep = implicit_keep && keep; rac = rac->next; } - printf("\nImplicit keep: %s\n", result->implicit_keep ? "yes" : "no"); + printf("\nImplicit keep: %s\n", implicit_keep ? "yes" : "no"); return TRUE; } @@ -169,6 +177,7 @@ bool sieve_result_execute (struct sieve_result *result, const struct sieve_message_data *msgdata, const struct sieve_mail_environment *menv) { + bool implicit_keep = TRUE; bool success = TRUE, commit_ok; struct sieve_result_action *rac; struct sieve_result_action *last_attempted; @@ -250,8 +259,11 @@ bool sieve_result_execute rac->context : rac->tr_context; if ( success ) { + bool keep = TRUE; + if ( act->commit != NULL ) - commit_ok = act->commit(act, &result->action_env, context) && commit_ok; + commit_ok = act->commit(act, &result->action_env, context, &keep) && + commit_ok; /* Execute post_commit event of side effects */ rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL; @@ -259,9 +271,12 @@ bool sieve_result_execute sef = rsef->seffect; if ( sef->post_commit != NULL ) sef->post_commit - (sef, act, &result->action_env, rsef->context, context); + (sef, act, &result->action_env, rsef->context, context, + &keep); rsef = rsef->next; } + + implicit_keep = implicit_keep && keep; } else { if ( act->rollback != NULL ) act->rollback(act, &result->action_env, context, rac->success); @@ -277,6 +292,7 @@ bool sieve_result_execute rsef = rsef->next; } } + rac = rac->next; }