From 0de2a195292b4b2a5154ec405e736f31c698d98e Mon Sep 17 00:00:00 2001 From: Stephan Bosch Date: Sat, 13 Feb 2016 00:40:48 +0100 Subject: [PATCH] lib-sieve: Implemented sieve_implicit_extensions setting. The extensions listed in this setting do not need to be enabled explicitly using the Sieve require command. This behavior voilates the standard, but is necessary for compatibility with some existing implementations of Sieve. Do not use this setting unless you really need to! --- src/lib-sieve/sieve-extensions.c | 57 +++++++++++++++++++++++--------- src/lib-sieve/sieve-extensions.h | 9 +++-- src/lib-sieve/sieve-validator.c | 10 ++++++ src/lib-sieve/sieve-validator.h | 3 +- src/lib-sieve/sieve.c | 2 +- 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index 67ef66bdd..7af86ff1b 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -273,13 +273,21 @@ void sieve_extensions_configure(struct sieve_instance *svinst) /* Apply sieve_extensions configuration */ - if ( (extensions=sieve_setting_get(svinst, "sieve_extensions")) != NULL ) - sieve_extensions_set_string(svinst, extensions, FALSE); + if ( (extensions=sieve_setting_get + (svinst, "sieve_extensions")) != NULL ) + sieve_extensions_set_string(svinst, extensions, FALSE, FALSE); /* Apply sieve_global_extensions configuration */ - if ( (extensions=sieve_setting_get(svinst, "sieve_global_extensions")) != NULL ) - sieve_extensions_set_string(svinst, extensions, TRUE); + if ( (extensions=sieve_setting_get + (svinst, "sieve_global_extensions")) != NULL ) + sieve_extensions_set_string(svinst, extensions, TRUE, FALSE); + + /* Apply sieve_implicit_extensions configuration */ + + if ( (extensions=sieve_setting_get + (svinst, "sieve_implicit_extensions")) != NULL ) + sieve_extensions_set_string(svinst, extensions, FALSE, TRUE); } void sieve_extensions_deinit(struct sieve_instance *svinst) @@ -494,13 +502,23 @@ void sieve_extension_override (*mod_ext)->overridden = TRUE; } -int sieve_extensions_get_count(struct sieve_instance *svinst) +unsigned int sieve_extensions_get_count(struct sieve_instance *svinst) { struct sieve_extension_registry *ext_reg = svinst->ext_reg; return array_count(&ext_reg->extensions); } +const struct sieve_extension *const * +sieve_extensions_get_all(struct sieve_instance *svinst, + unsigned int *count_r) +{ + struct sieve_extension_registry *ext_reg = svinst->ext_reg; + + return (const struct sieve_extension *const *) + array_get(&ext_reg->extensions, count_r); +} + const struct sieve_extension *sieve_extension_get_by_id (struct sieve_instance *svinst, unsigned int ext_id) { @@ -580,7 +598,6 @@ static void sieve_extension_set_enabled { if ( enabled ) { ext->enabled = TRUE; - ext->global = FALSE; if ( !ext->loaded ) { (void)_sieve_extension_load(ext); @@ -596,21 +613,27 @@ static void sieve_extension_set_global (struct sieve_extension *ext, bool enabled) { if ( enabled ) { - ext->enabled = TRUE; + sieve_extension_set_enabled(ext, TRUE); ext->global = TRUE; - - if ( !ext->loaded ) { - (void)_sieve_extension_load(ext); - } - - ext->loaded = TRUE; } else { ext->global = FALSE; } } +static void sieve_extension_set_implicit +(struct sieve_extension *ext, bool enabled) +{ + if ( enabled ) { + sieve_extension_set_enabled(ext, TRUE); + ext->implicit = TRUE; + } else { + ext->implicit = FALSE; + } +} + void sieve_extensions_set_string -(struct sieve_instance *svinst, const char *ext_string, bool global) +(struct sieve_instance *svinst, const char *ext_string, + bool global, bool implicit) { struct sieve_extension_registry *ext_reg = svinst->ext_reg; ARRAY(const struct sieve_extension *) enabled_extensions; @@ -623,7 +646,7 @@ void sieve_extensions_set_string bool relative = FALSE; if ( ext_string == NULL ) { - if ( global ) return; + if ( global || implicit ) return; /* Enable all */ exts = array_get_modifiable(&ext_reg->extensions, &ext_count); @@ -696,6 +719,8 @@ void sieve_extensions_set_string if ( relative ) { if ( global ) enabled = exts[i]->global; + else if ( implicit ) + enabled = exts[i]->implicit; else enabled = exts[i]->enabled; @@ -722,6 +747,8 @@ void sieve_extensions_set_string /* Perform actual activation/deactivation */ if ( global ) { sieve_extension_set_global(exts[i], enabled); + } else if ( implicit ) { + sieve_extension_set_implicit(exts[i], enabled); } else { sieve_extension_set_enabled(exts[i], enabled); } diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h index 6cf0529c1..760d44bb3 100644 --- a/src/lib-sieve/sieve-extensions.h +++ b/src/lib-sieve/sieve-extensions.h @@ -95,6 +95,7 @@ struct sieve_extension { unsigned int enabled:1; unsigned int dummy:1; unsigned int global:1; + unsigned int implicit:1; unsigned int overridden:1; }; @@ -142,7 +143,10 @@ void sieve_extension_override (struct sieve_instance *svinst, const char *name, const struct sieve_extension *ext); -int sieve_extensions_get_count(struct sieve_instance *svinst); +unsigned int sieve_extensions_get_count(struct sieve_instance *svinst); +const struct sieve_extension *const * +sieve_extensions_get_all(struct sieve_instance *svinst, + unsigned int *count_r); const struct sieve_extension *sieve_extension_get_by_id (struct sieve_instance *svinst, unsigned int ext_id); @@ -152,7 +156,8 @@ const struct sieve_extension *sieve_extension_get_by_name const char *sieve_extensions_get_string (struct sieve_instance *svinst); void sieve_extensions_set_string - (struct sieve_instance *svinst, const char *ext_string, bool global); + (struct sieve_instance *svinst, const char *ext_string, + bool global, bool implicit); const struct sieve_extension *sieve_get_match_type_extension (struct sieve_instance *svinst); diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index 58dceddb4..77ab8440c 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -1372,10 +1372,20 @@ static bool sieve_validate_block && !valdtr->finished_require && strcasecmp(cmd_node->identifier, cmd_require.identifier) != 0 ) { const struct sieve_validator_extension_reg *extrs; + const struct sieve_extension *const *exts; unsigned int ext_count, i; valdtr->finished_require = TRUE; + /* Load implicit extensions */ + exts = sieve_extensions_get_all(valdtr->svinst, &ext_count); + for (i = 0; i < ext_count; i++) { + if ( exts[i]->implicit ) { + (void)sieve_validator_extension_load + (valdtr, NULL, NULL, exts[i]); + } + } + /* Validate all 'require'd extensions */ extrs = array_get(&valdtr->extensions, &ext_count); for ( i = 0; i < ext_count; i++ ) { diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h index 3a350573e..857b7b2ff 100644 --- a/src/lib-sieve/sieve-validator.h +++ b/src/lib-sieve/sieve-validator.h @@ -138,7 +138,8 @@ struct sieve_validator_extension { bool sieve_validator_extension_load (struct sieve_validator *valdtr, struct sieve_command *cmd, - struct sieve_ast_argument *ext_arg, const struct sieve_extension *ext); + struct sieve_ast_argument *ext_arg, const struct sieve_extension *ext) + ATTR_NULL(2, 3); const struct sieve_extension *sieve_validator_extension_load_by_name (struct sieve_validator *valdtr, struct sieve_command *cmd, struct sieve_ast_argument *ext_arg, const char *ext_name); diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 5d28fd354..84fbc89d5 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -132,7 +132,7 @@ void sieve_deinit(struct sieve_instance **_svinst) void sieve_set_extensions (struct sieve_instance *svinst, const char *extensions) { - sieve_extensions_set_string(svinst, extensions, FALSE); + sieve_extensions_set_string(svinst, extensions, FALSE, FALSE); } const char *sieve_get_capabilities