From: Timo Sirainen Date: Wed, 13 Mar 2024 20:11:43 +0000 (+0200) Subject: config: Change $setting parsing to use prefixed $SET:setting X-Git-Tag: 2.4.1~939 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb5dbe09b6c349e1774716896a4d84818028fed3;p=thirdparty%2Fdovecot%2Fcore.git config: Change $setting parsing to use prefixed $SET:setting This allows using $text in setting values without having to quote the line. --- diff --git a/src/config/config-parser.c b/src/config/config-parser.c index 07c68714ed..244d18ab65 100644 --- a/src/config/config-parser.c +++ b/src/config/config-parser.c @@ -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) diff --git a/src/config/test-config-parser.c b/src/config/test-config-parser.c index f52c883c99..5365c59e02 100644 --- a/src/config/test-config-parser.c +++ b/src/config/test-config-parser.c @@ -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");