From: Timo Sirainen Date: Sat, 18 Oct 2008 14:07:42 +0000 (+0300) Subject: Subscription handling fixes for subscriptions=no namespaces and shared mailboxes. X-Git-Tag: 1.2.alpha3~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a988c3fd9251806e38931a011aaa4006dd081cbd;p=thirdparty%2Fdovecot%2Fcore.git Subscription handling fixes for subscriptions=no namespaces and shared mailboxes. --HG-- branch : HEAD --- diff --git a/src/imap/cmd-subscribe.c b/src/imap/cmd-subscribe.c index 127845dd35..1f4c5a57cf 100644 --- a/src/imap/cmd-subscribe.c +++ b/src/imap/cmd-subscribe.c @@ -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; /* */ 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)) { diff --git a/src/lib-storage/index/shared/shared-storage.c b/src/lib-storage/index/shared/shared-storage.c index defd3b2ab7..a61763246e 100644 --- a/src/lib-storage/index/shared/shared-storage.c +++ b/src/lib-storage/index/shared/shared-storage.c @@ -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); diff --git a/src/lib-storage/list/mailbox-list-subscriptions.c b/src/lib-storage/list/mailbox-list-subscriptions.c index edc3027da3..cca9e49b63 100644 --- a/src/lib-storage/list/mailbox-list-subscriptions.c +++ b/src/lib-storage/list/mailbox-list-subscriptions.c @@ -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); } diff --git a/src/lib-storage/mail-namespace.c b/src/lib-storage/mail-namespace.c index 7e856d80bb..07c202b4fc 100644 --- a/src/lib-storage/mail-namespace.c +++ b/src/lib-storage/mail-namespace.c @@ -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 * diff --git a/src/lib-storage/mail-namespace.h b/src/lib-storage/mail-namespace.h index 2bc7072450..7e509a534d 100644 --- a/src/lib-storage/mail-namespace.h +++ b/src/lib-storage/mail-namespace.h @@ -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);