]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Subscription handling fixes for subscriptions=no namespaces and shared mailboxes.
authorTimo Sirainen <tss@iki.fi>
Sat, 18 Oct 2008 14:07:42 +0000 (17:07 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 18 Oct 2008 14:07:42 +0000 (17:07 +0300)
--HG--
branch : HEAD

src/imap/cmd-subscribe.c
src/lib-storage/index/shared/shared-storage.c
src/lib-storage/list/mailbox-list-subscriptions.c
src/lib-storage/mail-namespace.c
src/lib-storage/mail-namespace.h

index 127845dd352ca86b14f45fabf62ba1c3262d5232..1f4c5a57cf938c84e10a3e8e9c46551484477110 100644 (file)
@@ -27,21 +27,38 @@ static bool have_listable_namespace_prefix(struct mail_namespace *ns,
 
 bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
 {
-       struct mail_namespace *ns;
-       const char *mailbox, *verify_name;
+       struct mail_namespace *ns, *real_ns;
+       struct mail_storage *storage;
+       const char *mailbox, *verify_name, *real_name;
 
        /* <mailbox> */
        if (!client_read_string_args(cmd, 1, &mailbox))
                return FALSE;
-
        verify_name = mailbox;
+
+       real_name = mailbox;
+       storage = client_find_storage(cmd, &real_name);
+       if (storage == NULL)
+               return TRUE;
+
+       /* now find a namespace where the subscription can be added to */
        ns = mail_namespace_find_subscribable(cmd->client->user->namespaces,
                                              &mailbox);
        if (ns == NULL) {
-               client_send_tagline(cmd, "NO Unknown namespace.");
+               client_send_tagline(cmd, "NO Unknown subscription namespace.");
                return TRUE;
        }
 
+       real_ns = mail_storage_get_namespace(storage);
+       if (ns != real_ns) {
+               /* subscription is being written to a different namespace
+                  than where the mailbox exists. */
+               mailbox = t_strconcat(real_ns->prefix, real_name, NULL);
+               /* drop the common prefix */
+               i_assert(strncmp(ns->prefix, mailbox, strlen(ns->prefix)) == 0);
+               mailbox += strlen(ns->prefix);
+       }
+
        if ((client_workarounds & WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
            *mailbox != '\0' && mailbox[strlen(mailbox)-1] ==
            mail_storage_get_hierarchy_sep(ns->storage)) {
index defd3b2ab72813aa4fdc0cfb7c7883f6570b78d1..a61763246eb56ea7f453969bff3f0b6878767449 100644 (file)
@@ -181,7 +181,8 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
        ns->type = NAMESPACE_SHARED;
        ns->user = user;
        ns->prefix = p_strdup(user->pool, str_c(prefix));
-       ns->flags = NAMESPACE_FLAG_LIST | NAMESPACE_FLAG_HIDDEN;
+       ns->flags = NAMESPACE_FLAG_LIST | NAMESPACE_FLAG_HIDDEN |
+               NAMESPACE_FLAG_AUTOCREATED;
        ns->sep = _storage->ns->sep;
 
        location = t_str_new(256);
index edc3027da30375c38907a3175affe1e33c1799d6..cca9e49b637062106664caf870040d3cc7c80681 100644 (file)
@@ -12,10 +12,12 @@ mailbox_list_subscriptions_fill_real(struct mailbox_list_iterate_context *ctx,
                                     struct imap_match_glob *glob,
                                     bool update_only)
 {
-       struct mail_namespace *ns = ctx->list->ns;
+       struct mail_namespace *default_ns = ctx->list->ns;
+       struct mail_namespace *namespaces = default_ns->user->namespaces;
        struct mailbox_list_iter_update_context update_ctx;
        struct subsfile_list_context *subsfile_ctx;
-       const char *path, *name;
+       struct mail_namespace *ns;
+       const char *path, *name, *name2, *full_name;
        string_t *vname;
 
        vname = t_str_new(256);
@@ -35,10 +37,26 @@ mailbox_list_subscriptions_fill_real(struct mailbox_list_iterate_context *ctx,
        update_ctx.match_parents =
                (ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0;
 
-       while ((name = subsfile_list_next(subsfile_ctx)) != NULL) {
+       while ((name = subsfile_list_next(subsfile_ctx)) != NULL) T_BEGIN {
+               full_name = name2 =
+                       t_strconcat(default_ns->prefix, name, NULL);
+               ns = mail_namespace_find_unsubscribable(namespaces, &name2);
+               if (ns == NULL)
+                       ns = default_ns;
+               else if (ns->type == NAMESPACE_SHARED &&
+                        (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
+                       /* we'll need to get the namespace autocreated. */
+                       (void)mailbox_list_is_valid_existing_name(ns->list,
+                                                                 name2);
+                       name = full_name;
+                       ns = mail_namespace_find_unsubscribable(namespaces,
+                                                               &name);
+               } else {
+                       name = name2;
+               }
                name = mail_namespace_get_vname(ns, vname, name);
                mailbox_list_iter_update(&update_ctx, name);
-       }
+       } T_END;
        return subsfile_list_deinit(subsfile_ctx);
 }
 
index 7e856d80bb665b923623f887d08fd16f798ce5be..07c202b4fcd00144da5126f6982a58964f42ac24 100644 (file)
@@ -382,7 +382,15 @@ mail_namespace_find_subscribable(struct mail_namespace *namespaces,
 {
        return mail_namespace_find_mask(namespaces, mailbox,
                                        NAMESPACE_FLAG_SUBSCRIPTIONS,
-                                        NAMESPACE_FLAG_SUBSCRIPTIONS);
+                                       NAMESPACE_FLAG_SUBSCRIPTIONS);
+}
+
+struct mail_namespace *
+mail_namespace_find_unsubscribable(struct mail_namespace *namespaces,
+                                  const char **mailbox)
+{
+       return mail_namespace_find_mask(namespaces, mailbox,
+                                       0, NAMESPACE_FLAG_SUBSCRIPTIONS);
 }
 
 struct mail_namespace *
index 2bc7072450296a7a8a9df8acc1ddd51ac36d147f..7e509a534d0ae23d4ecc14db78cf0683dbafa176 100644 (file)
@@ -20,7 +20,9 @@ enum namespace_flags {
        NAMESPACE_FLAG_SUBSCRIPTIONS    = 0x10,
 
        /* Namespace is created for internal use only. */
-       NAMESPACE_FLAG_INTERNAL         = 0x1000
+       NAMESPACE_FLAG_INTERNAL         = 0x1000,
+       /* Namespace was created automatically (for shared mailboxes) */
+       NAMESPACE_FLAG_AUTOCREATED      = 0x2000
 };
 
 struct mail_namespace {
@@ -71,6 +73,10 @@ mail_namespace_find_visible(struct mail_namespace *namespaces,
 struct mail_namespace *
 mail_namespace_find_subscribable(struct mail_namespace *namespaces,
                                 const char **mailbox);
+/* Like above, but find only from namespaces with subscriptions flag not set. */
+struct mail_namespace *
+mail_namespace_find_unsubscribable(struct mail_namespace *namespaces,
+                                  const char **mailbox);
 /* Returns the INBOX namespace */
 struct mail_namespace *
 mail_namespace_find_inbox(struct mail_namespace *namespaces);