shared-storage.c revision 1453e7c587b98f93e1434aa0b147933948dbb50f
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2008-2012 Dovecot authors, see the included COPYING file */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "lib.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "array.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "str.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "ioloop.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "var-expand.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "index-storage.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "mailbox-list-private.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "fail-mail-storage.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "shared-storage.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include <stdlib.h>
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include <ctype.h>
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenextern struct mail_storage shared_storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen struct shared_storage *storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen pool_t pool;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen pool = pool_alloconly_create("shared storage", 1024);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->storage = shared_storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->storage.pool = pool;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen return &storage->storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic int
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen const char **error_r)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen struct mail_storage *storage_class;
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen const char *driver, *p;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen char *wildcardp, key;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen bool have_username;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* location must begin with the actual mailbox driver */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p = strchr(ns->set->location, ':');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (p == NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen driver = t_strdup_until(ns->set->location, p);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen storage->unexpanded_location =
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (storage_class != NULL)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen _storage->class_flags = storage_class->class_flags;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen else if (strcmp(driver, "auto") != 0) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen driver, NULL);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen wildcardp = strchr(ns->prefix, '%');
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen if (wildcardp == NULL) {
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen have_username = FALSE;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (*p != '%')
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen continue;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen key = p[1];
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen if (key == 'u' || key == 'n')
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen have_username = TRUE;
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen else if (key != '%' && key != 'd')
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen break;
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen }
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (*p != '\0') {
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (!have_username) {
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen return -1;
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen }
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (p[-1] != mail_namespace_get_sep(ns) &&
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* truncate prefix after the above checks are done, so they can log
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen the full prefix in error conditions */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen *wildcardp = '\0';
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns->prefix_len = strlen(ns->prefix);
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen return 0;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mailbox_list_settings *set)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen set->layout = "shared";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen const char *username, string_t *location)
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen{
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 str_append_c(location, ':');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* use a reachable but nonexistent path as the mail root directory */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen str_append(location, "/user-not-found/");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append(location, username);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen}
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen const char *path;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct stat st;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen if (path == NULL) {
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen /* we can't know if this exists */
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen return TRUE;
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen }
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen return stat(path, &st) == 0;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen const char **_name)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mailbox_list *list = (*_ns)->list;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_user *user = _storage->user;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen static struct var_expand_table static_tab[] = {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen { 'u', NULL, "user" },
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen { 'n', NULL, "username" },
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen { 'd', NULL, "domain" },
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen { 'h', NULL, "home" },
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen { '\0', NULL, NULL }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen };
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct var_expand_table *tab;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_namespace *new_ns, *ns = *_ns;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_user *owner;
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen const char *name, *p, *next, **dest, *error;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen string_t *prefix, *location;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen char ns_sep = mail_namespace_get_sep(ns);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen int ret;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p = storage->ns_prefix_pattern;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (name = *_name; *p != '\0';) {
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen if (*p != '%') {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (*p != *name)
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen break;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p++; name++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen continue;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen switch (*++p) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen case 'd':
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen dest = &domain;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen break;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen case 'n':
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen dest = &username;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen break;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen case 'u':
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen dest = &userdomain;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen break;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen default:
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen /* we checked this already above */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_unreached();
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen }
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen p++;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen if (next == NULL) {
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen *dest = name;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen name = "";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen break;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen }
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen *dest = t_strdup_until(name, next);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen name = next;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (*p != '\0') {
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen if (*name == '\0' ||
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen (name[1] == '\0' && *name == ns_sep)) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* trying to open <prefix>/<user> mailbox */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen name = "INBOX";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen } else {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mailbox_list_set_critical(list,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Invalid namespace prefix %s vs %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen storage->ns_prefix_pattern, *_name);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* successfully matched the name. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (userdomain != NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* user@domain given */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen domain = strchr(userdomain, '@');
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen if (domain == NULL)
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen username = userdomain;
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen else {
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen username = t_strdup_until(userdomain, domain);
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen domain++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen } else if (username == NULL) {
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen /* trying to open namespace "shared/domain"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen namespace prefix. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen } else {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (domain == NULL) {
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen /* no domain given, use ours (if we have one) */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen domain = strchr(user->username, '@');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (domain != NULL) domain++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen userdomain = domain == NULL ? username :
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen t_strconcat(username, "@", domain, NULL);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (*userdomain == '\0') {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Empty username doesn't exist");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
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 */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen tab = t_malloc(sizeof(static_tab));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen tab[0].value = userdomain;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen tab[1].value = username;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen tab[2].value = domain;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen prefix = t_str_new(128);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen str_append(prefix, ns->prefix);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen var_expand(prefix, storage->ns_prefix_pattern, tab);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen if (*_ns != NULL) {
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen t_strconcat(ns->prefix, name, NULL));
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen return 0;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen user->unexpanded_set);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen owner->autocreated = TRUE;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (mail_user_init(owner, &error) < 0) {
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen if (!owner->nonexistent) {
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen mailbox_list_set_critical(list,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns->prefix, userdomain, error);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_user_unref(&owner);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ret = 0;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ret = 1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen } else {
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 ns->prefix, userdomain);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_user_unref(&owner);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* create the new namespace */
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen new_ns = i_new(struct mail_namespace, 1);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->refcount = 1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->type = MAIL_NAMESPACE_TYPE_SHARED;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->user = user;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->prefix = i_strdup(str_c(prefix));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->owner = owner;
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 new_ns->mail_set = _storage->set;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen location = t_str_new(256);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (ret > 0)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen var_expand(location, storage->location, tab);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen else {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen get_nonexistent_user_location(storage, userdomain, location);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (ns->user->mail_debug) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_debug("shared: Tried to access mails of "
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "nonexistent user %s", userdomain);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->type = "shared";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->prefix = new_ns->prefix;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->hidden = TRUE;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ns_set->list = "yes";
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->set = ns_set;
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen unexpanded_ns_set =
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen *unexpanded_ns_set = *ns_set;
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen unexpanded_ns_set->location =
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen p_strdup(user->pool, storage->unexpanded_location);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen new_ns->unexpanded_set = unexpanded_ns_set;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
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",
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen new_ns->prefix, error);
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen mail_namespace_destroy(new_ns);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen !shared_namespace_exists(new_ns)) {
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen /* this user doesn't have a usable storage */
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* mark the shared namespace root as usable, since it now has
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen child namespaces */
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen ns->flags |= NAMESPACE_FLAG_USABLE;
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen t_strconcat(new_ns->prefix, name, NULL));
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen *_ns = new_ns;
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen if (_storage->class_flags == 0) {
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen /* flags are unset if we were using "auto" storage */
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen _storage->class_flags = new_ns->storage->class_flags;
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen mail_user_add_namespace(user, &new_ns);
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen return 0;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen}
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainenstruct mail_storage shared_storage = {
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen .name = SHARED_STORAGE_NAME,
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen .class_flags = 0, /* unknown at this point */
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen .v = {
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen NULL,
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen shared_storage_alloc,
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen shared_storage_create,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen index_storage_destroy,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen NULL,
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen shared_storage_get_list_settings,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen NULL,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen fail_mailbox_alloc,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen NULL
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen};
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen