]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dict, global: Add dict named list filter and require using it
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Sat, 16 Mar 2024 11:00:07 +0000 (13:00 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:39:58 +0000 (10:39 +0200)
It's no longer possible to simply specify dict_driver setting without
dict named list filter. This makes it more consistent with lib-fs.

src/lib-dict-extra/test-dict-fs.c
src/lib-dict/dict.c
src/lib-dict/dict.h
src/lib-fs/fs-dict.c
src/lib-storage/mail-storage-settings.c
src/lib-storage/mailbox-attribute.c
src/plugins/acl/acl-settings.c
src/plugins/mail-crypt/test-mail-key.c
src/plugins/notify-status/notify-status-plugin.c
src/plugins/quota-clone/quota-clone-settings.c

index 5211936c20d07b3aadb9cadaa957e8a181e54d2f..d95b21b0f8617c86f5aedeff4bbb107ac48d1acd 100644 (file)
@@ -39,7 +39,8 @@ static void test_dict_fs_set_get(void)
        const char *error;
        struct dict *dict;
        const char *const settings[] = {
-               "dict_driver", "fs",
+               "dict", "fs",
+               "dict/fs/dict_driver", "fs",
                "fs", "posix",
                "fs/posix/fs_driver", "posix",
                "fs_posix_prefix", ".test-dict/",
index 99e2e8e00d3b27d203e2ba420302217c3ee00773..173e6e4d630d89df8353c94014f4070de07e23f0 100644 (file)
@@ -30,16 +30,24 @@ struct dict_lookup_callback_ctx {
        void *context;
 };
 
+static bool dict_settings_check(void *_set, pool_t pool, const char **error_r);
+
 #undef DEF
 #define DEF(type, name) \
        SETTING_DEFINE_STRUCT_##type(#name, name, struct dict_settings)
 static const struct setting_define dict_setting_defines[] = {
+       DEF(STR, dict_name),
        DEF(STR, dict_driver),
+       { .type = SET_FILTER_ARRAY, .key = "dict",
+         .offset = offsetof(struct dict_settings, dicts),
+         .filter_array_field_name = "dict_name", },
 
        SETTING_DEFINE_LIST_END
 };
 static const struct dict_settings dict_default_settings = {
+       .dict_name = "",
        .dict_driver = "",
+       .dicts = ARRAY_INIT,
 };
 const struct setting_parser_info dict_setting_parser_info = {
        .name = "dict",
@@ -49,6 +57,8 @@ const struct setting_parser_info dict_setting_parser_info = {
 
        .struct_size = sizeof(struct dict_settings),
        .pool_offset1 = 1 + offsetof(struct dict_settings, pool),
+
+       .check_func = dict_settings_check,
 };
 
 static ARRAY(struct dict *) dict_drivers;
@@ -154,6 +164,20 @@ int dict_init_legacy(const char *uri, const struct dict_legacy_settings *set,
        return 0;
 }
 
+static bool dict_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+                               const char **error_r ATTR_UNUSED)
+{
+       struct dict_settings *set = _set;
+
+       if (set->dict_driver[0] == '\0' && set->dict_name[0] != '\0') {
+               /* default an empty dict_driver to dict_name, so it's possible
+                  to configure simply: dict driver { .. }, but to still allow
+                  the same driver to be used multiple times if necessary. */
+               set->dict_driver = set->dict_name;
+       }
+       return TRUE;
+}
+
 int dict_init_auto(struct event *event, struct dict **dict_r,
                   const char **error_r)
 {
@@ -166,21 +190,44 @@ int dict_init_auto(struct event *event, struct dict **dict_r,
        if (settings_get(event, &dict_setting_parser_info, 0,
                         &dict_set, error_r) < 0)
                return -1;
-
-       if (dict_set->dict_driver[0] == '\0') {
-               *error_r = "dict_driver setting is empty";
+       if (array_is_empty(&dict_set->dicts)) {
+               *error_r = "dict { .. } named list filter is missing";
                settings_free(dict_set);
                return 0;
        }
+       const char *dict_name_first =
+               t_strdup(array_idx_elem(&dict_set->dicts, 0));
+       if (array_count(&dict_set->dicts) > 1) {
+               /* There are currently no dicts that support child dicts. */
+               const char *dict_name_extra =
+                       array_idx_elem(&dict_set->dicts, 1);
+               *error_r = t_strdup_printf(
+                       "Extra dict %s { .. } named list filter - "
+                       "the parent dict %s { .. } doesn't support a child dict",
+                       dict_name_extra, dict_name_first);
+               settings_free(dict_set);
+               return -1;
+       }
+
+       /* Get settings for the first dict list filter */
+       event = event_create(event);
+       event_add_str(event, "dict", dict_name_first);
+       settings_free(dict_set);
+       if (settings_get(event, &dict_setting_parser_info, 0,
+                        &dict_set, error_r) < 0) {
+               event_unref(&event);
+               return -1;
+       }
+
        dict_driver = dict_driver_lookup(dict_set->dict_driver);
        if (dict_driver == NULL) {
                *error_r = t_strdup_printf("Unknown dict module: %s",
                                           dict_set->dict_driver);
+               event_unref(&event);
                settings_free(dict_set);
                return -1;
        }
 
-       event = event_create(event);
        event_add_category(event, &event_category_dict);
        event_add_str(event, "driver", dict_driver->name);
        event_set_append_log_prefix(event, t_strdup_printf("dict(%s): ",
index 36fbd96cd627244c306cea330d00f95f167998b8..6e57aed7b484bc4093280db1557bc293bbfa988b 100644 (file)
@@ -39,7 +39,9 @@ struct dict_legacy_settings {
 
 struct dict_settings {
        pool_t pool;
+       const char *dict_name;
        const char *dict_driver;
+       ARRAY_TYPE(const_string) dicts;
 };
 extern const struct setting_parser_info dict_setting_parser_info;
 
index 69598cbd52f23afc09d78d1b15e20a91cad31665..415b816f3c2bd0b72430d19b56a40f96d15293cd 100644 (file)
@@ -113,7 +113,7 @@ fs_dict_init(struct fs *_fs, const struct fs_parameters *params ATTR_UNUSED,
        ret = dict_init_auto(event, &fs->dict, error_r);
        event_unref(&event);
        if (ret == 0)
-               *error_r = "fs_dict { dict_driver } not set";
+               *error_r = "fs_dict { dict { .. } } not set";
        return ret <= 0 ? -1 : 0;
 }
 
index 765ea455d4ee955f68747fff0c3c6045cc79ddb9..1283cd644fd31891c6ce623dd6fb7bed03b7a49f 100644 (file)
@@ -40,7 +40,7 @@ static const struct setting_define mail_storage_setting_defines[] = {
        DEF(SIZE, mail_ext_attachment_min_size),
        DEF(STR, mail_attachment_detection_options),
        { .type = SET_FILTER_NAME, .key = "mail_attribute",
-         .required_setting = "dict_driver", },
+         .required_setting = "dict", },
        DEF(UINT, mail_prefetch_count),
        DEF(STR, mail_cache_fields),
        DEF(STR, mail_always_cache_fields),
index a5273f6fc418124883fd5217afad868313819ff4..8d7a6322afdff3e805e10760e7cac276c8148b41 100644 (file)
@@ -483,7 +483,7 @@ int mailbox_attribute_dict_is_enabled(struct mail_user *user,
        event_set_ptr(event, SETTINGS_EVENT_FILTER_NAME, "mail_attribute");
        int ret = settings_get(event, &dict_setting_parser_info, 0,
                               &dict_set, error_r);
-       if (ret == 0 && dict_set->dict_driver[0] != '\0')
+       if (ret == 0 && array_not_empty(&dict_set->dicts))
                ret = 1;
        settings_free(dict_set);
        event_unref(&event);
index fafd8e0ed964c1490bdba4a4d81fa4786f8248ca..5e0ec86da62a8b918ef872ca4530fb181382b23e 100644 (file)
@@ -53,7 +53,7 @@ static const struct setting_define acl_setting_defines[] = {
        DEF(BOOL, acl_defaults_from_inbox),
        DEF(BOOL, acl_ignore),
        { .type = SET_FILTER_NAME, .key = "acl_sharing_map",
-               .required_setting = "dict_driver", },
+               .required_setting = "dict", },
        { .type = SET_FILTER_ARRAY,
                .key = "acl",
                .filter_array_field_name = "acl_id",
index 03bc190a2d1f2b32f881cf022cf651ac843aba7a..5ee58f85bb62ddd5557082434301551868438a06 100644 (file)
@@ -375,7 +375,8 @@ static void test_setup(void)
        test_ctx = test_mail_storage_init();
        const char *username = "mcp_test@example.com";
        const char *const extra_input[] = {
-               "mail_attribute/dict_driver=file",
+               "mail_attribute/dict=file",
+               "mail_attribute/dict/file/driver=file",
                t_strdup_printf("dict_file_path=%s/%s/dovecot-attributes",
                                test_ctx->home_root, username),
                NULL
index 7a1bce45bc7b3b866af13bf2d19cd0f0e722f96d..8e6efd04cd78cf1edabe40c8fdf02375d5a19c15 100644 (file)
@@ -44,7 +44,7 @@ static const struct setting_define notify_status_plugin_setting_defines[] = {
        DEF(BOOL, mailbox_notify_status),
        DEF(STR_NOVARS, notify_status_value),
        { .type = SET_FILTER_NAME, .key = "notify_status",
-        .required_setting = "dict_driver", },
+        .required_setting = "dict", },
 
        SETTING_DEFINE_LIST_END
 };
index c1d9faf1fb9a7b82c91a92c96e43ba5eb3607f16..dac2e5435ce45aa8dd9b3a4b8b5b80311f845957 100644 (file)
@@ -12,7 +12,7 @@
        SETTING_DEFINE_STRUCT_##type("quota_clone_"#name, name, struct quota_clone_settings)
 
 static const struct setting_define quota_clone_setting_defines[] = {
-       { .type = SET_FILTER_NAME, .key = "quota_clone", .required_setting = "dict_driver" },
+       { .type = SET_FILTER_NAME, .key = "quota_clone", .required_setting = "dict" },
        DEF(BOOL, unset),
        SETTING_DEFINE_LIST_END
 };