]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-settings, config: Support '/' in strlist and boollist keys
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 22 Dec 2023 15:24:28 +0000 (10:24 -0500)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:39:57 +0000 (10:39 +0200)
Use settings_section_[un]escape() for escaping.

src/config/config-dump-full.c
src/lib-settings/settings-parser.c
src/lib-settings/settings.c
src/lib-settings/test-settings-parser.c

index 7b307dd690743c917fd274ceecf8832341aafbfd..419385d5a71bab9877ea4f54d8d2bdea81706db0 100644 (file)
@@ -225,6 +225,11 @@ static void
 config_dump_full_stdout_callback(const struct config_export_setting *set,
                                 struct dump_context *ctx)
 {
+       if (set->type == CONFIG_KEY_LIST) {
+               /* these aren't needed */
+               return;
+       }
+
        if (!ctx->filter_written) {
                string_t *str = t_str_new(128);
                str_append(str, ":FILTER ");
@@ -234,8 +239,25 @@ config_dump_full_stdout_callback(const struct config_export_setting *set,
                ctx->filter_written = TRUE;
        }
        T_BEGIN {
-               o_stream_nsend_str(ctx->output, t_strdup_printf(
-                       "%s=%s\n", set->key, str_tabescape(set->value)));
+               const struct setting_define *def =
+                       &ctx->info->defines[set->key_define_idx];
+               if (def->type == SET_STRLIST || def->type == SET_BOOLLIST) {
+                       const char *suffix;
+                       if (!str_begins(set->key, def->key, &suffix) ||
+                           suffix[0] != '/')
+                               i_unreached();
+
+                       suffix++;
+                       o_stream_nsend_str(ctx->output,
+                                          t_strdup_until(set->key, suffix));
+                       o_stream_nsend_str(ctx->output,
+                                          settings_section_escape(suffix));
+               } else {
+                       o_stream_nsend_str(ctx->output, set->key);
+               }
+               o_stream_nsend_str(ctx->output, "=");
+               o_stream_nsend_str(ctx->output, str_tabescape(set->value));
+               o_stream_nsend_str(ctx->output, "\n");
        } T_END;
 }
 
@@ -278,7 +300,7 @@ static void config_dump_full_callback(const struct config_export_setting *set,
                            suffix[0] != '/')
                                i_unreached();
                        else {
-                               suffix++;
+                               suffix = settings_section_escape(suffix + 1);
                                o_stream_nsend(ctx->output, suffix,
                                               strlen(suffix) + 1);
                        }
index 19006bd388991534d61c0c5898add91edd6c0d89..1b156fb17c4b6a35a64fbd5c371c628b09afcb27 100644 (file)
@@ -284,7 +284,7 @@ settings_parse_strlist(struct setting_parser_context *ctx,
        key = strchr(key, SETTINGS_SEPARATOR);
        if (key == NULL)
                return;
-       key++;
+       key = settings_section_unescape(key + 1);
        vvalue = p_strdup(ctx->set_pool, value);
 
        if (!array_is_created(array))
@@ -338,7 +338,8 @@ int settings_parse_boollist_string(const char *value, pool_t pool,
                        }
 
                        if (quoted || str_len(elem) > 0) {
-                               elem_dup = p_strdup(pool, str_c(elem));
+                               elem_dup = p_strdup(pool,
+                                       settings_section_unescape(str_c(elem)));
                                array_push_back(dest, &elem_dup);
                                str_truncate(elem, 0);
                        }
@@ -368,7 +369,7 @@ int settings_parse_boollist_string(const char *value, pool_t pool,
                return -1;
        }
        if (quoted || str_len(elem) > 0) {
-               elem_dup = p_strdup(pool, str_c(elem));
+               elem_dup = settings_section_unescape(p_strdup(pool, str_c(elem)));
                array_push_back(dest, &elem_dup);
        }
        return 0;
@@ -421,7 +422,7 @@ settings_parse_boollist(struct setting_parser_context *ctx,
                boollist_null_terminate(array);
                return 0;
        }
-       key++;
+       key = settings_section_unescape(key + 1);
 
        bool value_bool;
        if (get_bool(ctx, value, &value_bool) < 0)
@@ -461,6 +462,7 @@ settings_parse(struct setting_parser_context *ctx,
        void *ptr;
        const void *ptr2;
        const char *error;
+       int ret;
 
        if (value == set_value_unknown) {
                /* setting value is unknown - preserve the exact pointer */
@@ -537,10 +539,15 @@ settings_parse(struct setting_parser_context *ctx,
                        return -1;
                break;
        case SET_STRLIST:
-               settings_parse_strlist(ctx, ptr, key, value);
+               T_BEGIN {
+                       settings_parse_strlist(ctx, ptr, key, value);
+               } T_END;
                break;
        case SET_BOOLLIST:
-               if (settings_parse_boollist(ctx, ptr, key, value) < 0)
+               T_BEGIN {
+                       ret = settings_parse_boollist(ctx, ptr, key, value);
+               } T_END;
+               if (ret < 0)
                        return -1;
                break;
        case SET_FILTER_ARRAY: {
index 6c86a410204128d905897958b32281ec75c1bc4f..b48a7b47a109c2dc9976f14073a181c232b6b24e 100644 (file)
@@ -633,7 +633,7 @@ settings_mmap_apply_blob(struct settings_apply_ctx *ctx,
                        offset += strlen(list_key)+1;
                        set_apply = set_apply &&
                                !settings_parse_list_has_key(ctx->parser,
-                                                            key_idx, list_key);
+                                       key_idx, settings_section_unescape(list_key));
                } else if (ctx->info->defines[key_idx].type == SET_FILTER_ARRAY)
                        set_apply = TRUE;
                else if (set_apply)
@@ -1390,7 +1390,8 @@ settings_instance_override(struct settings_apply_ctx *ctx,
                                   (invalid for strlist) */
                                i_assert(suffix[0] == '\0');
                        } else if (settings_parse_list_has_key(ctx->parser,
-                                               key_idx, suffix + 1))
+                                       key_idx,
+                                       settings_section_unescape(suffix + 1)))
                                continue;
                        else
                                track_seen = FALSE;
index 2618c6c31379a0322012ad8c232f17a6ab42bcb1..e4cb89c2424ecaa80719286134c8dc0fbb4442ec 100644 (file)
@@ -152,13 +152,15 @@ static void test_settings_parse_boollist_string(void)
                { "foo", (const char *const []) { "foo", NULL } },
                { "foo bar", (const char *const []) { "foo", "bar", NULL } },
                { "foo bar,baz", (const char *const []) { "foo", "bar", "baz", NULL } },
-               { ", foo, ,  b\\\\ar  ", (const char *const []) { "foo", "b\\\\ar", NULL } },
+               { ", foo, ,  b\\\\sa  ", (const char *const []) { "foo", "b\\sa", NULL } },
+               { ", a\\s\\e\\_\\+, ", (const char *const []) { "a/= ,", NULL } },
 
                { "\"\"", (const char *const []) { "", NULL } },
                { "\",.\"", (const char *const []) { ",.", NULL } },
-               { "\"esc\\\\str\"", (const char *const []) { "esc\\str", NULL } },
+               { "\"esc\\\\\\\\str\"", (const char *const []) { "esc\\str", NULL } },
                { "\"quotes\\\"str\"", (const char *const []) { "quotes\"str", NULL } },
                { "\"val1\", \"val2\" \"val3\"", (const char *const []) { "val1", "val2", "val3", NULL } },
+               { "\"a\\\\s\\\\e\\\\_\\\\+\"", (const char *const []) { "a/= ,", NULL } },
        };
        const struct {
                const char *input;