]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage, acl: Replace %%variables in shared namespace prefix with $variables
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 18 Sep 2024 10:55:13 +0000 (13:55 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:40:00 +0000 (10:40 +0200)
%%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.

src/lib-storage/index/shared/shared-storage.c
src/lib-storage/index/shared/shared-storage.h
src/lib-storage/mail-namespace.c
src/plugins/acl/acl-shared-storage.c

index bea7afa7534311f6f80be0c7d9e1d89b2d5c61cd..26f059c4ed428db08f6de96bb0f39ca820520a3b 100644 (file)
@@ -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) {
index 4cff041e5ae2a91e83d516d8aaf342a6a890d24d..dc4864bba1fc35e9d7ec09344783ab01ec9865ae 100644 (file)
@@ -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
index 253c1e92b30094c50abd6c03186f5a27fb1562cc..3ea987411f2ab6011ad0dab672d3db2427701f78 100644 (file)
@@ -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;
index 7bd4042388afc58d85f18533fa1e179c9c01890b..abf66cc718c4a4dec52738d4d1fa52a4a57137fd 100644 (file)
@@ -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;