From 2b6bc9234a65ef209c6efcda023a3ecf86b27e65 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Fri, 30 Nov 2007 21:56:55 +0100 Subject: [PATCH] Further developed imapflags extension and added proper logging functions to the result object. --- .../plugins/imapflags/ext-imapflags-common.c | 2 +- .../plugins/imapflags/ext-imapflags-common.h | 3 + .../plugins/imapflags/imapflags.sieve | 8 +- src/lib-sieve/plugins/imapflags/tag-flags.c | 109 +++++++++++++----- src/lib-sieve/sieve-actions.c | 43 ++++--- src/lib-sieve/sieve-actions.h | 1 + src/lib-sieve/sieve-result.c | 37 ++++++ src/lib-sieve/sieve-result.h | 5 + src/lib-sieve/sieve-validator.c | 8 +- 9 files changed, 156 insertions(+), 60 deletions(-) diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c index 5f88019bc..871bd5e74 100644 --- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c @@ -131,7 +131,7 @@ static bool flag_is_valid(const char *flag) return TRUE; } -static void ext_imapflags_iter_init +void ext_imapflags_iter_init (struct ext_imapflags_iter *iter, string_t *flags_list) { iter->flags_list = flags_list; diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h index 087e3ec20..e50b6fb0b 100644 --- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h @@ -31,6 +31,9 @@ struct ext_imapflags_iter { unsigned int offset; unsigned int last; }; + +void ext_imapflags_iter_init + (struct ext_imapflags_iter *iter, string_t *flags_list); const char *ext_imapflags_iter_get_flag (struct ext_imapflags_iter *iter); diff --git a/src/lib-sieve/plugins/imapflags/imapflags.sieve b/src/lib-sieve/plugins/imapflags/imapflags.sieve index a05a2f68b..44a39ec7c 100644 --- a/src/lib-sieve/plugins/imapflags/imapflags.sieve +++ b/src/lib-sieve/plugins/imapflags/imapflags.sieve @@ -9,7 +9,7 @@ removeflag "$DSNRequired"; if header :contains "from" "boss@frobnitzm.example.edu" { setflag "\\Flagged"; - fileinto "INBOX.From Boss"; + fileinto "From Boss"; } if header :contains "Disposition-Notification-To" "mel@example.com" { @@ -18,11 +18,11 @@ if header :contains "Disposition-Notification-To" "mel@example.com" { if header :contains "from" "imap@cac.washington.example.edu" { removeflag "$MDNRequired \\Flagged \\Seen \\Deleted"; - fileinto "INBOX.imap-list"; + fileinto "imap-list"; } if hasflag :count "ge" :comparator "i;ascii-numeric" "2" { - fileinto "INBOX.imap-twoflags"; + fileinto "imap-twoflags"; } -fileinto :flags "\\Seen" "INBOX"; +fileinto :flags "\\Seen $MDNRequired \\Draft" "INBOX"; diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c index ea9257486..9aa9e961a 100644 --- a/src/lib-sieve/plugins/imapflags/tag-flags.c +++ b/src/lib-sieve/plugins/imapflags/tag-flags.c @@ -1,5 +1,6 @@ #include "lib.h" #include "array.h" +#include "mail-storage.h" #include "sieve-extensions.h" #include "sieve-commands.h" @@ -38,14 +39,10 @@ bool seff_flags_read void seff_flags_print (const struct sieve_side_effect *seffect, const struct sieve_action *action, void *se_context, bool *keep); -bool seff_flags_pre_execute +bool seff_flags_post_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); -bool seff_flags_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, bool *keep); + const struct sieve_action_exec_env *aenv, + void *se_context, void *tr_context); const struct sieve_side_effect flags_side_effect = { "flags", @@ -55,9 +52,9 @@ const struct sieve_side_effect flags_side_effect = { 0, seff_flags_read, seff_flags_print, - NULL, NULL, - seff_flags_post_commit, - NULL + NULL, + seff_flags_post_execute, + NULL, NULL }; const struct sieve_side_effect_extension imapflags_seffect_extension = { @@ -120,17 +117,24 @@ static bool tag_flags_generate /* Side effect execution */ +struct seff_flags_context { + const char *const *keywords; + enum mail_flags flags; +}; + bool seff_flags_read (const struct sieve_side_effect *seffect ATTR_UNUSED, const struct sieve_runtime_env *renv, sieve_size_t *address, void **se_context) { pool_t pool = sieve_result_pool(renv->result); - ARRAY_DEFINE(flags, const char *); - string_t *flag_item; + struct seff_flags_context *ctx; + ARRAY_DEFINE(keywords, const char *); + string_t *flags_item; struct sieve_coded_stringlist *flag_list; - p_array_init(&flags, pool, 2); + ctx = p_new(pool, struct seff_flags_context, 1); + p_array_init(&keywords, pool, 2); t_push(); @@ -141,16 +145,37 @@ bool seff_flags_read } /* Iterate through all requested headers to match */ - flag_item = NULL; - while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && - flag_item != NULL ) { - const char *flag = str_c(flag_item); - - array_append(&flags, &flag, 1); + flags_item = NULL; + while ( sieve_coded_stringlist_next_item(flag_list, &flags_item) && + flags_item != NULL ) { + const char *flag; + struct ext_imapflags_iter flit; + + ext_imapflags_iter_init(&flit, flags_item); + + while ( (flag=ext_imapflags_iter_get_flag(&flit)) != NULL ) { + if (flag != NULL && *flag != '\\') { + /* keyword */ + array_append(&keywords, &flag, 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; + } + } } - (void)array_append_space(&flags); - *se_context = (void **) array_idx(&flags, 0); + (void)array_append_space(&keywords); + ctx->keywords = array_idx(&keywords, 0); + *se_context = (void *) ctx; t_pop(); @@ -162,14 +187,30 @@ void seff_flags_print const struct sieve_action *action ATTR_UNUSED, void *se_context ATTR_UNUSED, bool *keep) { - const char *const *flags = (const char *const *) se_context; + struct seff_flags_context *ctx = (struct seff_flags_context *) se_context; + const char *const *keywords = ctx->keywords; printf(" + add flags:"); - while ( *flags != NULL ) { - printf(" %s", *flags); + if ( (ctx->flags & MAIL_FLAGGED) > 0 ) + printf(" \\flagged\n"); + + if ( (ctx->flags & MAIL_ANSWERED) > 0 ) + printf(" \\answered"); - flags++; + if ( (ctx->flags & MAIL_DELETED) > 0 ) + printf(" \\deleted"); + + if ( (ctx->flags & MAIL_SEEN) > 0 ) + printf(" \\seen"); + + if ( (ctx->flags & MAIL_DRAFT) > 0 ) + printf(" \\draft"); + + while ( *keywords != NULL ) { + printf(" %s", *keywords); + + keywords++; }; printf("\n"); @@ -177,14 +218,22 @@ void seff_flags_print *keep = TRUE; } -bool seff_flags_post_commit +bool seff_flags_post_execute (const struct sieve_side_effect *seffect ATTR_UNUSED, - const struct sieve_action *action, + const struct sieve_action *action ATTR_UNUSED, const struct sieve_action_exec_env *aenv ATTR_UNUSED, - void *se_context ATTR_UNUSED, void *tr_context ATTR_UNUSED, bool *keep) + void *se_context, void *tr_context) { - i_info("implicit keep preserved after %s action.", action->name); - *keep = TRUE; + struct seff_flags_context *ctx = (struct seff_flags_context *) se_context; + struct act_store_transaction *trans = + (struct act_store_transaction *) tr_context; + + printf("SETTING FLAGS\n"); + /* Update message flags. */ + mail_update_flags(trans->dest_mail, MODIFY_ADD, ctx->flags); + /* Update message keywords. */ + //mail_update_keywords(trans->dest_mail, MODIFY_REPLACE, keywords); + return TRUE; } diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index 48e9b4c55..7a2c73a25 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -8,7 +8,9 @@ #include "sieve-binary.h" #include "sieve-interpreter.h" #include "sieve-result.h" -#include "sieve-actions.h"\ +#include "sieve-actions.h" + +#include <ctype.h> /* * Side-effects 'extension' @@ -47,6 +49,7 @@ static inline const struct sieve_side_effect_extension * } void sieve_side_effect_extension_set + (struct sieve_binary *sbin, int ext_id, const struct sieve_side_effect_extension *ext) { @@ -114,7 +117,6 @@ const struct sieve_side_effect *sieve_opr_side_effect_read return NULL; } - /* * Actions common to multiple core commands */ @@ -228,10 +230,8 @@ static bool act_store_start trans->namespace = ns; trans->box = box; - if ( box == NULL ) { - printf("Open failed\n"); - act_store_get_storage_error(aenv, trans); - } + if ( box == NULL ) + act_store_get_storage_error(aenv, trans); *tr_context = (void *)trans; @@ -250,8 +250,10 @@ static bool act_store_execute trans->mail_trans = mailbox_transaction_begin (trans->box, MAILBOX_TRANSACTION_FLAG_EXTERNAL); - if (mailbox_copy(trans->mail_trans, aenv->msgdata->mail, 0, NULL, NULL) < 0) { - printf("Copy failed\n"); + trans->dest_mail = mail_alloc(trans->mail_trans, 0, NULL); + + if (mailbox_copy(trans->mail_trans, aenv->msgdata->mail, MAIL_DRAFT, NULL, + trans->dest_mail) < 0) { act_store_get_storage_error(aenv, trans); return FALSE; } @@ -261,22 +263,17 @@ static bool act_store_execute static void act_store_log_status (struct act_store_transaction *trans, - const struct sieve_message_data *msgdata, bool rolled_back, bool status ) + const struct sieve_action_exec_env *aenv, bool rolled_back, bool status ) { - const char *msgid, *mailbox_name; + const char *mailbox_name; - if (mail_get_first_header(msgdata->mail, "Message-ID", &msgid) <= 0) - msgid = ""; - else - msgid = str_sanitize(msgid, 80); - if ( trans->box == NULL ) mailbox_name = str_sanitize(trans->context->folder, 80); else mailbox_name = str_sanitize(mailbox_get_name(trans->box), 80); if (!rolled_back && status) { - i_info("msgid=%s: stored mail into mailbox '%s'", msgid, mailbox_name); + sieve_result_log(aenv, "stored mail into mailbox '%s'", mailbox_name); } else { const char *errstr; enum mail_error error; @@ -285,12 +282,12 @@ static void act_store_log_status errstr = trans->error; else errstr = mail_storage_get_last_error(trans->namespace->storage, &error); - + if ( status ) - i_info("msgid=%s: store into mailbox '%s' aborted.", msgid, mailbox_name); + sieve_result_log(aenv, "store into mailbox '%s' aborted.", mailbox_name); else - i_info("msgid=%s: failed to store into mailbox '%s': %s", - msgid, mailbox_name, errstr); + sieve_result_error(aenv, "failed to store into mailbox '%s': %s", + mailbox_name, errstr); } } @@ -302,7 +299,7 @@ static bool act_store_commit (struct act_store_transaction *) tr_context; bool status = mailbox_transaction_commit(&trans->mail_trans) == 0; - act_store_log_status(trans, aenv->msgdata, FALSE, status); + act_store_log_status(trans, aenv, FALSE, status); *keep = !status; @@ -319,11 +316,11 @@ static void act_store_rollback struct act_store_transaction *trans = (struct act_store_transaction *) tr_context; + act_store_log_status(trans, aenv, TRUE, success); + if ( trans->mail_trans != NULL ) mailbox_transaction_rollback(&trans->mail_trans); - act_store_log_status(trans, aenv->msgdata, TRUE, success); - 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 a36821be9..c3f97bd10 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -120,6 +120,7 @@ struct act_store_transaction { struct mail_namespace *namespace; struct mailbox *box; struct mailbox_transaction_context *mail_trans; + struct mail *dest_mail; const char *error; }; diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index 93cd5c518..e0afc5fb2 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -1,5 +1,7 @@ #include "lib.h" #include "mempool.h" +#include "strfuncs.h" +#include "str-sanitize.h" #include "sieve-common.h" #include "sieve-interpreter.h" @@ -7,6 +9,7 @@ #include "sieve-result.h" #include <stdio.h> + struct sieve_result_action { struct sieve_result *result; const struct sieve_action *action; @@ -76,6 +79,40 @@ inline pool_t sieve_result_pool(struct sieve_result *result) return result->pool; } +/* Logging of result */ + +void sieve_result_log + (const struct sieve_action_exec_env *aenv, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + /* Kludgy, needs explict support from liblib.a (something like i_vinfo) */ + + i_info("msgid=%s: %s", aenv->msgdata->id == NULL ? + "unspecified" : str_sanitize(aenv->msgdata->id, 80), + t_strdup_vprintf(fmt, args)); + + va_end(args); +} + +void sieve_result_error + (const struct sieve_action_exec_env *aenv, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + /* Kludgy, needs explict support from liblib.a (something like i_vinfo) */ + + i_error("msgid=%s: %s", aenv->msgdata->id == NULL ? + "unspecified" : str_sanitize(aenv->msgdata->id, 80), + t_strdup_vprintf(fmt, args)); + + va_end(args); +} + +/* Result composition */ + bool sieve_result_add_action (const struct sieve_runtime_env *renv, const struct sieve_action *action, struct sieve_side_effects_list *seffects, diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h index 8927048e1..f982a1ed9 100644 --- a/src/lib-sieve/sieve-result.h +++ b/src/lib-sieve/sieve-result.h @@ -12,6 +12,11 @@ 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_log + (const struct sieve_action_exec_env *aenv, const char *fmt, ...); +void sieve_result_error + (const struct sieve_action_exec_env *aenv, const char *fmt, ...); + bool sieve_result_add_action (const struct sieve_runtime_env *renv, const struct sieve_action *action, struct sieve_side_effects_list *seffects, diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index 747e35718..d43d9e5d0 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -32,7 +32,9 @@ static void sieve_validator_register_core_tests(struct sieve_validator *validato /* Error management */ -void sieve_validator_warning(struct sieve_validator *validator, struct sieve_ast_node *node, const char *fmt, ...) +void sieve_validator_warning +(struct sieve_validator *validator, struct sieve_ast_node *node, + const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -42,7 +44,9 @@ void sieve_validator_warning(struct sieve_validator *validator, struct sieve_ast va_end(args); } -void sieve_validator_error(struct sieve_validator *validator, struct sieve_ast_node *node, const char *fmt, ...) +void sieve_validator_error +(struct sieve_validator *validator, struct sieve_ast_node *node, + const char *fmt, ...) { va_list args; va_start(args, fmt); -- GitLab