diff --git a/src/lib-sieve/plugins/imap4flags/cmd-flag.c b/src/lib-sieve/plugins/imap4flags/cmd-flag.c index 13e43100ed4e743a47375d53c0ee6040691587d5..0fbde66ce7599238afb79e620904ed6ba1bebb5e 100644 --- a/src/lib-sieve/plugins/imap4flags/cmd-flag.c +++ b/src/lib-sieve/plugins/imap4flags/cmd-flag.c @@ -241,17 +241,7 @@ static int cmd_flag_operation_execute i_unreached(); } - /* Iterate through all flags and perform requested operation */ + /* Perform requested operation */ - while ( (ret=sieve_stringlist_next_item(flag_list, &flag_item)) > 0 ) { - if ( (ret=flag_op(renv, storage, var_index, flag_item)) <= 0) - return ret; - } - - if ( ret < 0 ) { - sieve_runtime_trace_error(renv, "invalid flag-list item"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - return SIEVE_EXEC_OK; + return flag_op(renv, storage, var_index, flag_list); } diff --git a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c index 771455247007174e2fd8f467ba35fb3c05caf4b0..3c42ebe6d1f3054634a237b036274c3befd8e605 100644 --- a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +++ b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c @@ -457,27 +457,43 @@ static void flags_list_set_flags flags_list_add_flags(flags_list, flags); } +static void flags_list_clear_flags +(string_t *flags_list) +{ + str_truncate(flags_list, 0); +} + int ext_imap4flags_set_flags (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, - unsigned int var_index, string_t *flags) + unsigned int var_index, struct sieve_stringlist *flags) { string_t *cur_flags; if ( storage != NULL ) { if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) ) return SIEVE_EXEC_BIN_CORRUPT; - } else + } else { cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); + } + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; - if ( cur_flags != NULL ) - flags_list_set_flags(cur_flags, flags); + flags_list_clear_flags(cur_flags); + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + flags_list_add_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + } return SIEVE_EXEC_OK; } int ext_imap4flags_add_flags (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, - unsigned int var_index, string_t *flags) + unsigned int var_index, struct sieve_stringlist *flags) { string_t *cur_flags; @@ -486,16 +502,24 @@ int ext_imap4flags_add_flags return SIEVE_EXEC_BIN_CORRUPT; } else cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); - - if ( cur_flags != NULL ) - flags_list_add_flags(cur_flags, flags); - - return SIEVE_EXEC_OK; + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + flags_list_add_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; } int ext_imap4flags_remove_flags (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, - unsigned int var_index, string_t *flags) + unsigned int var_index, struct sieve_stringlist *flags) { string_t *cur_flags; @@ -505,8 +529,16 @@ int ext_imap4flags_remove_flags } else cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); - if ( cur_flags != NULL ) - flags_list_remove_flags(cur_flags, flags); + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + flags_list_remove_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + } return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h index 5e4140a36797c763b0015c1fc172018bd7a19c2e..9194463c8aa1948b4fd478ac3e1c3e0ed5a7ee71 100644 --- a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h +++ b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h @@ -90,17 +90,17 @@ const char *ext_imap4flags_iter_get_flag 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); + unsigned int var_index, struct sieve_stringlist *flags); int ext_imap4flags_set_flags (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, - unsigned int var_index, string_t *flags); + unsigned int var_index, struct sieve_stringlist *flags); int ext_imap4flags_add_flags (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, - unsigned int var_index, string_t *flags); + unsigned int var_index, struct sieve_stringlist *flags); int ext_imap4flags_remove_flags (const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, - unsigned int var_index, string_t *flags); + unsigned int var_index, struct sieve_stringlist *flags); /* Flags access */ diff --git a/tests/extensions/imap4flags/basic.svtest b/tests/extensions/imap4flags/basic.svtest index ec94ca18f167bf0a73dc100bdf3d55ece896738f..874c40de5b4a0895822dc59413f7f720a2aa3966 100644 --- a/tests/extensions/imap4flags/basic.svtest +++ b/tests/extensions/imap4flags/basic.svtest @@ -104,6 +104,30 @@ test "Flag operations" { } } +test "Setflag; string list" { + setflag ["A B", "C D"]; + + if not hasflag "A" { + test_fail "hasflag misses A flag"; + } + + if not hasflag "B" { + test_fail "hasflag misses B flag"; + } + + if not hasflag "C" { + test_fail "hasflag misses C flag"; + } + + if not hasflag "D" { + test_fail "hasflag misses D flag"; + } + + if hasflag :comparator "i;ascii-numeric" :count "ne" "4" { + test_fail "hasflag sees incorrect number of flags"; + } +} + test "Removal: one" { setflag "\\seen";