]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
config: Change $setting parsing to use prefixed $SET:setting
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 13 Mar 2024 20:11:43 +0000 (22:11 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Feb 2025 10:34:12 +0000 (12:34 +0200)
This allows using $text in setting values without having to quote the line.

src/config/config-parser.c
src/config/test-config-parser.c

index 07c68714eda8d9e9f0e2dc7c02277c73bf0bcdc1..244d18ab656d7b1312d8ca34d5cd2b8c1fa6072d 100644 (file)
@@ -1755,47 +1755,49 @@ static int config_write_keyvariable(struct config_parser_context *ctx,
                                    const char *key, const char *value,
                                    string_t *str)
 {
-       const char *var_end, *p_start = value;
+       const char *var_end;
        while (value != NULL) {
-               const char *var_name, *env_name;
-               bool expand_parent;
+               const char *var_name, *env_name, *set_name;
+               bool var_is_set, expand_parent;
                var_end = strchr(value, ' ');
 
-               /* expand_parent=TRUE for "key = $key stuff".
+               /* expand_parent=TRUE for "key = $SET:key stuff".
                   we'll always expand it so that doveconf -n can give
                   usable output */
                if (var_end == NULL)
                        var_name = value;
                else
                        var_name = t_strdup_until(value, var_end);
-               expand_parent = strcmp(key, var_name +
-                                      (*var_name == '$' ? 1 : 0)) == 0;
+               var_is_set = str_begins(var_name, "$SET:", &set_name);
+               expand_parent = var_is_set && strcmp(key, set_name) == 0;
 
-               if (!str_begins_with(var_name, "$") ||
-                   (value > p_start && !IS_WHITE(value[-1]))) {
-                       str_append(str, var_name);
-               } else if (!ctx->expand_values && !expand_parent) {
+               if (!ctx->expand_values && !expand_parent) {
                        str_append(str, var_name);
                } else if (str_begins(var_name, "$ENV:", &env_name)) {
                        /* use environment variable */
                        const char *envval = getenv(env_name);
                        if (envval != NULL)
                                str_append(str, envval);
-               } else {
+               } else if (var_is_set) {
                        struct config_parser_key *config_key;
 
-                       i_assert(var_name[0] == '$');
-                       var_name++;
-
-                       config_key = hash_table_lookup(ctx->all_keys, var_name);
-                       if (config_key == NULL ||
-                           !config_get_value(ctx->cur_section, config_key,
-                                             var_name, expand_parent, str)) {
+                       config_key = hash_table_lookup(ctx->all_keys, set_name);
+                       if (config_key == NULL) {
                                ctx->error = p_strconcat(ctx->pool,
-                                                        "Unknown variable: $",
-                                                        var_name, NULL);
+                                                        "Unknown setting: ",
+                                                        set_name, NULL);
+                               return -1;
+                       }
+                       if (!config_get_value(ctx->cur_section, config_key,
+                                             set_name, expand_parent, str)) {
+                               ctx->error = p_strdup_printf(ctx->pool,
+                                       "Failed to expand $SET:%s: "
+                                       "Setting type can't be expanded to string",
+                                       set_name);
                                return -1;
                        }
+               } else {
+                       str_append(str, var_name);
                }
 
                if (var_end == NULL)
index f52c883c9943d616902f9c4acd6a62a01debebe1..5365c59e02d2f1c668a4dc732e2e9d43d4505177 100644 (file)
@@ -97,20 +97,20 @@ static void test_config_parser(void)
 "# comment\n"
 "key=value\n"
 "key2 = \\$escape \\escape \\\"escape\\\"\n"
-"key3 = value\n"
-"key3 = $key3 nothervalue\n"
-"key3 = yetanother value $key3 right here\n"
-"key4 = \" $key3 \"\n"
-"key5 = ' $key4 '\n"
+"key3 = $value\n"
+"key3 = $SET:key3 nothervalue\n"
+"key3 = yetanother value $SET:key3 right here\n"
+"key4 = \" $SET:key3 \"\n"
+"key5 = ' $SET:key4 '\n"
 "pop3_deleted_flag = \"$Deleted\"\n"
 "env_key=$ENV:foo\n"
-"env_key=$env_key $ENV:bar\n"
-"env_key=$env_key \"$env_key\"\n"
+"env_key=$SET:env_key $ENV:bar\n"
+"env_key=$SET:env_key \"$SET:env_key\"\n"
 "env_key2 = foo$ENV:FOO bar\n"
 "env_key3 = $ENV:FOO$ENV:FOO bar\n"
-"env_key4 = $ENV:foo $ENV:bar $key\n"
+"env_key4 = $ENV:foo $ENV:bar $SET:key\n"
 "env_key5 = $ENV:foo $ENV:foo\n"
-"protocols = $protocols imap\n"
+"protocols = $SET:protocols imap\n"
        );
 
        putenv("foo=test1");
@@ -134,11 +134,11 @@ static void test_config_parser(void)
        const struct test_settings *set = settings_parser_get_set(set_parser);
        test_assert_strcmp(set->key, "value");
        test_assert_strcmp(set->key2, "\\$escape \\escape \\\"escape\\\"");
-       test_assert_strcmp(set->key3, "yetanother value value nothervalue right here");
-       test_assert_strcmp(set->key4, " $key3 ");
-       test_assert_strcmp(set->key5, " $key4 ");
+       test_assert_strcmp(set->key3, "yetanother value $value nothervalue right here");
+       test_assert_strcmp(set->key4, " $SET:key3 ");
+       test_assert_strcmp(set->key5, " $SET:key4 ");
        test_assert_strcmp(set->pop3_deleted_flag, "$Deleted");
-       test_assert_strcmp(set->env_key, "test1 test2 \"$env_key\"");
+       test_assert_strcmp(set->env_key, "test1 test2 \"$SET:env_key\"");
        test_assert_strcmp(set->env_key2, "foo$ENV:FOO bar");
        test_assert_strcmp(set->env_key3, "works bar");
        test_assert_strcmp(set->env_key4, "test1 test2 value");
@@ -160,14 +160,14 @@ static void test_config_parser(void)
 
        test_assert_strcmp(set->key, "value");
        test_assert_strcmp(set->key2, "\\$escape \\escape \\\"escape\\\"");
-       test_assert_strcmp(set->key3, "yetanother value value nothervalue right here");
-       test_assert_strcmp(set->key4, " $key3 ");
-       test_assert_strcmp(set->key5, " $key4 ");
+       test_assert_strcmp(set->key3, "yetanother value $value nothervalue right here");
+       test_assert_strcmp(set->key4, " $SET:key3 ");
+       test_assert_strcmp(set->key5, " $SET:key4 ");
        test_assert_strcmp(set->pop3_deleted_flag, "$Deleted");
-       test_assert_strcmp(set->env_key, "$ENV:foo $ENV:bar \"$env_key\"");
+       test_assert_strcmp(set->env_key, "$ENV:foo $ENV:bar \"$SET:env_key\"");
        test_assert_strcmp(set->env_key2, "foo$ENV:FOO bar");
        test_assert_strcmp(set->env_key3, "$ENV:FOO$ENV:FOO bar");
-       test_assert_strcmp(set->env_key4, "$ENV:foo $ENV:bar $key");
+       test_assert_strcmp(set->env_key4, "$ENV:foo $ENV:bar $SET:key");
        test_assert_strcmp(set->env_key5, "$ENV:foo $ENV:foo");
        test_assert_strcmp(set->protocols, "pop3 imap");