From 5fb4684d81b35f602a5c89f546a31ae7fece28c3 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Mon, 21 Jul 2008 16:11:56 +0200 Subject: [PATCH] Cleaned up command implementations. --- src/lib-sieve/cmd-discard.c | 50 +++++++++-------- src/lib-sieve/cmd-if.c | 76 ++++++++++++++++--------- src/lib-sieve/cmd-keep.c | 42 ++++++++------ src/lib-sieve/cmd-redirect.c | 104 ++++++++++++++++++++++------------- src/lib-sieve/cmd-require.c | 26 +++++---- 5 files changed, 183 insertions(+), 115 deletions(-) diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c index 66bf04edf..c5a459076 100644 --- a/src/lib-sieve/cmd-discard.c +++ b/src/lib-sieve/cmd-discard.c @@ -1,3 +1,6 @@ +/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file + */ + #include "lib.h" #include "sieve-commands.h" @@ -10,24 +13,17 @@ #include "sieve-interpreter.h" #include "sieve-result.h" -/* Forward declarations */ +/* + * Discard command + * + * Syntax + * discard + */ static bool cmd_discard_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx ATTR_UNUSED); -static bool cmd_discard_operation_dump - (const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address); -static bool cmd_discard_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); - -/* Discard command - * - * Syntax - * discard - */ const struct sieve_command cmd_discard = { "discard", SCT_COMMAND, @@ -37,7 +33,16 @@ const struct sieve_command cmd_discard = { NULL }; -/* Discard operation */ +/* + * Discard operation + */ + +static bool cmd_discard_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool cmd_discard_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_operation cmd_discard_operation = { "DISCARD", @@ -47,14 +52,16 @@ const struct sieve_operation cmd_discard_operation = { cmd_discard_operation_execute }; -/* discard action */ +/* + * Discard actions + */ static void act_discard_print (const struct sieve_action *action, const struct sieve_result_print_env *rpenv, 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 *action, + const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep); const struct sieve_action act_discard = { "discard", @@ -66,14 +73,13 @@ const struct sieve_action act_discard = { NULL }; - /* - * Generation + * Code generation */ static bool cmd_discard_generate - (const struct sieve_codegen_env *cgenv, - struct sieve_command_context *ctx ATTR_UNUSED) +(const struct sieve_codegen_env *cgenv, + struct sieve_command_context *ctx ATTR_UNUSED) { sieve_operation_emit_code(cgenv->sbin, &cmd_discard_operation, -1); @@ -123,7 +129,7 @@ static bool cmd_discard_operation_execute } /* - * Action + * Action implementation */ static void act_discard_print diff --git a/src/lib-sieve/cmd-if.c b/src/lib-sieve/cmd-if.c index 5a56dd315..8e14c6bd1 100644 --- a/src/lib-sieve/cmd-if.c +++ b/src/lib-sieve/cmd-if.c @@ -1,3 +1,6 @@ +/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file + */ + #include "sieve-commands.h" #include "sieve-commands-private.h" #include "sieve-validator.h" @@ -5,22 +8,21 @@ #include "sieve-code.h" #include "sieve-binary.h" -/* Predeclarations */ - -static bool cmd_if_validate - (struct sieve_validator *validator, struct sieve_command_context *cmd); -static bool cmd_elsif_validate - (struct sieve_validator *validator, struct sieve_command_context *cmd); -static bool cmd_if_generate - (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); -static bool cmd_else_generate - (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); +/* + * Commands + */ /* If command * * Syntax: * if <test1: test> <block1: block> */ + +static bool cmd_if_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); +static bool cmd_if_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); + const struct sieve_command cmd_if = { "if", SCT_COMMAND, @@ -36,6 +38,10 @@ const struct sieve_command cmd_if = { * Santax: * elsif <test2: test> <block2: block> */ + +static bool cmd_elsif_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); + const struct sieve_command cmd_elsif = { "elsif", SCT_COMMAND, @@ -51,6 +57,10 @@ const struct sieve_command cmd_elsif = { * Syntax: * else <block> */ + +static bool cmd_else_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); + const struct sieve_command cmd_else = { "else", SCT_COMMAND, @@ -61,7 +71,9 @@ const struct sieve_command cmd_else = { NULL }; -/* Context */ +/* + * Context management + */ struct cmd_if_context_data { struct cmd_if_context_data *previous; @@ -72,36 +84,40 @@ struct cmd_if_context_data { }; static void cmd_if_initialize_context_data - (struct sieve_command_context *cmd, struct cmd_if_context_data *previous) +(struct sieve_command_context *cmd, struct cmd_if_context_data *previous) { struct cmd_if_context_data *ctx_data; /* Assign context */ ctx_data = p_new(sieve_command_pool(cmd), struct cmd_if_context_data, 1); - ctx_data->previous = previous; - ctx_data->next = NULL; ctx_data->exit_jump = 0; ctx_data->jump_generated = FALSE; - + + /* Update linked list of contexts */ + ctx_data->previous = previous; + ctx_data->next = NULL; if ( previous != NULL ) previous->next = ctx_data; + /* Assign to command context */ cmd->data = ctx_data; } -/* Validation */ +/* + * Validation + */ static bool cmd_if_validate - (struct sieve_validator *validator ATTR_UNUSED, - struct sieve_command_context *cmd) -{ +(struct sieve_validator *validator ATTR_UNUSED, struct sieve_command_context *cmd) +{ + /* Start if-command structure */ cmd_if_initialize_context_data(cmd, NULL); return TRUE; } static bool cmd_elsif_validate - (struct sieve_validator *validator, struct sieve_command_context *cmd) +(struct sieve_validator *validator, struct sieve_command_context *cmd) { struct sieve_command_context *prev_context = sieve_command_prev_context(cmd); @@ -125,13 +141,23 @@ static bool cmd_elsif_validate return TRUE; } -/* Code generation */ +/* + * Code generation + */ + +/* The if command does not generate specific IF-ELSIF-ELSE opcodes, but only uses + * JMP instructions. This is why the implementation of the if command does not + * include an opcode implementation. + */ static void cmd_if_resolve_exit_jumps - (struct sieve_binary *sbin, struct cmd_if_context_data *ctx_data) +(struct sieve_binary *sbin, struct cmd_if_context_data *ctx_data) { struct cmd_if_context_data *if_ctx = ctx_data->previous; + /* Iterate backwards through all if-command contexts and resolve the + * exit jumps to the current code position. + */ while ( if_ctx != NULL ) { if ( if_ctx->jump_generated ) sieve_binary_resolve_offset(sbin, if_ctx->exit_jump); @@ -154,7 +180,7 @@ static bool cmd_if_generate test = sieve_ast_test_first(ctx->ast_node); sieve_generate_test(cgenv, test, &jmplist, FALSE); - /* Case true { } */ + /* Case true { */ sieve_generate_block(cgenv, ctx->ast_node); /* Are we the final command in this if-elsif-else structure? */ @@ -185,10 +211,10 @@ static bool cmd_else_generate { struct cmd_if_context_data *ctx_data = (struct cmd_if_context_data *) ctx->data; - /* Else */ + /* Else { */ sieve_generate_block(cgenv, ctx->ast_node); - /* End: resolve all exit blocks */ + /* } End: resolve all exit blocks */ cmd_if_resolve_exit_jumps(cgenv->sbin, ctx_data); return TRUE; diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c index 07ce8f04f..355318033 100644 --- a/src/lib-sieve/cmd-keep.c +++ b/src/lib-sieve/cmd-keep.c @@ -1,3 +1,6 @@ +/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file + */ + #include "lib.h" #include "sieve-commands.h" @@ -10,24 +13,17 @@ #include "sieve-interpreter.h" #include "sieve-result.h" -/* Forward declarations */ - -static bool cmd_keep_operation_dump - (const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address); -static bool cmd_keep_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); +/* + * Keep command + * + * Syntax: + * keep + */ static bool cmd_keep_generate (const struct sieve_codegen_env *cgenv, - struct sieve_command_context *ctx ATTR_UNUSED); - -/* Keep command - * - * Syntax - * keep - */ + struct sieve_command_context *ctx); + const struct sieve_command cmd_keep = { "keep", SCT_COMMAND, @@ -37,7 +33,16 @@ const struct sieve_command cmd_keep = { NULL }; -/* Keep operation */ +/* + * Keep operation + */ + +static bool cmd_keep_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool cmd_keep_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_operation cmd_keep_operation = { "KEEP", @@ -48,13 +53,14 @@ const struct sieve_operation cmd_keep_operation = { }; /* - * Generation + * Code generation */ static bool cmd_keep_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx ATTR_UNUSED) { + /* Emit opcode */ sieve_operation_emit_code(cgenv->sbin, &cmd_keep_operation, -1); /* Emit line number */ @@ -100,9 +106,11 @@ static bool cmd_keep_operation_execute if ( !sieve_code_source_line_read(renv, address, &source_line) ) return FALSE; + /* Optional operands (side effects only) */ if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) ) return FALSE; + /* Add store action (sieve-actions.h) to result */ if ( renv->scriptenv != NULL && renv->scriptenv->inbox != NULL ) ret = sieve_act_store_add_to_result (renv, slist, renv->scriptenv->inbox, source_line); diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 58a5c4ade..9c282a3be 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -1,3 +1,6 @@ +/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file + */ + #include "lib.h" #include "ioloop.h" #include "str-sanitize.h" @@ -17,30 +20,24 @@ #include <stdio.h> -/* Config */ +/* + * Configuration + */ #define CMD_REDIRECT_DUPLICATE_KEEP (3600 * 24) -/* Forward declarations */ - -static bool cmd_redirect_operation_dump - (const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address); -static bool cmd_redirect_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); +/* + * Redirect command + * + * Syntax + * redirect <address: string> + */ static bool cmd_redirect_validate (struct sieve_validator *validator, struct sieve_command_context *cmd); static bool cmd_redirect_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); -/* Redirect command - * - * Syntax - * redirect <address: string> - */ - const struct sieve_command cmd_redirect = { "redirect", SCT_COMMAND, @@ -51,7 +48,16 @@ const struct sieve_command cmd_redirect = { NULL }; -/* Redirect operation */ +/* + * Redirect operation + */ + +static bool cmd_redirect_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool cmd_redirect_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_operation cmd_redirect_operation = { "REDIRECT", @@ -61,7 +67,9 @@ const struct sieve_operation cmd_redirect_operation = { cmd_redirect_operation_execute }; -/* Redirect action */ +/* + * Redirect action + */ static int act_redirect_check_duplicate (const struct sieve_runtime_env *renv, @@ -71,13 +79,9 @@ static void act_redirect_print (const struct sieve_action *action, const struct sieve_result_print_env *rpenv, 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, bool *keep); + (const struct sieve_action *action, const struct sieve_action_exec_env *aenv, + void *tr_context, bool *keep); -struct act_redirect_context { - const char *to_address; -}; - const struct sieve_action act_redirect = { "redirect", SIEVE_ACTFLAG_TRIES_DELIVER, @@ -89,14 +93,21 @@ const struct sieve_action act_redirect = { NULL }; -/* Validation */ +struct act_redirect_context { + const char *to_address; +}; + +/* + * Validation + */ static bool cmd_redirect_validate - (struct sieve_validator *validator, struct sieve_command_context *cmd) +(struct sieve_validator *validator, struct sieve_command_context *cmd) { struct sieve_ast_argument *arg = cmd->first_positional; - /* Check argument */ + /* Check and activate address argument */ + if ( !sieve_validate_positional_argument (validator, cmd, arg, "address", 1, SAAT_STRING) ) { return FALSE; @@ -105,12 +116,17 @@ static bool cmd_redirect_validate if ( !sieve_validator_argument_activate(validator, cmd, arg, FALSE) ) return FALSE; + /* We can only assess the validity of the outgoing address when it is + * a string literal. For runtime-generated strings this needs to be + * done at runtime + */ if ( sieve_argument_is_string_literal(arg) ) { string_t *address = sieve_ast_argument_str(arg); const char *error; const char *norm_address; T_BEGIN { + /* Verify and normalize the address to 'local_part@domain' */ norm_address = sieve_address_normalize(address, &error); if ( norm_address == NULL ) { @@ -118,6 +134,7 @@ static bool cmd_redirect_validate "specified redirect address '%s' is invalid: %s", str_c(address), error); } else { + /* Replace string literal in AST */ sieve_ast_argument_string_setc(arg, norm_address); } } T_END; @@ -129,7 +146,7 @@ static bool cmd_redirect_validate } /* - * Generation + * Code generation */ static bool cmd_redirect_generate @@ -141,10 +158,7 @@ static bool cmd_redirect_generate sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(ctx)); /* Generate arguments */ - if ( !sieve_generate_arguments(cgenv, ctx, NULL) ) - return FALSE; - - return TRUE; + return sieve_generate_arguments(cgenv, ctx, NULL); } /* @@ -165,8 +179,7 @@ static bool cmd_redirect_operation_dump if ( !sieve_code_dumper_print_optional_operands(denv, address) ) return FALSE; - return - sieve_opr_string_dump(denv, address); + return sieve_opr_string_dump(denv, address); } /* @@ -188,19 +201,25 @@ static bool cmd_redirect_operation_execute if ( !sieve_code_source_line_read(renv, address, &source_line) ) return FALSE; + /* Optional operands (side effects) */ if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) ) return FALSE; t_push(); + /* Read the address */ if ( !sieve_opr_string_read(renv, address, &redirect) ) { t_pop(); return FALSE; } + /* FIXME: perform address normalization if the string is not a string literal + */ + sieve_runtime_trace(renv, "REDIRECT action (\"%s\")", str_c(redirect)); /* Add redirect action to the result */ + pool = sieve_result_pool(renv->result); act = p_new(pool, struct act_redirect_context, 1); act->to_address = p_strdup(pool, str_c(redirect)); @@ -213,7 +232,7 @@ static bool cmd_redirect_operation_execute } /* - * Action + * Action implementation */ static int act_redirect_check_duplicate @@ -225,6 +244,7 @@ static int act_redirect_check_duplicate struct act_redirect_context *ctx1 = (struct act_redirect_context *) context1; struct act_redirect_context *ctx2 = (struct act_redirect_context *) context2; + /* Address is already normalized, strcmp suffices to assess duplicates */ if ( strcmp(ctx1->to_address, ctx2->to_address) == 0 ) return 1; @@ -243,7 +263,7 @@ static void act_redirect_print } static bool act_redirect_send - (const struct sieve_action_exec_env *aenv, struct act_redirect_context *ctx) +(const struct sieve_action_exec_env *aenv, struct act_redirect_context *ctx) { const struct sieve_message_data *msgdata = aenv->msgdata; const struct sieve_script_env *senv = aenv->scriptenv; @@ -264,18 +284,22 @@ static bool act_redirect_send if (mail_get_stream(msgdata->mail, NULL, NULL, &input) < 0) return -1; - smtp_handle = senv->smtp_open(ctx->to_address, msgdata->return_path, &f); + /* Open SMTP transport */ + smtp_handle = senv->smtp_open(ctx->to_address, msgdata->return_path, &f); - input = i_stream_create_header_filter - (input, HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR, hide_headers, - N_ELEMENTS(hide_headers), null_header_filter_callback, NULL); + /* Remove unwanted headers */ + input = i_stream_create_header_filter + (input, HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR, hide_headers, + N_ELEMENTS(hide_headers), null_header_filter_callback, NULL); + /* Pipe the message to the outgoing SMTP transport */ while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) { if (fwrite(data, size, 1, f) == 0) break; i_stream_skip(input, size); } + /* Close SMTP transport */ return senv->smtp_close(smtp_handle); } @@ -312,7 +336,9 @@ static bool act_redirect_commit sieve_result_log(aenv, "forwarded to <%s>", str_sanitize(ctx->to_address, 80)); + /* Cancel implicit keep */ *keep = FALSE; + return TRUE; } diff --git a/src/lib-sieve/cmd-require.c b/src/lib-sieve/cmd-require.c index 134f64f77..2bc45d948 100644 --- a/src/lib-sieve/cmd-require.c +++ b/src/lib-sieve/cmd-require.c @@ -1,3 +1,6 @@ +/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file + */ + #include "lib.h" #include "sieve-commands.h" @@ -6,14 +9,8 @@ #include "sieve-validator.h" #include "sieve-generator.h" -/* Types */ - -struct cmd_require_context_data { - struct sieve_ast_argument *arg; - struct sieve_extension *extension; -}; - -/* Require command +/* + * Require command * * Syntax * Syntax: require <capabilities: string-list> @@ -34,7 +31,9 @@ const struct sieve_command cmd_require = { NULL }; -/* Command validation */ +/* + * Validation + */ static bool cmd_require_validate (struct sieve_validator *validator, struct sieve_command_context *cmd) @@ -54,10 +53,10 @@ static bool cmd_require_validate "at the beginning of the file"); return FALSE; } - - arg = cmd->first_positional; /* Check argument and load specified extension(s) */ + + arg = cmd->first_positional; if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { /* Single string */ int ext_id = sieve_validator_extension_load @@ -91,7 +90,9 @@ static bool cmd_require_validate return result; } -/* Command code generation */ +/* + * Code generation + */ static bool cmd_require_generate (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) @@ -99,6 +100,7 @@ static bool cmd_require_generate struct sieve_ast_argument *arg = ctx->first_positional; if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ int ext_id = (int) arg->context; sieve_generator_link_extension(cgenv->gentr, ext_id); -- GitLab