shared-storage.c revision 1453e7c587b98f93e1434aa0b147933948dbb50f
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2008-2012 Dovecot authors, see the included COPYING file */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen pool = pool_alloconly_create("shared storage", 1024);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen const char **error_r)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen const char *driver, *p;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* location must begin with the actual mailbox driver */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen driver = t_strdup_until(ns->set->location, p);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen _storage->class_flags = storage_class->class_flags;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (*p != '%')
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (*p != '\0') {
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* truncate prefix after the above checks are done, so they can log
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen the full prefix in error conditions */
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen /* user wasn't found. we'll still need to create the storage
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen to avoid exposing which users exist and which don't. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append(location, storage->storage_class_name);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* use a reachable but nonexistent path as the mail root directory */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen /* we can't know if this exists */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen const char **_name)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen static struct var_expand_table static_tab[] = {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen if (*p != '%') {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen switch (*++p) {
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen /* we checked this already above */
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (*p != '\0') {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* trying to open <prefix>/<user> mailbox */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Invalid namespace prefix %s vs %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* successfully matched the name. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* user@domain given */
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen username = t_strdup_until(userdomain, domain);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen /* trying to open namespace "shared/domain"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen namespace prefix. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen /* no domain given, use ours (if we have one) */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Empty username doesn't exist");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* expand the namespace prefix and see if it already exists.
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen this should normally happen only when the mailbox is being opened */
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen var_expand(prefix, storage->ns_prefix_pattern, tab);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* we'll need to look up the user's home directory */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': "
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Could not lookup home for user %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* create the new namespace */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
c52eba0224a0ff239f4778a7f6ed5ce38d92a5ddTimo Sirainen NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen get_nonexistent_user_location(storage, userdomain, location);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen p_strdup(user->pool, storage->unexpanded_location);
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen if (mail_storage_create(new_ns, NULL, _storage->flags |
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen MAIL_STORAGE_FLAG_NO_AUTOVERIFY, &error) < 0) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen /* this user doesn't have a usable storage */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* mark the shared namespace root as usable, since it now has
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen child namespaces */
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen /* flags are unset if we were using "auto" storage */