shared-storage.c revision 1ba47b1a31e60c533631c8810400b365f785870a
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes/* Copyright (c) 2008-2010 Dovecot authors, see the included COPYING file */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "lib.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "array.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "str.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "ioloop.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "var-expand.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "index-storage.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "mailbox-list-private.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include "shared-storage.h"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include <stdlib.h>
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes#include <ctype.h>
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesextern struct mail_storage shared_storage;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesstatic struct mail_storage *shared_storage_alloc(void)
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes{
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct shared_storage *storage;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes pool_t pool;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes pool = pool_alloconly_create("shared storage", 1024);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage = p_new(pool, struct shared_storage, 1);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage->storage = shared_storage;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage->storage.pool = pool;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return &storage->storage;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes}
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesstatic int
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes const char **error_r)
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes{
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct shared_storage *storage = (struct shared_storage *)_storage;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes const char *driver, *p;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes char *wildcardp, key;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes bool have_username;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* location must begin with the actual mailbox driver */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes p = strchr(ns->set->location, ':');
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (p == NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *error_r = "Shared mailbox location not prefixed with driver";
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes driver = t_strdup_until(ns->set->location, p);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage->location = p_strdup(_storage->pool, ns->set->location);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage->unexpanded_location =
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes p_strdup(_storage->pool, ns->unexpanded_set->location);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage->storage_class = mail_storage_find_class(driver);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (storage->storage_class == NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *error_r = t_strconcat("Unknown shared storage driver: ",
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes driver, NULL);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes _storage->class_flags = storage->storage_class->class_flags;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes wildcardp = strchr(ns->prefix, '%');
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (wildcardp == NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *error_r = "Shared namespace prefix doesn't contain %";
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes have_username = FALSE;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*p != '%')
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes continue;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes key = var_get_key(p + 1);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (key == 'u' || key == 'n')
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes have_username = TRUE;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes else if (key != '%' && key != 'd')
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes break;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*p != '\0') {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *error_r = "Shared namespace prefix contains unknown variables";
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (!have_username) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *error_r = "Shared namespace prefix doesn't contain %u or %n";
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* truncate prefix after the above checks are done, so they can log
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes the full prefix in error conditions */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *wildcardp = '\0';
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes ns->prefix_len = strlen(ns->prefix);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return 0;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes}
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesstatic void
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct mailbox_list_settings *set)
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes{
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes set->layout = "shared";
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes}
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesstatic void
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesget_nonexistent_user_location(struct shared_storage *storage,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes const char *username, string_t *location)
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes{
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* user wasn't found. we'll still need to create the storage
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes to avoid exposing which users exist and which don't. */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes str_append(location, storage->storage_class->name);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes str_append_c(location, ':');
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* use a reachable but nonexistent path as the mail root directory */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes str_append(location, storage->storage.user->set->base_dir);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes str_append(location, "/user-not-found/");
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes str_append(location, username);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes}
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholesint shared_storage_get_namespace(struct mail_namespace **_ns,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes const char **_name)
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes{
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct mail_storage *_storage = (*_ns)->storage;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct mailbox_list *list = (*_ns)->list;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct shared_storage *storage = (struct shared_storage *)_storage;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct mail_user *user = _storage->user;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes static struct var_expand_table static_tab[] = {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes { 'u', NULL, "user" },
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes { 'n', NULL, "username" },
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes { 'd', NULL, "domain" },
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes { 'h', NULL, "home" },
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes { '\0', NULL, NULL }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes };
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct var_expand_table *tab;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct mail_namespace *new_ns, *ns = *_ns;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes struct mail_user *owner;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes const char *domain = NULL, *username = NULL, *userdomain = NULL;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes const char *name, *p, *next, **dest, *error;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes string_t *prefix, *location;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes int ret;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes p = storage->ns_prefix_pattern;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes for (name = *_name; *p != '\0';) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*p != '%') {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*p != *name)
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes break;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes p++; name++;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes continue;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes switch (*++p) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes case 'd':
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes dest = &domain;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes break;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes case 'n':
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes dest = &username;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes break;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes case 'u':
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes dest = &userdomain;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes break;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes default:
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* we checked this already above */
be5bd52e27f7609ecfa7b472935e1fb422f02c09bnicholes i_unreached();
be5bd52e27f7609ecfa7b472935e1fb422f02c09bnicholes }
be5bd52e27f7609ecfa7b472935e1fb422f02c09bnicholes p++;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes next = strchr(name, *p != '\0' ? *p : ns->sep);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (next == NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *dest = name;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes name = "";
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes break;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *dest = t_strdup_until(name, next);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes name = next;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*p != '\0') {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*name == '\0' ||
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes (name[1] == '\0' && *name == ns->sep)) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* trying to open <prefix>/<user> mailbox */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes name = "INBOX";
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes } else {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes mailbox_list_set_critical(list,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes "Invalid namespace prefix %s vs %s",
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes storage->ns_prefix_pattern, *_name);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* successfully matched the name. */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (userdomain != NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* user@domain given */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes domain = strchr(userdomain, '@');
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (domain == NULL)
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes username = userdomain;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes else {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes username = t_strdup_until(userdomain, domain);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes domain++;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes } else if (username == NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* trying to open namespace "shared/domain"
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes namespace prefix. */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes } else {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (domain == NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* no domain given, use ours (if we have one) */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes domain = strchr(user->username, '@');
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (domain != NULL) domain++;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes userdomain = domain == NULL ? username :
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes t_strconcat(username, "@", domain, NULL);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*userdomain == '\0') {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes "Empty username doesn't exist");
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* expand the namespace prefix and see if it already exists.
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes this should normally happen only when the mailbox is being opened */
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes tab = t_malloc(sizeof(static_tab));
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes memcpy(tab, static_tab, sizeof(static_tab));
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes tab[0].value = userdomain;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes tab[1].value = username;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes tab[2].value = domain;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes prefix = t_str_new(128);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes str_append(prefix, ns->prefix);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes var_expand(prefix, storage->ns_prefix_pattern, tab);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (*_ns != NULL) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes *_name = mail_namespace_fix_sep(ns, name);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return 0;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes owner = mail_user_alloc(userdomain, user->set_info,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes user->unexpanded_set);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (!var_has_key(storage->location, 'h', "home"))
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes ret = 1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes else {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes /* we'll need to look up the user's home directory */
f2f3f241c00a7a4bd597e57a19023940e072918abnicholes if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes mailbox_list_set_critical(list, "Namespace '%s': "
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes "Could not lookup home for user %s",
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes ns->prefix, userdomain);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes mail_user_unref(&owner);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes if (mail_user_init(owner, &error) < 0) {
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes mailbox_list_set_critical(list,
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes "Couldn't create namespace '%s' for user %s: %s",
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes ns->prefix, userdomain, error);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes mail_user_unref(&owner);
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes return -1;
bb2b38cd44b032118359afbc743efbea12f48e61bnicholes }
/* create the new namespace */
new_ns = i_new(struct mail_namespace, 1);
new_ns->refcount = 1;
new_ns->type = NAMESPACE_SHARED;
new_ns->user = user;
new_ns->prefix = i_strdup(str_c(prefix));
new_ns->owner = owner;
new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
new_ns->sep = ns->sep;
new_ns->mail_set = _storage->set;
location = t_str_new(256);
if (ret > 0)
var_expand(location, storage->location, tab);
else {
get_nonexistent_user_location(storage, userdomain, location);
new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
}
ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
ns_set->type = "shared";
ns_set->separator = p_strdup_printf(user->pool, "%c", new_ns->sep);
ns_set->prefix = new_ns->prefix;
ns_set->location = p_strdup(user->pool, str_c(location));
ns_set->hidden = TRUE;
ns_set->list = "yes";
new_ns->set = ns_set;
unexpanded_ns_set =
p_new(user->pool, struct mail_namespace_settings, 1);
*unexpanded_ns_set = *ns_set;
unexpanded_ns_set->location =
p_strdup(user->pool, storage->unexpanded_location);
new_ns->unexpanded_set = unexpanded_ns_set;
if (mail_storage_create(new_ns, NULL, _storage->flags, &error) < 0) {
mailbox_list_set_critical(list, "Namespace '%s': %s",
new_ns->prefix, error);
mail_namespace_destroy(new_ns);
return -1;
}
ns->flags |= NAMESPACE_FLAG_USABLE;
*_name = mail_namespace_fix_sep(new_ns, name);
*_ns = new_ns;
mail_user_add_namespace(user, &new_ns);
return 0;
}
struct mail_storage shared_storage = {
.name = SHARED_STORAGE_NAME,
.class_flags = 0, /* unknown at this point */
.v = {
NULL,
shared_storage_alloc,
shared_storage_create,
NULL,
NULL,
shared_storage_get_list_settings,
NULL,
NULL,
NULL
}
};