shared-storage.c revision f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0c
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen MODULE_CONTEXT(obj, shared_mailbox_list_module)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(shared_mailbox_list_module,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen pool = pool_alloconly_create("shared storage", 256);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage = p_new(pool, struct shared_storage, 1);
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen storage->storage.storage_class = &shared_storage;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen storage->base_dir = p_strdup(pool, getenv("BASE_DIR"));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic int shared_create(struct mail_storage *_storage, const char *data,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char **error_r)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *driver, *p;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* data must begin with the actual mailbox driver */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->location = p_strdup(_storage->pool, data);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->storage_class = mail_storage_find_class(driver);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen _storage->mailbox_is_file = storage->storage_class->mailbox_is_file;
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen wildcardp = strchr(_storage->ns->prefix, '%');
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '%')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*++p == '\0')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen else if (*p != 'd')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '\0') {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mailbox_list_alloc("shared", &_storage->list, error_r) < 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen MODULE_CONTEXT_SET_FULL(_storage->list, shared_mailbox_list_module,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen list_set.mail_storage_flags = &_storage->flags;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen list_set.lock_method = &_storage->lock_method;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mailbox_list_init(_storage->list, _storage->ns, &list_set,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_storage_get_list_flags(_storage->flags));
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenget_nonexisting_user_location(struct shared_storage *storage,
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. */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen str_append(location, storage->storage_class->name);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* use a reachable but non-existing path as the mail root directory */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenint shared_storage_get_namespace(struct mail_storage *_storage,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char **_name,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen static struct var_expand_table static_tab[] = {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '%') {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen switch (*++p) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* we checked this already above */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen next = strchr(name, *p != '\0' ? *p : _storage->ns->sep);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* successfully matched the name. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen username = t_strdup_until(userdomain, domain);
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 */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen var_expand(prefix, storage->ns_prefix_pattern, tab);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen if (!var_has_key(storage->location, 'h', "home"))
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) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen mail_storage_set_critical(_storage, "Namespace '%s': "
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen "Could not lookup home for user %s",
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* create the new namespace */
4ac2d38239cea8090154e17faefd77de5a71d882Timo Sirainen ns->flags = NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen get_nonexisting_user_location(storage, userdomain, location);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mail_storage_create(ns, NULL, str_c(location), _storage->flags,
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen mail_storage_set_critical(_storage, "Namespace '%s': %s",
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic void shared_mailbox_copy_error(struct mail_storage *shared_storage,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *str;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen str = mail_storage_get_last_error(backend_ns->storage, &error);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_storage_set_error(shared_storage, error, str);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic struct mailbox *
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenshared_mailbox_open(struct mail_storage *storage, const char *name,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct istream *input, enum mailbox_open_flags flags)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen "Shared storage doesn't support streamed mailboxes");
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (shared_storage_get_namespace(storage, &name, &ns) < 0)
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen /* if we call the normal mailbox_open() here the plugins will see
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen mailbox_open() called twice and they could break. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic int shared_mailbox_create(struct mail_storage *storage,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (shared_storage_get_namespace(storage, &name, &ns) < 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ret = mail_storage_mailbox_create(ns->storage, name, directory);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen MEMBER(mailbox_is_file) FALSE, /* unknown at this point */