From: Timo Sirainen Date: Wed, 18 Sep 2024 10:55:13 +0000 (+0300) Subject: lib-storage, acl: Replace %%variables in shared namespace prefix with $variables X-Git-Tag: 2.4.0~356 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0b57d23fddfed5cd729cd3f9d5a8a86abae90e67;p=thirdparty%2Fdovecot%2Fcore.git lib-storage, acl: Replace %%variables in shared namespace prefix with $variables %%u -> $user, %%n -> $username, %%d -> $domain This the variables couldn't actually be used in any complex ways, these $variable templates make more sense. They're also more consistent with how dict-sql handles similar templating. --- diff --git a/src/lib-storage/index/shared/shared-storage.c b/src/lib-storage/index/shared/shared-storage.c index bea7afa753..26f059c4ed 100644 --- a/src/lib-storage/index/shared/shared-storage.c +++ b/src/lib-storage/index/shared/shared-storage.c @@ -4,7 +4,6 @@ #include "array.h" #include "str.h" #include "ioloop.h" -#include "var-expand.h" #include "settings.h" #include "index-storage.h" #include "mail-storage-service.h" @@ -34,7 +33,7 @@ shared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns, { struct shared_storage *storage = SHARED_STORAGE(_storage); const char *p; - char *wildcardp, key; + char *wildcardp; bool have_username; struct mail_storage_settings *set; @@ -61,30 +60,38 @@ shared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns, } settings_free(set); - wildcardp = strchr(ns->prefix, '%'); + wildcardp = strchr(ns->prefix, '$'); if (wildcardp == NULL) { - *error_r = "Shared namespace prefix doesn't contain %"; - return -1; + /* We shouldn't even get here normally. If there is no '$', the + namespace creation wouldn't have set + MAIL_STORAGE_FLAG_SHARED_DYNAMIC and a different storage + driver would have been used. Continue anyway, the following + error handling code will complain about missing variables. */ + wildcardp = ns->prefix; } storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp); have_username = FALSE; - for (p = storage->ns_prefix_pattern; *p != '\0'; p++) { - if (*p != '%') + for (p = storage->ns_prefix_pattern; *p != '\0'; ) { + if (*p != '$') { + p++; continue; + } - key = p[1]; - if (key == 'u' || key == 'n') + if (str_begins(p, "$username", &p) || + str_begins(p, "$user", &p)) have_username = TRUE; - else if (key != '%' && key != 'd') + else if (!str_begins(p, "$domain", &p)) + break; + if (i_isalnum(*p)) break; } if (*p != '\0') { - *error_r = "Shared namespace prefix contains unknown variables"; + *error_r = "Shared namespace prefix contains unknown $variables"; return -1; } if (!have_username) { - *error_r = "Shared namespace prefix doesn't contain %u or %n"; + *error_r = "Shared namespace prefix doesn't contain $user or $username"; return -1; } if (p[-1] != mail_namespace_get_sep(ns) && @@ -119,6 +126,31 @@ shared_mail_user_init(struct mail_storage *_storage, struct mail_namespace **_ns, const char *username, const char *domain, const char *new_ns_prefix); +void shared_storage_ns_prefix_expand(struct shared_storage *storage, + string_t *dest, const char *user) +{ + const char *p, *last = storage->ns_prefix_pattern; + + while ((p = strchr(last, '$')) != NULL) { + str_append_data(dest, last, p - last); + + if (str_begins(p, "$username", &p)) + str_append(dest, t_strcut(user, '@')); + else if (str_begins(p, "$user", &p)) + str_append(dest, user); + else if (str_begins(p, "$domain", &p)) { + const char *domain = strchr(user, '@'); + if (domain != NULL) + str_append(dest, domain + 1); + } else { + /* pattern validity was already checked */ + i_unreached(); + } + last = p; + } + str_append(dest, last); +} + int shared_storage_get_namespace(struct mail_namespace **_ns, const char **_name) { @@ -135,27 +167,22 @@ int shared_storage_get_namespace(struct mail_namespace **_ns, p = storage->ns_prefix_pattern; for (name = *_name; *p != '\0';) { - if (*p != '%') { + if (*p != '$') { if (*p != *name) break; p++; name++; continue; } - switch (*++p) { - case 'd': - dest = &domain; - break; - case 'n': + if (str_begins(p, "$username", &p)) dest = &username; - break; - case 'u': + else if (str_begins(p, "$user", &p)) dest = &userdomain; - break; - default: - /* we checked this already above */ + else if (str_begins(p, "$domain", &p)) + dest = &domain; + else { + /* pattern validity was already checked */ i_unreached(); } - p++; next = strchr(name, *p != '\0' ? *p : ns_sep); if (next == NULL) { @@ -211,23 +238,10 @@ int shared_storage_get_namespace(struct mail_namespace **_ns, /* expand the namespace prefix and see if it already exists. this should normally happen only when the mailbox is being opened */ - struct var_expand_table tab[] = { - { 'u', userdomain, "user" }, - { 'n', username, "username" }, - { 'd', domain, "domain" }, - { 'h', NULL, "home" }, - { '\0', NULL, NULL } - }; - prefix = t_str_new(128); str_append(prefix, ns->prefix); - if (var_expand_with_table(prefix, storage->ns_prefix_pattern, tab, - &error) <= 0) { - mailbox_list_set_critical(list, - "Failed to expand namespace prefix '%s': %s", - storage->ns_prefix_pattern, error); - return -1; - } + + shared_storage_ns_prefix_expand(storage, prefix, userdomain); *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix)); if (*_ns != NULL) { diff --git a/src/lib-storage/index/shared/shared-storage.h b/src/lib-storage/index/shared/shared-storage.h index 4cff041e5a..dc4864bba1 100644 --- a/src/lib-storage/index/shared/shared-storage.h +++ b/src/lib-storage/index/shared/shared-storage.h @@ -17,4 +17,7 @@ struct mailbox_list *shared_mailbox_list_alloc(void); int shared_storage_get_namespace(struct mail_namespace **_ns, const char **_name); +void shared_storage_ns_prefix_expand(struct shared_storage *storage, + string_t *dest, const char *user); + #endif diff --git a/src/lib-storage/mail-namespace.c b/src/lib-storage/mail-namespace.c index 253c1e92b3..3ea987411f 100644 --- a/src/lib-storage/mail-namespace.c +++ b/src/lib-storage/mail-namespace.c @@ -155,9 +155,9 @@ int mail_namespaces_init_add(struct mail_user *user, struct event *set_event, } if (ns->type == MAIL_NAMESPACE_TYPE_SHARED && - strchr(ns->prefix, '%') != NULL) { + strchr(ns->prefix, '$') != NULL) { /* This is a dynamic shared namespace root under which new - per-user shared namespaces are created. The '%' is checked + per-user shared namespaces are created. The '$' is checked to allow non-dynamic shared namespaces to be created with explicit locations. */ flags |= MAIL_STORAGE_FLAG_SHARED_DYNAMIC; diff --git a/src/plugins/acl/acl-shared-storage.c b/src/plugins/acl/acl-shared-storage.c index 7bd4042388..abf66cc718 100644 --- a/src/plugins/acl/acl-shared-storage.c +++ b/src/plugins/acl/acl-shared-storage.c @@ -4,7 +4,6 @@ #include "array.h" #include "ioloop.h" #include "str.h" -#include "var-expand.h" #include "acl-plugin.h" #include "acl-lookup-dict.h" #include "acl-shared-storage.h" @@ -40,7 +39,7 @@ acl_shared_namespace_add(struct mail_namespace *ns, struct mail_namespace *new_ns = ns; struct mailbox_list_iterate_context *iter; const struct mailbox_info *info; - const char *mailbox, *error; + const char *mailbox; string_t *str; if (strcmp(ns->user->username, userdomain) == 0) { @@ -48,21 +47,9 @@ acl_shared_namespace_add(struct mail_namespace *ns, return; } - const struct var_expand_table tab[] = { - { 'u', userdomain, "user" }, - { 'n', t_strcut(userdomain, '@'), "username" }, - { 'd', i_strchr_to_next(userdomain, '@'), "domain" }, - { '\0', NULL, NULL } - }; - str = t_str_new(128); - if (var_expand_with_table(str, sstorage->ns_prefix_pattern, tab, - &error) <= 0) { - e_error(storage->event, - "Failed to expand namespace prefix %s: %s", - sstorage->ns_prefix_pattern, error); - return; - } + shared_storage_ns_prefix_expand(sstorage, str, userdomain); + mailbox = str_c(str); if (shared_storage_get_namespace(&new_ns, &mailbox) < 0) return;