shared-storage.c revision 0175d37a5ae5a4d146ca41b684bd38d9b03683cb
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2016 Dovecot authors, see the included COPYING file */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "lib.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "array.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "str.h"
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde#include "ioloop.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "var-expand.h"
cda217260716cfd8d8ec5e56f91708c64c140538Timo Sirainen#include "index-storage.h"
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen#include "mailbox-list-private.h"
d00ae137b6772f0b047cc98cb153f11c5246f82bTimo Sirainen#include "fail-mail-storage.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "shared-storage.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen#include <ctype.h>
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenextern struct mail_storage shared_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen pool_t pool;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
f325d795b52ce2053f914072b22ebca9c4f0dc7eTimo Sirainen pool = pool_alloconly_create("shared storage", 1024);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage = p_new(pool, struct shared_storage, 1);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->storage = shared_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->storage.pool = pool;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return &storage->storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char **error_r)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen struct mail_storage *storage_class;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *driver, *p;
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen char *wildcardp, key;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen bool have_username;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* location must begin with the actual mailbox driver */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p = strchr(ns->set->location, ':');
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (p == NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen driver = t_strdup_until(ns->set->location, p);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen storage->unexpanded_location =
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
0f17bb103602d0c4394e3784cb96d788530fc79eTimo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
0f17bb103602d0c4394e3784cb96d788530fc79eTimo Sirainen
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen if (storage_class != NULL)
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen _storage->class_flags = storage_class->class_flags;
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen else if (strcmp(driver, "auto") != 0) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen driver, NULL);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen wildcardp = strchr(ns->prefix, '%');
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen if (wildcardp == NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen have_username = FALSE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '%')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen
f6d63a21010540d3ddf08f2e7664ffca3ea70489Timo Sirainen key = p[1];
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen if (key == 'u' || key == 'n')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen have_username = TRUE;
139cbf8d9e1cc0c65d985f525756fe47a7bfada6Timo Sirainen else if (key != '%' && key != 'd')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '\0') {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!have_username) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
dc912088f84c263db1609435c2f5d7cb29bf1a33Timo Sirainen if (p[-1] != mail_namespace_get_sep(ns) &&
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen return -1;
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* truncate prefix after the above checks are done, so they can log
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen the full prefix in error conditions */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *wildcardp = '\0';
8d90e4f9a8f79f79c393aca23d0a897471dc2d8fTimo Sirainen ns->prefix_len = strlen(ns->prefix);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mailbox_list_settings *set)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen set->layout = "shared";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenstatic void
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen const char *username, string_t *location)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen{
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* user wasn't found. we'll still need to create the storage
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen to avoid exposing which users exist and which don't. */
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen str_append(location, storage->storage_class_name);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen str_append_c(location, ':');
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen /* use a reachable but nonexistent path as the mail root directory */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen str_append(location, "/user-not-found/");
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen str_append(location, username);
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde}
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen{
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen const char *path;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen struct stat st;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen if (path == NULL) {
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen /* we can't know if this exists */
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen return TRUE;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen }
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen return stat(path, &st) == 0;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen}
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char **_name)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mailbox_list *list = (*_ns)->list;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_user *user = _storage->user;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen static struct var_expand_table static_tab[] = {
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen { 'u', NULL, "user" },
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen { 'n', NULL, "username" },
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen { 'd', NULL, "domain" },
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen { 'h', NULL, "home" },
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen { '\0', NULL, NULL }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen };
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct var_expand_table *tab;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_namespace *new_ns, *ns = *_ns;
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct mail_user *owner;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *name, *p, *next, **dest, *error;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen string_t *prefix, *location;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen char ns_sep = mail_namespace_get_sep(ns);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen int ret;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p = storage->ns_prefix_pattern;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (name = *_name; *p != '\0';) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '%') {
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen if (*p != *name)
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p++; name++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen switch (*++p) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen case 'd':
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = &domain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen case 'n':
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = &username;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen case 'u':
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = &userdomain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen default:
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* we checked this already above */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_unreached();
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
35083063d0e432d0cf78206b5929750e613ad772Timo Sirainen if (next == NULL) {
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen *dest = name;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen name = "";
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen break;
35083063d0e432d0cf78206b5929750e613ad772Timo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *dest = t_strdup_until(name, next);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen name = next;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen if (*p != '\0') {
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen if (*name == '\0' ||
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (name[1] == '\0' && *name == ns_sep)) {
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen /* trying to open <prefix>/<user> mailbox */
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen name = "INBOX";
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_critical(list,
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen "Invalid namespace prefix %s vs %s",
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen storage->ns_prefix_pattern, *_name);
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen return -1;
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen }
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen }
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* successfully matched the name. */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen if (userdomain != NULL) {
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* user@domain given */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen domain = strchr(userdomain, '@');
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (domain == NULL)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen username = userdomain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen else {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen username = t_strdup_until(userdomain, domain);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen domain++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen } else if (username == NULL) {
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* trying to open namespace "shared/domain"
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen namespace prefix. */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen return -1;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen } else {
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen if (domain == NULL) {
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* no domain given, use ours (if we have one) */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen domain = strchr(user->username, '@');
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen if (domain != NULL) domain++;
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen }
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen userdomain = domain == NULL ? username :
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen t_strconcat(username, "@", domain, NULL);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen if (*userdomain == '\0') {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen "Empty username doesn't exist");
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen return -1;
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* expand the namespace prefix and see if it already exists.
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen this should normally happen only when the mailbox is being opened */
0175d37a5ae5a4d146ca41b684bd38d9b03683cbMartti Rannanjärvi tab = t_malloc_no0(sizeof(static_tab));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen tab[0].value = userdomain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen tab[1].value = username;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen tab[2].value = domain;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen prefix = t_str_new(128);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append(prefix, ns->prefix);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen var_expand(prefix, storage->ns_prefix_pattern, tab);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (*_ns != NULL) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen t_strconcat(ns->prefix, name, NULL));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen user->unexpanded_set);
691f802ef6ec2105079d420ba26b21088402c6daTimo Sirainen owner->_service_user = user->_service_user;
645d76bbb742c74795a0b35fe159451c4afad8d8Timo Sirainen owner->creator = user;
f534c0d42f1470fca8e4ff3493c94927bf600260Timo Sirainen owner->autocreated = TRUE;
bff606130fa332dbf837569f922028b68f45fd61Timo Sirainen owner->session_id = p_strdup(owner->pool, user->session_id);
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen if (mail_user_init(owner, &error) < 0) {
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen if (!owner->nonexistent) {
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen mailbox_list_set_critical(list,
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen "Couldn't create namespace '%s' for user %s: %s",
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen ns->prefix, userdomain, error);
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen mail_user_unref(&owner);
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen return -1;
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen }
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen ret = 0;
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen ret = 1;
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen } else {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* we'll need to look up the user's home directory */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': "
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen "Could not lookup home for user %s",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ns->prefix, userdomain);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen mail_user_unref(&owner);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen return -1;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen }
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen }
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* create the new namespace */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns = i_new(struct mail_namespace, 1);
1ba47b1a31e60c533631c8810400b365f785870aTimo Sirainen new_ns->refcount = 1;
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen new_ns->type = MAIL_NAMESPACE_TYPE_SHARED;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->user = user;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->prefix = i_strdup(str_c(prefix));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->owner = owner;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
9762e4f86950549c8186c7d3d4fa4a6b533ea848Timo Sirainen NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->mail_set = _storage->set;
fedb7a111ba2102edce8e55a1ba77cf907c6add9Timo Sirainen i_array_init(&new_ns->all_storages, 2);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen location = t_str_new(256);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (ret > 0)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen var_expand(location, storage->location, tab);
60b42c6dfdf9edcca8a96b380ef9a0adc60c2464Timo Sirainen else {
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen get_nonexistent_user_location(storage, userdomain, location);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen if (ns->user->mail_debug) {
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen i_debug("shared: Tried to access mails of "
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen "nonexistent user %s", userdomain);
4ed1c0fedf33299264a319b2c4e0fe2465ea321bTimo Sirainen }
60b42c6dfdf9edcca8a96b380ef9a0adc60c2464Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ns_set->type = "shared";
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ns_set->prefix = new_ns->prefix;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ns_set->hidden = TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ns_set->list = "yes";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->set = ns_set;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen unexpanded_ns_set =
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen *unexpanded_ns_set = *ns_set;
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen unexpanded_ns_set->location =
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen p_strdup(user->pool, storage->unexpanded_location);
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen new_ns->unexpanded_set = unexpanded_ns_set;
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen /* We need to create a prefix="" namespace for the owner */
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen if (mail_namespaces_init_location(owner, str_c(location), &error) < 0) {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* owner gets freed by namespace deinit */
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen mail_namespace_destroy(new_ns);
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen return -1;
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen }
e9081684ea0808ed427cfd2624656d5f22fbb225Timo Sirainen
cc2c73be39dfe988f52c0370667e3882d01c63a2Timo Sirainen if (mail_storage_create(new_ns, NULL, _storage->flags |
cc2c73be39dfe988f52c0370667e3882d01c63a2Timo Sirainen MAIL_STORAGE_FLAG_NO_AUTOVERIFY, &error) < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': %s",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen new_ns->prefix, error);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* owner gets freed by namespace deinit */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_namespace_destroy(new_ns);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen !shared_namespace_exists(new_ns)) {
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen /* this user doesn't have a usable storage */
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen }
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen /* mark the shared namespace root as usable, since it now has
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen child namespaces */
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen ns->flags |= NAMESPACE_FLAG_USABLE;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen t_strconcat(new_ns->prefix, name, NULL));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *_ns = new_ns;
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen if (_storage->class_flags == 0) {
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen /* flags are unset if we were using "auto" storage */
949fa97a4ab5c62e4db73c3973e35ae3b73a2b23Timo Sirainen _storage->class_flags =
949fa97a4ab5c62e4db73c3973e35ae3b73a2b23Timo Sirainen mail_namespace_get_default_storage(new_ns)->class_flags;
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen }
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_user_add_namespace(user, &new_ns);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstruct mail_storage shared_storage = {
1a5573ebc32fae2fe576ec544e1781323c1db609Timo Sirainen .name = MAIL_SHARED_STORAGE_NAME,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .class_flags = 0, /* unknown at this point */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .v = {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen NULL,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen shared_storage_alloc,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen shared_storage_create,
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen index_storage_destroy,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen NULL,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen shared_storage_get_list_settings,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen NULL,
d00ae137b6772f0b047cc98cb153f11c5246f82bTimo Sirainen fail_mailbox_alloc,
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen NULL
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen};