diff --git a/TODO b/TODO index 53f6f693c8b11f8c4be0be1eb8b0209ff8132c2e..199916f6561ba2aad7c57d291f1882a2737848ef 100644 --- a/TODO +++ b/TODO @@ -9,8 +9,6 @@ Next (in order of descending priority/precedence): * Improve error handling. Now it is not very consistent, especially for the sieve command line tools and multiscript. -* Imapflags: merge execution of setflags, removeflags and addflags into one - common implementation. * Implement dropping errors in the user's mailbox as a mail message. * Fix remaining RFC deviations: - Fix issues listed in doc/rfc/RFC-questions.txt based on answers diff --git a/src/lib-sieve/plugins/imapflags/Makefile.am b/src/lib-sieve/plugins/imapflags/Makefile.am index eee48e7a29be481d8d98c750018631505a3e6ad8..0ac8bb48b6db5f490878459324107b57cdc32ade 100644 --- a/src/lib-sieve/plugins/imapflags/Makefile.am +++ b/src/lib-sieve/plugins/imapflags/Makefile.am @@ -8,12 +8,10 @@ AM_CPPFLAGS = \ -I$(dovecot_incdir)/src/lib-mail \ -I$(dovecot_incdir)/src/lib-storage -cmds = \ - cmd-setflag.c \ - cmd-addflag.c \ - cmd-removeflag.c +commands = \ + cmd-flag.c -tsts = \ +tests = \ tst-hasflag.c tags = \ @@ -21,8 +19,8 @@ tags = \ libsieve_ext_imapflags_la_SOURCES = \ ext-imapflags-common.c \ - $(cmds) \ - $(tsts) \ + $(commands) \ + $(tests) \ $(tags) \ ext-imapflags.c diff --git a/src/lib-sieve/plugins/imapflags/cmd-addflag.c b/src/lib-sieve/plugins/imapflags/cmd-addflag.c deleted file mode 100644 index fada6c57aab96b0f13eefbffa887d866c4a05995..0000000000000000000000000000000000000000 --- a/src/lib-sieve/plugins/imapflags/cmd-addflag.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file - */ - -#include "lib.h" - -#include "sieve-commands.h" -#include "sieve-code.h" -#include "sieve-validator.h" -#include "sieve-generator.h" -#include "sieve-interpreter.h" - -#include "ext-imapflags-common.h" - -/* - * Addflag command - * - * Syntax: - * addflag [<variablename: string>] <list-of-flags: string-list> - */ - -static bool cmd_addflag_generate - (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); - -const struct sieve_command cmd_addflag = { - "addflag", - SCT_COMMAND, - -1, /* We check positional arguments ourselves */ - 0, FALSE, FALSE, - NULL, NULL, - ext_imapflags_command_validate, - cmd_addflag_generate, - NULL -}; - -/* - * Addflag operation - */ - -static int cmd_addflag_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); - -const struct sieve_operation addflag_operation = { - "ADDFLAG", - &imapflags_extension, - EXT_IMAPFLAGS_OPERATION_ADDFLAG, - ext_imapflags_command_operation_dump, - cmd_addflag_operation_execute -}; - -/* - * Code generation - */ - -static bool cmd_addflag_generate - (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) -{ - sieve_operation_emit_code(cgenv->sbin, &addflag_operation); - - /* Generate arguments */ - if ( !sieve_generate_arguments(cgenv, ctx, NULL) ) - return FALSE; - - return TRUE; -} - -/* - * Execution - */ - -static int cmd_addflag_operation_execute -(const struct sieve_operation *op ATTR_UNUSED, - const struct sieve_runtime_env *renv, sieve_size_t *address) -{ - bool result = TRUE; - string_t *flag_item; - struct sieve_coded_stringlist *flag_list; - struct sieve_variable_storage *storage; - unsigned int var_index; - int ret; - - if ( (ret=ext_imapflags_command_operands_read - (renv, address, &flag_list, &storage, &var_index)) <= 0 ) - return ret; - - sieve_runtime_trace(renv, "ADDFLAG command"); - - /* Iterate through all added flags */ - while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && - flag_item != NULL ) { - - if ( (ret=ext_imapflags_add_flags(renv, storage, var_index, flag_item)) <= 0 ) - return ret; - } - - if ( !result ) { - sieve_runtime_trace_error(renv, "invalid flag-list item"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - return SIEVE_EXEC_OK; -} diff --git a/src/lib-sieve/plugins/imapflags/cmd-flag.c b/src/lib-sieve/plugins/imapflags/cmd-flag.c new file mode 100644 index 0000000000000000000000000000000000000000..8722134f39ac15a7d8b91df9395868edf18291fd --- /dev/null +++ b/src/lib-sieve/plugins/imapflags/cmd-flag.c @@ -0,0 +1,264 @@ +/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-imapflags-common.h" + +/* + * Commands + */ + +/* Forward declarations */ + +static bool cmd_flag_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); + +/* Setflag command + * + * Syntax: + * setflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command cmd_setflag = { + "setflag", + SCT_COMMAND, + -1, /* We check positional arguments ourselves */ + 0, FALSE, FALSE, + NULL, NULL, + ext_imapflags_command_validate, + cmd_flag_generate, + NULL +}; + +/* Addflag command + * + * Syntax: + * addflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command cmd_addflag = { + "addflag", + SCT_COMMAND, + -1, /* We check positional arguments ourselves */ + 0, FALSE, FALSE, + NULL, NULL, + ext_imapflags_command_validate, + cmd_flag_generate, + NULL +}; + + +/* Removeflag command + * + * Syntax: + * removeflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command cmd_removeflag = { + "removeflag", + SCT_COMMAND, + -1, /* We check positional arguments ourselves */ + 0, FALSE, FALSE, + NULL, NULL, + ext_imapflags_command_validate, + cmd_flag_generate, + NULL +}; + +/* + * Operations + */ + +/* Forward declarations */ + +bool cmd_flag_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_flag_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Setflag operation */ + +const struct sieve_operation setflag_operation = { + "SETFLAG", + &imapflags_extension, + EXT_IMAPFLAGS_OPERATION_SETFLAG, + cmd_flag_operation_dump, + cmd_flag_operation_execute +}; + +/* Addflag operation */ + +const struct sieve_operation addflag_operation = { + "ADDFLAG", + &imapflags_extension, + EXT_IMAPFLAGS_OPERATION_ADDFLAG, + cmd_flag_operation_dump, + cmd_flag_operation_execute +}; + +/* Removeflag operation */ + +const struct sieve_operation removeflag_operation = { + "REMOVEFLAG", + &imapflags_extension, + EXT_IMAPFLAGS_OPERATION_REMOVEFLAG, + cmd_flag_operation_dump, + cmd_flag_operation_execute +}; + +/* + * Code generation + */ + +static bool cmd_flag_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) +{ + const struct sieve_command *command = ctx->command; + + /* Emit operation */ + if ( command == &cmd_setflag ) + sieve_operation_emit_code(cgenv->sbin, &setflag_operation); + else if ( command == &cmd_addflag ) + sieve_operation_emit_code(cgenv->sbin, &addflag_operation); + else if ( command == &cmd_removeflag ) + sieve_operation_emit_code(cgenv->sbin, &removeflag_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, ctx, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +bool cmd_flag_operation_dump +(const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct sieve_operand *operand; + + sieve_code_dumpf(denv, "%s", op->mnemonic); + sieve_code_descend(denv); + + sieve_code_mark(denv); + operand = sieve_operand_read(denv->sbin, address); + + if ( sieve_operand_is_variable(operand) ) { + return + sieve_opr_string_dump_data(denv, operand, address, + "variable name") && + sieve_opr_stringlist_dump(denv, address, + "list of flags"); + } + + return + sieve_opr_stringlist_dump_data(denv, operand, address, + "list of flags"); +} + +/* + * Code execution + */ + +static int cmd_flag_operation_execute +(const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operand *operand; + sieve_size_t op_address = *address; + bool result = TRUE; + string_t *flag_item; + struct sieve_coded_stringlist *flag_list; + struct sieve_variable_storage *storage; + unsigned int var_index; + ext_imapflag_flag_operation_t flag_op; + int ret; + + /* + * Read operands + */ + + operand = sieve_operand_read(renv->sbin, address); + if ( operand == NULL ) { + sieve_runtime_trace_error(renv, "invalid operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( sieve_operand_is_variable(operand) ) { + + /* Read the variable operand */ + if ( !sieve_variable_operand_read_data + (renv, operand, address, &storage, &var_index) ) { + sieve_runtime_trace_error(renv, "invalid variable operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Read flag list */ + if ( (flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { + sieve_runtime_trace_error(renv, "invalid flag-list operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + } else if ( sieve_operand_is_stringlist(operand) ) { + storage = NULL; + var_index = 0; + + /* Read flag list */ + if ( (flag_list=sieve_opr_stringlist_read_data + (renv, operand, op_address, address)) == NULL ) { + sieve_runtime_trace_error(renv, "invalid flag-list operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + } else { + sieve_runtime_trace_error(renv, "unexpected operand '%s'", + operand->name); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, "%s command", op->mnemonic); + + /* Determine what to do */ + + if ( op == &setflag_operation ) + flag_op = ext_imapflags_set_flags; + else if ( op == &addflag_operation ) + flag_op = ext_imapflags_add_flags; + else if ( op == &removeflag_operation ) + flag_op = ext_imapflags_remove_flags; + else + i_unreached(); + + /* Iterate through all flags and perform requested operation */ + + while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && + flag_item != NULL ) { + + if ( (ret=flag_op(renv, storage, var_index, flag_item)) <= 0) + return ret; + } + + if ( !result ) { + sieve_runtime_trace_error(renv, "invalid flag-list item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; +} diff --git a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c deleted file mode 100644 index 65d0c74b69a10f7f23c89e7fd2874ca90603a503..0000000000000000000000000000000000000000 --- a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file - */ - -#include "lib.h" - -#include "sieve-code.h" -#include "sieve-commands.h" -#include "sieve-validator.h" -#include "sieve-generator.h" -#include "sieve-interpreter.h" - -#include "ext-imapflags-common.h" - -/* - * Removeflag command - * - * Syntax: - * removeflag [<variablename: string>] <list-of-flags: string-list> - */ - -static bool cmd_removeflag_generate - (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); - -const struct sieve_command cmd_removeflag = { - "removeflag", - SCT_COMMAND, - -1, /* We check positional arguments ourselves */ - 0, FALSE, FALSE, - NULL, NULL, - ext_imapflags_command_validate, - cmd_removeflag_generate, - NULL -}; - -/* - * Removeflag operation - */ - -static int cmd_removeflag_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); - -const struct sieve_operation removeflag_operation = { - "REMOVEFLAG", - &imapflags_extension, - EXT_IMAPFLAGS_OPERATION_REMOVEFLAG, - ext_imapflags_command_operation_dump, - cmd_removeflag_operation_execute -}; - -/* - * Code generation - */ - -static bool cmd_removeflag_generate -(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) -{ - sieve_operation_emit_code(cgenv->sbin, &removeflag_operation); - - /* Generate arguments */ - if ( !sieve_generate_arguments(cgenv, ctx, NULL) ) - return FALSE; - - return TRUE; -} - -/* - * Execution - */ - -static int cmd_removeflag_operation_execute -(const struct sieve_operation *op ATTR_UNUSED, - const struct sieve_runtime_env *renv, sieve_size_t *address) -{ - bool result = TRUE; - string_t *flag_item; - struct sieve_coded_stringlist *flag_list; - struct sieve_variable_storage *storage; - unsigned int var_index; - int ret; - - if ( (ret=ext_imapflags_command_operands_read - (renv, address, &flag_list, &storage, &var_index)) <= 0 ) - return ret; - - sieve_runtime_trace(renv, "REMOVEFLAG command"); - - /* Iterate through all flags to remove */ - while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && - flag_item != NULL ) { - - if ( (ret=ext_imapflags_remove_flags(renv, storage, var_index, flag_item)) <= 0) - return ret; - } - - if ( !result ) { - sieve_runtime_trace_error(renv, "invalid flag-list item"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - return SIEVE_EXEC_OK; -} diff --git a/src/lib-sieve/plugins/imapflags/cmd-setflag.c b/src/lib-sieve/plugins/imapflags/cmd-setflag.c deleted file mode 100644 index fb50cb03ad9a58855d8a75e094fa85e2ab07f817..0000000000000000000000000000000000000000 --- a/src/lib-sieve/plugins/imapflags/cmd-setflag.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file - */ - -#include "lib.h" - -#include "sieve-commands.h" -#include "sieve-code.h" -#include "sieve-validator.h" -#include "sieve-generator.h" -#include "sieve-interpreter.h" - -#include "ext-imapflags-common.h" - -/* - * Setflag command - * - * Syntax: - * setflag [<variablename: string>] <list-of-flags: string-list> - */ - -static bool cmd_setflag_generate - (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx); - -const struct sieve_command cmd_setflag = { - "setflag", - SCT_COMMAND, - -1, /* We check positional arguments ourselves */ - 0, FALSE, FALSE, - NULL, NULL, - ext_imapflags_command_validate, - cmd_setflag_generate, - NULL -}; - -/* - * Setflag operation - */ - -static int cmd_setflag_operation_execute - (const struct sieve_operation *op, - const struct sieve_runtime_env *renv, sieve_size_t *address); - -const struct sieve_operation setflag_operation = { - "SETFLAG", - &imapflags_extension, - EXT_IMAPFLAGS_OPERATION_SETFLAG, - ext_imapflags_command_operation_dump, - cmd_setflag_operation_execute -}; - -/* - * Code generation - */ - -static bool cmd_setflag_generate -(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) -{ - sieve_operation_emit_code(cgenv->sbin, &setflag_operation); - - /* Generate arguments */ - if ( !sieve_generate_arguments(cgenv, ctx, NULL) ) - return FALSE; - - return TRUE; -} - -/* - * Execution - */ - -static int cmd_setflag_operation_execute -(const struct sieve_operation *op ATTR_UNUSED, - const struct sieve_runtime_env *renv, sieve_size_t *address) -{ - bool result = TRUE; - string_t *flag_item; - struct sieve_coded_stringlist *flag_list; - struct sieve_variable_storage *storage; - unsigned int var_index; - int ret; - - if ( (ret=ext_imapflags_command_operands_read - (renv, address, &flag_list, &storage, &var_index)) <=0 ) - return ret; - - sieve_runtime_trace(renv, "SETFLAG command"); - - /* Iterate through all flags to set */ - while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && - flag_item != NULL ) { - - if ( (ret=ext_imapflags_set_flags(renv, storage, var_index, flag_item)) <= 0) - return ret; - } - - if ( !result ) { - sieve_runtime_trace_error(renv, "invalid flag-list item operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - return SIEVE_EXEC_OK; -} - diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c index 543c3a1b7c2721b9fd33e68866f0a2d8abdaabb8..485f784f343d2cbd87818d9b04ab808012fe5087 100644 --- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c @@ -138,82 +138,6 @@ bool ext_imapflags_command_validate return TRUE; } -bool ext_imapflags_command_operands_dump -(const struct sieve_dumptime_env *denv, sieve_size_t *address) -{ - const struct sieve_operand *operand; - - sieve_code_mark(denv); - operand = sieve_operand_read(denv->sbin, address); - - if ( sieve_operand_is_variable(operand) ) { - return - sieve_opr_string_dump_data(denv, operand, address, - "variable name") && - sieve_opr_stringlist_dump(denv, address, - "list of flags"); - } - - return - sieve_opr_stringlist_dump_data(denv, operand, address, - "list of flags"); -} - -bool ext_imapflags_command_operation_dump -(const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address) -{ - sieve_code_dumpf(denv, "%s", op->mnemonic); - sieve_code_descend(denv); - - return ext_imapflags_command_operands_dump(denv, address); -} - -int ext_imapflags_command_operands_read -(const struct sieve_runtime_env *renv, sieve_size_t *address, - struct sieve_coded_stringlist **flag_list, - struct sieve_variable_storage **storage, unsigned int *var_index) -{ - sieve_size_t op_address = *address; - const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address); - - if ( operand == NULL ) { - sieve_runtime_trace_error(renv, "invalid operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - if ( sieve_operand_is_variable(operand) ) { - /* Read the variable operand */ - if ( !sieve_variable_operand_read_data - (renv, operand, address, storage, var_index) ) { - sieve_runtime_trace_error(renv, "invalid variable operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - /* Read flag list */ - if ( (*flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid flag-list operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - } else if ( sieve_operand_is_stringlist(operand) ) { - *storage = NULL; - *var_index = 0; - - /* Read flag list */ - if ( (*flag_list=sieve_opr_stringlist_read_data - (renv, operand, op_address, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid flag-list operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - } else { - sieve_runtime_trace_error(renv, "unexpected operand '%s'", - operand->name); - return SIEVE_EXEC_BIN_CORRUPT; - } - - return SIEVE_EXEC_OK; -} - /* * Flags tag registration */ diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h index 9b1f256215454c9b862504a0f33fb60f17aada2a..8812dfc6166aa014bf42bc03ad0e00e3cfff868a 100644 --- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h +++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h @@ -62,17 +62,6 @@ extern const struct sieve_command tst_hasflag; bool ext_imapflags_command_validate (struct sieve_validator *validator, struct sieve_command_context *cmd); -bool ext_imapflags_command_operands_dump -(const struct sieve_dumptime_env *denv, sieve_size_t *address); -bool ext_imapflags_command_operation_dump -(const struct sieve_operation *op, - const struct sieve_dumptime_env *denv, sieve_size_t *address); - -int ext_imapflags_command_operands_read -( const struct sieve_runtime_env *renv, sieve_size_t *address, - struct sieve_coded_stringlist **flag_list, - struct sieve_variable_storage **storage, unsigned int *var_index); - /* * Flags tagged argument */ @@ -96,6 +85,10 @@ void ext_imapflags_iter_init const char *ext_imapflags_iter_get_flag (struct ext_imapflags_iter *iter); +typedef int (*ext_imapflag_flag_operation_t) + (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, + unsigned int var_index, string_t *flags); + int ext_imapflags_set_flags (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, unsigned int var_index, string_t *flags);