]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveconf: Don't strip key prefix from output if it would result in conflicting wrong...
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 20 Mar 2024 12:25:54 +0000 (14:25 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:39:58 +0000 (10:39 +0200)
For example with:

dict proxy {
  dict_name = foo
  dict_proxy_name = bar
}

If "dict_name" was shortened to just "name", it would actually be parsed
as "dict_proxy_name" setting.

src/config/config-parser.c
src/config/config-parser.h
src/config/doveconf.c

index 1391afaab607c60e3c3900dc07ecb86217b31732..91b10c4ea4ddedc59e4306ec7d13274f06812560 100644 (file)
@@ -50,6 +50,7 @@ struct config_parsed {
        struct config_filter_parser *const *filter_parsers;
        struct config_module_parser *module_parsers;
        ARRAY_TYPE(const_string) errors;
+       HASH_TABLE(const char *, const struct setting_define *) key_hash;
 };
 
 ARRAY_DEFINE_TYPE(setting_parser_info_p, const struct setting_parser_info *);
@@ -2380,6 +2381,26 @@ config_module_parsers_get_setting(const struct config_module_parser *module_pars
        return str_c(str);
 }
 
+const struct setting_define *
+config_parsed_key_lookup(struct config_parsed *config, const char *key)
+{
+       const struct config_module_parser *l;
+       unsigned int key_idx;
+
+       if (hash_table_is_created(config->key_hash))
+               return hash_table_lookup(config->key_hash, key);
+       hash_table_create(&config->key_hash, config->pool, 0, str_hash, strcmp);
+
+       for (l = config->module_parsers; l->info != NULL; l++) {
+               for (key_idx = 0; l->info->defines[key_idx].key != NULL; key_idx++) {
+                       hash_table_update(config->key_hash,
+                                         l->info->defines[key_idx].key,
+                                         &l->info->defines[key_idx]);
+               }
+       }
+       return hash_table_lookup(config->key_hash, key);
+}
+
 void config_parsed_free(struct config_parsed **_config)
 {
        struct config_parsed *config = *_config;
@@ -2388,6 +2409,7 @@ void config_parsed_free(struct config_parsed **_config)
                return;
        *_config = NULL;
 
+       hash_table_destroy(&config->key_hash);
        pool_unref(&config->pool);
 }
 
index 295f6b1464eaf2318928a343f24e56a5f0c9eb5b..a29ec3d2e622b11cd806f726d4a599070695f23d 100644 (file)
@@ -91,6 +91,9 @@ void config_fill_set_parser(struct setting_parser_context *parser,
 const char *
 config_module_parsers_get_setting(const struct config_module_parser *module_parsers,
                                  const char *info_name, const char *key);
+/* Lookup setting with the specified key. */
+const struct setting_define *
+config_parsed_key_lookup(struct config_parsed *config, const char *key);
 void config_parsed_free(struct config_parsed **config);
 
 void config_parse_load_modules(void);
index cc0013a1fce98623b317c83ab21d7e71856ec045..0103c00d655021e9a2fa5756d5bdca7b87fe925e 100644 (file)
@@ -335,7 +335,29 @@ try_strip_prefix(const char **key_prefix, const char *strip_prefix,
                return;
        if (strip_prefix2 == NULL)
                return;
-       (void)str_begins(*key_prefix, strip_prefix2, key_prefix);
+
+       const char *suffix;
+       if (str_begins(*key_prefix, strip_prefix2, &suffix)) {
+               /* Prefix isn't stripped in all situations or it would result
+                  in wrong output. For example:
+
+                  *key_prefix = "dict_name"
+                  strip_prefix = "dict_proxy_"
+                  strip_prefix2 = "dict_"
+                  suffix = "name"
+
+                  Now if we return "name", it conflicts with "dict_proxy_name"
+                  setting. So if such conflicting setting name exists, don't
+                  strip the prefix.
+               */
+               const char *conflict_key =
+                       t_strconcat(strip_prefix, t_strcut(suffix, '='), NULL);
+               if (config_parsed_key_lookup(config, conflict_key) == NULL) {
+                       *key_prefix = suffix;
+                       return;
+               }
+
+       }
 }
 
 static void ATTR_NULL(4)