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