mail-namespace.c revision 288d6ef592719f2be3cad9f034e9be05f9839785
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2005-2011 Dovecot authors, see the included COPYING file */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#include "lib.h"
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#include "array.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "str.h"
5601c23c0d59376dfda22c7eb807c9e1a0870426Timo Sirainen#include "file-lock.h"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#include "settings-parser.h"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#include "mailbox-list-private.h"
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen#include "mail-storage-private.h"
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen#include "mail-storage-settings.h"
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#include "mail-namespace.h"
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#include <stdlib.h>
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainenvoid mail_namespace_add_storage(struct mail_namespace *ns,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct mail_storage *storage)
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen{
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* currently we support only a single storage */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen i_assert(ns->storage == NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->storage = storage;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (storage->v.add_list != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage->v.add_list(storage, ns->list);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen hook_mail_namespace_storage_added(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenvoid mail_namespace_finish_list_init(struct mail_namespace *ns,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mailbox_list *list)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ns->list = list;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix_len = strlen(ns->prefix);
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen}
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void mail_namespace_free(struct mail_namespace *ns)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ns->storage != NULL)
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen mail_storage_unref(&ns->storage);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (ns->list != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_destroy(&ns->list);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ns->owner != ns->user && ns->owner != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_user_unref(&ns->owner);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_free(ns->prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_free(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainennamespace_add(struct mail_user *user,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace_settings *ns_set,
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen struct mail_namespace_settings *unexpanded_ns_set,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_storage_settings *mail_set,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace **ns_p, const char **error_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen struct mail_namespace *ns;
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen const char *driver, *error;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns = i_new(struct mail_namespace, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->refcount = 1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->user = user;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strncmp(ns_set->type, "private", 7) == 0) {
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen ns->owner = user;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen ns->type = NAMESPACE_PRIVATE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else if (strncmp(ns_set->type, "shared", 6) == 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->type = NAMESPACE_SHARED;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else if (strncmp(ns_set->type, "public", 6) == 0)
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen ns->type = NAMESPACE_PUBLIC;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else {
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen *error_r = t_strdup_printf("Unknown namespace type: %s",
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen ns_set->type);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_namespace_free(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strcmp(ns_set->list, "children") == 0)
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen ns->flags |= NAMESPACE_FLAG_LIST_CHILDREN;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else if (strcmp(ns_set->list, "yes") == 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->flags |= NAMESPACE_FLAG_LIST_PREFIX;
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen else if (strcmp(ns_set->list, "no") != 0) {
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen *error_r = t_strdup_printf("Invalid list setting value: %s",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns_set->list);
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen mail_namespace_free(ns);
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ns_set->inbox) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->flags |= NAMESPACE_FLAG_INBOX_USER |
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen NAMESPACE_FLAG_INBOX_ANY;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ns_set->hidden)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->flags |= NAMESPACE_FLAG_HIDDEN;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ns_set->subscriptions)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->flags |= NAMESPACE_FLAG_SUBSCRIPTIONS;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (*ns_set->location == '\0')
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns_set->location = mail_set->mail_location;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mail_set->mail_debug) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_debug("Namespace %s: type=%s, prefix=%s, sep=%s, "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "inbox=%s, hidden=%s, list=%s, subscriptions=%s "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "location=%s",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns_set->name, ns_set->type, ns_set->prefix,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns_set->separator == NULL ? "" : ns_set->separator,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ns_set->inbox ? "yes" : "no",
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen ns_set->hidden ? "yes" : "no",
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ns_set->list,
ebfbf5d78dcf95e8b176429f4b5b0694eb4e17d5Timo Sirainen ns_set->subscriptions ? "yes" : "no", ns_set->location);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
ac383c437b1ccb9420cae6b4c4b03af3c8019e02Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ns->set = ns_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->unexpanded_set = unexpanded_ns_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->mail_set = mail_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix = i_strdup(ns_set->prefix);
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen if (ns->type == NAMESPACE_SHARED &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (strchr(ns->prefix, '%') != NULL ||
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen strchr(ns->set->location, '%') != NULL)) {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* dynamic shared namespace. the above check catches wrong
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mixed %% usage, but still allows for specifying a shared
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen namespace to an explicit location without any %% */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen driver = "shared";
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen } else {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen driver = NULL;
ac383c437b1ccb9420cae6b4c4b03af3c8019e02Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
ac383c437b1ccb9420cae6b4c4b03af3c8019e02Timo Sirainen if (mail_storage_create(ns, driver, 0, &error) < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = t_strdup_printf("Namespace '%s': %s",
ac383c437b1ccb9420cae6b4c4b03af3c8019e02Timo Sirainen ns->prefix, error);
ebfbf5d78dcf95e8b176429f4b5b0694eb4e17d5Timo Sirainen mail_namespace_free(ns);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen return -1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *ns_p = ns;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return 0;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen}
4ae81f8f7aad06aad2f570535cad6e40aaec2b28Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic bool namespace_is_valid_alias_storage(struct mail_namespace *ns,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char **error_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strcmp(ns->storage->name, ns->alias_for->storage->name) != 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = t_strdup_printf(
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen "Namespace %s can't have alias_for=%s "
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen "to a different storage type (%s vs %s)",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix, ns->alias_for->prefix,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->storage->name, ns->alias_for->storage->name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen }
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if ((ns->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ns->storage != ns->alias_for->storage) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = t_strdup_printf(
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen "Namespace %s can't have alias_for=%s "
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen "to a different storage (different root dirs)",
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ns->prefix, ns->alias_for->prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen return TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainennamespace_set_alias_for(struct mail_namespace *ns,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace *all_namespaces,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char **error_r)
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen{
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (ns->set->alias_for != NULL) {
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen ns->alias_for = mail_namespace_find_prefix(all_namespaces,
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen ns->set->alias_for);
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen if (ns->alias_for == NULL) {
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen *error_r = t_strdup_printf("Invalid namespace alias_for: %s",
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen ns->set->alias_for);
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen return -1;
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen }
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen if (ns->alias_for->alias_for != NULL) {
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen *error_r = t_strdup_printf("Chained namespace alias_for: %s",
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen ns->set->alias_for);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen return -1;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen }
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen if (!namespace_is_valid_alias_storage(ns, error_r))
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen return -1;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen ns->alias_chain_next = ns->alias_for->alias_chain_next;
fcde781c3ceb470c8dff34a68df19c69f93bcec9Timo Sirainen ns->alias_for->alias_chain_next = ns;
fcde781c3ceb470c8dff34a68df19c69f93bcec9Timo Sirainen }
fcde781c3ceb470c8dff34a68df19c69f93bcec9Timo Sirainen return 0;
fcde781c3ceb470c8dff34a68df19c69f93bcec9Timo Sirainen}
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainenstatic bool
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainennamespaces_check(struct mail_namespace *namespaces, const char **error_r)
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen{
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen struct mail_namespace *ns, *inbox_ns = NULL;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen unsigned int subscriptions_count = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen char ns_sep, list_sep = '\0';
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (ns = namespaces; ns != NULL; ns = ns->next) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns_sep = mail_namespace_get_sep(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mail_namespace_find_prefix(ns->next, ns->prefix) != NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = t_strdup_printf(
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "Duplicate namespace prefix: \"%s\"",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (namespace_set_alias_for(ns, namespaces, error_r) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (inbox_ns != NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = "There can be only one namespace with "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "inbox=yes";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_ns = ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen if (*ns->prefix != '\0' &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0 &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix[strlen(ns->prefix)-1] != ns_sep) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = t_strdup_printf(
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "list=yes requires prefix=%s "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "to end with separator", ns->prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen }
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen if (*ns->prefix != '\0' &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0 &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix[0] == ns_sep) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = t_strdup_printf(
fcde781c3ceb470c8dff34a68df19c69f93bcec9Timo Sirainen "list=yes requires prefix=%s "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "not to start with separator", ns->prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen }
1caf757864e7734345660e7d190f84e42668a6f8Timo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (list_sep == '\0')
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list_sep = ns_sep;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else if (list_sep != ns_sep) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = "All list=yes namespaces must use "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "the same separator";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if ((ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen subscriptions_count++;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (inbox_ns == NULL) {
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen *error_r = "inbox=yes namespace missing";
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen return FALSE;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen }
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (list_sep == '\0') {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = "no list=yes namespaces";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (subscriptions_count == 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = "no subscriptions=yes namespaces";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint mail_namespaces_init(struct mail_user *user, const char **error_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen const struct mail_storage_settings *mail_set;
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen struct mail_namespace_settings *const *ns_set;
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen struct mail_namespace_settings *const *unexpanded_ns_set;
37cd04fc1d01c4a7140ffcb514e15cee1e97986aTimo Sirainen struct mail_namespace *namespaces, *ns, **ns_p;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen unsigned int i, count, count2;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen i_assert(user->initialized);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen namespaces = NULL; ns_p = &namespaces;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen mail_set = mail_user_set_get_storage_set(user);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (array_is_created(&user->set->namespaces)) {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ns_set = array_get(&user->set->namespaces, &count);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unexpanded_ns_set =
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_get(&user->unexpanded_set->namespaces, &count2);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_assert(count == count2);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns_set = unexpanded_ns_set = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen count = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (i = 0; i < count; i++) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (namespace_add(user, ns_set[i], unexpanded_ns_set[i],
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_set, ns_p, error_r) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns_p = &(*ns_p)->next;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (namespaces != NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!namespaces_check(namespaces, error_r)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = t_strconcat("namespace configuration error: ",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r, NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while (namespaces != NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns = namespaces;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen namespaces = ns->next;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_namespace_free(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_user_add_namespace(user, &namespaces);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen T_BEGIN {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen hook_mail_namespaces_created(namespaces);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } T_END;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* no namespaces defined, create a default one */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return mail_namespaces_init_location(user, NULL, error_r);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint mail_namespaces_init_location(struct mail_user *user, const char *location,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char **error_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace_settings *inbox_set, *unexpanded_inbox_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace *ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_storage_settings *mail_set, *unexpanded_mail_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *error, *driver, *location_source;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_assert(location == NULL || *location != '\0');
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns = i_new(struct mail_namespace, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->refcount = 1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->type = NAMESPACE_PRIVATE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->flags = NAMESPACE_FLAG_INBOX_USER | NAMESPACE_FLAG_INBOX_ANY |
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_SUBSCRIPTIONS;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->owner = user;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_set = p_new(user->pool, struct mail_namespace_settings, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *inbox_set = mail_namespace_default_settings;
de11cf486e0d0448537b1b5d546496ab85e7cda8Timo Sirainen inbox_set->inbox = TRUE;
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen unexpanded_inbox_set = p_new(user->pool, struct mail_namespace_settings, 1);
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen *unexpanded_inbox_set = *inbox_set;
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen driver = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_set = mail_user_set_get_storage_set(user);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (location != NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_set->location = p_strdup(user->pool, location);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen location_source = "mail_location parameter";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else if (*mail_set->mail_location != '\0') {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unexpanded_mail_set = mail_user_set_get_driver_settings(
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen user->set_info, user->unexpanded_set,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MAIL_STORAGE_SET_DRIVER_NAME);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_set->location = mail_set->mail_location;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unexpanded_inbox_set->location =
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unexpanded_mail_set->mail_location;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen location_source = "mail_location setting";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen location_source = "environment MAIL";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_set->location = getenv("MAIL");
5601c23c0d59376dfda22c7eb807c9e1a0870426Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (inbox_set->location == NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* support also maildir-specific environment */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_set->location = getenv("MAILDIR");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (inbox_set->location == NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_set->location = "";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen driver = "maildir";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen location_source = "environment MAILDIR";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (*unexpanded_inbox_set->location == '\0') {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unexpanded_inbox_set->location =
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen p_strconcat(user->pool, SETTING_STRVAR_EXPANDED,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen inbox_set->location, NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->set = inbox_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->unexpanded_set = unexpanded_inbox_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->mail_set = mail_set;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix = i_strdup(ns->set->prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->user = user;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mail_storage_create(ns, driver, 0, &error) < 0) {
5601c23c0d59376dfda22c7eb807c9e1a0870426Timo Sirainen if (*inbox_set->location != '\0') {
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen *error_r = t_strdup_printf(
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen "Initializing mail storage from %s "
5601c23c0d59376dfda22c7eb807c9e1a0870426Timo Sirainen "failed: %s", location_source, error);
5601c23c0d59376dfda22c7eb807c9e1a0870426Timo Sirainen } else {
5601c23c0d59376dfda22c7eb807c9e1a0870426Timo Sirainen *error_r = t_strdup_printf("mail_location not set and "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "autodetection failed: %s", error);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_namespace_free(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen user->namespaces = ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen T_BEGIN {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen hook_mail_namespaces_created(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } T_END;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mail_namespace *mail_namespaces_init_empty(struct mail_user *user)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace *ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns = i_new(struct mail_namespace, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->refcount = 1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->user = user;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->owner = user;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->prefix = i_strdup("");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->flags = NAMESPACE_FLAG_INBOX_USER | NAMESPACE_FLAG_INBOX_ANY |
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_SUBSCRIPTIONS;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->mail_set = mail_user_set_get_storage_set(user);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen user->namespaces = ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_namespaces_deinit(struct mail_namespace **_namespaces)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace *ns, *next;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* update *_namespaces as needed, instead of immediately setting it
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen to NULL. for example mdbox_storage.destroy() wants to go through
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen user's namespaces. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while (*_namespaces != NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns = *_namespaces;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen next = ns->next;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_namespace_free(ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *_namespaces = next;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_namespaces_set_storage_callbacks(struct mail_namespace *namespaces,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_storage_callbacks *callbacks,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen void *context)
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen{
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen struct mail_namespace *ns;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (ns = namespaces; ns != NULL; ns = ns->next)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_storage_set_callbacks(ns->storage, callbacks, context);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenvoid mail_namespace_ref(struct mail_namespace *ns)
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen{
0007969c084c671b9f9378706083fad47799c84eTimo Sirainen i_assert(ns->refcount > 0);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ns->refcount++;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_namespace_unref(struct mail_namespace **_ns)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_namespace *ns = *_ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen i_assert(ns->refcount > 0);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
0007969c084c671b9f9378706083fad47799c84eTimo Sirainen *_ns = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (--ns->refcount > 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
0aa8ac8b4c2f1fd539cc3d93358d6c7af8481408Timo Sirainen i_assert(ns->destroyed);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_namespace_free(ns);
0aa8ac8b4c2f1fd539cc3d93358d6c7af8481408Timo Sirainen}
0aa8ac8b4c2f1fd539cc3d93358d6c7af8481408Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_namespace_destroy(struct mail_namespace *ns)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct mail_namespace **nsp;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen i_assert(!ns->destroyed);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen /* remove from user's namespaces list */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen for (nsp = &ns->user->namespaces; *nsp != NULL; nsp = &(*nsp)->next) {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (*nsp == ns) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *nsp = ns->next;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen break;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen }
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ns->destroyed = TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_namespace_unref(&ns);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mail_storage *
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenmail_namespace_get_default_storage(struct mail_namespace *ns)
de11cf486e0d0448537b1b5d546496ab85e7cda8Timo Sirainen{
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen /* currently we don't support more than one storage per namespace */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return ns->storage;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
b7fdf4fe23801de680e0be5aca0596a3c9ea3f8fTimo Sirainenchar mail_namespace_get_sep(struct mail_namespace *ns)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen return *ns->set->separator != '\0' ? *ns->set->separator :
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen mailbox_list_get_hierarchy_sep(ns->list);
}
char mail_namespaces_get_root_sep(struct mail_namespace *namespaces)
{
while ((namespaces->flags & NAMESPACE_FLAG_LIST_PREFIX) == 0)
namespaces = namespaces->next;
return mail_namespace_get_sep(namespaces);
}
static bool mail_namespace_is_usable_prefix(struct mail_namespace *ns,
const char *mailbox, bool inbox)
{
if (strncmp(ns->prefix, mailbox, ns->prefix_len) == 0) {
/* true exact prefix match */
return TRUE;
}
if (inbox && strncmp(ns->prefix, "INBOX", 5) == 0 &&
strncmp(ns->prefix+5, mailbox+5, ns->prefix_len-5) == 0) {
/* we already checked that mailbox begins with case-insensitive
INBOX. this namespace also begins with INBOX and the rest
of the prefix matches too. */
return TRUE;
}
if (strncmp(ns->prefix, mailbox, ns->prefix_len-1) == 0 &&
mailbox[ns->prefix_len-1] == '\0' &&
ns->prefix[ns->prefix_len-1] == mail_namespace_get_sep(ns)) {
/* we're trying to access the namespace prefix itself */
return TRUE;
}
return FALSE;
}
static struct mail_namespace *
mail_namespace_find_mask(struct mail_namespace *namespaces, const char *box,
enum namespace_flags flags,
enum namespace_flags mask)
{
struct mail_namespace *ns = namespaces;
struct mail_namespace *best = NULL;
unsigned int best_len = 0;
bool inbox;
inbox = strncasecmp(box, "INBOX", 5) == 0;
if (inbox && box[5] == '\0') {
/* find the INBOX namespace */
while (ns != NULL) {
if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
(ns->flags & mask) == flags)
return ns;
if (*ns->prefix == '\0')
best = ns;
ns = ns->next;
}
return best;
}
for (; ns != NULL; ns = ns->next) {
if (ns->prefix_len >= best_len && (ns->flags & mask) == flags &&
mail_namespace_is_usable_prefix(ns, box, inbox)) {
best = ns;
best_len = ns->prefix_len;
}
}
return best;
}
static struct mail_namespace *
mail_namespace_find_shared(struct mail_namespace *ns, const char *mailbox)
{
struct mailbox_list *list = ns->list;
struct mail_storage *storage;
if (mailbox_list_get_storage(&list, mailbox, &storage) < 0)
return ns;
return mailbox_list_get_namespace(list);
}
struct mail_namespace *
mail_namespace_find(struct mail_namespace *namespaces, const char *mailbox)
{
struct mail_namespace *ns;
ns = mail_namespace_find_mask(namespaces, mailbox, 0, 0);
if (ns != NULL && ns->type == NAMESPACE_SHARED &&
(ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
/* see if we need to autocreate a namespace for shared user */
if (strchr(mailbox, mail_namespace_get_sep(ns)) != NULL)
return mail_namespace_find_shared(ns, mailbox);
}
return ns;
}
struct mail_namespace *
mail_namespace_find_unalias(struct mail_namespace *namespaces,
const char **mailbox)
{
struct mail_namespace *ns;
const char *storage_name;
ns = mail_namespace_find(namespaces, *mailbox);
if (ns->alias_for != NULL) {
storage_name =
mailbox_list_get_storage_name(ns->list, *mailbox);
ns = ns->alias_for;
*mailbox = mailbox_list_get_vname(ns->list, storage_name);
}
return ns;
}
struct mail_namespace *
mail_namespace_find_visible(struct mail_namespace *namespaces,
const char *mailbox)
{
return mail_namespace_find_mask(namespaces, mailbox, 0,
NAMESPACE_FLAG_HIDDEN);
}
struct mail_namespace *
mail_namespace_find_subscribable(struct mail_namespace *namespaces,
const char *mailbox)
{
return mail_namespace_find_mask(namespaces, mailbox,
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 *
mail_namespace_find_inbox(struct mail_namespace *namespaces)
{
while ((namespaces->flags & NAMESPACE_FLAG_INBOX_USER) == 0)
namespaces = namespaces->next;
return namespaces;
}
struct mail_namespace *
mail_namespace_find_prefix(struct mail_namespace *namespaces,
const char *prefix)
{
struct mail_namespace *ns;
unsigned int len = strlen(prefix);
for (ns = namespaces; ns != NULL; ns = ns->next) {
if (ns->prefix_len == len &&
strcmp(ns->prefix, prefix) == 0)
return ns;
}
return NULL;
}
struct mail_namespace *
mail_namespace_find_prefix_nosep(struct mail_namespace *namespaces,
const char *prefix)
{
struct mail_namespace *ns;
unsigned int len = strlen(prefix);
for (ns = namespaces; ns != NULL; ns = ns->next) {
if (ns->prefix_len == len + 1 &&
strncmp(ns->prefix, prefix, len) == 0 &&
ns->prefix[len] == mail_namespace_get_sep(ns))
return ns;
}
return NULL;
}