shared-storage.c revision b1c42176a65dbe9c83a0af766e6bd8315530f3a5
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek MODULE_CONTEXT(obj, shared_mailbox_list_module)
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židekstatic MODULE_CONTEXT_DEFINE_INIT(shared_mailbox_list_module,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek pool = pool_alloconly_create("shared storage", 1024);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek storage = p_new(pool, struct shared_storage, 1);
1a71eeb4d71f7f6d63edb4298d69b35a94edc020Jakub Hrozek storage->storage.storage_class = &shared_storage;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek storage->base_dir = p_strdup(pool, getenv("BASE_DIR"));
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židekstatic int shared_create(struct mail_storage *_storage, const char *data,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek const char **error_r)
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek struct shared_storage *storage = (struct shared_storage *)_storage;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek const char *driver, *p;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* data must begin with the actual mailbox driver */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek *error_r = "Shared mailbox location not prefixed with driver";
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek storage->location = p_strdup(_storage->pool, data);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek storage->storage_class = mail_storage_find_class(driver);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek *error_r = t_strconcat("Unknown shared storage driver: ",
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek _storage->mailbox_is_file = storage->storage_class->mailbox_is_file;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek *error_r = "Shared namespace prefix doesn't contain %";
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (*p != '%')
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (*++p == '\0')
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (*p != '\0') {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek *error_r = "Shared namespace prefix contains unknown variables";
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek *error_r = "Shared namespace prefix doesn't contain %u or %n";
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* truncate prefix after the above checks are done, so they can log
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek the full prefix in error conditions */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (mailbox_list_alloc("shared", &_storage->list, error_r) < 0)
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek MODULE_CONTEXT_SET_FULL(_storage->list, shared_mailbox_list_module,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek list_set.mail_storage_flags = &_storage->flags;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek mailbox_list_init(_storage->list, _storage->ns, &list_set, 0);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židekget_nonexisting_user_location(struct shared_storage *storage,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* user wasn't found. we'll still need to create the storage
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek to avoid exposing which users exist and which don't. */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek str_append(location, storage->storage_class->name);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* use a reachable but non-existing path as the mail root directory */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židekint shared_storage_get_namespace(struct mail_storage *_storage,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek const char **_name,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek struct shared_storage *storage = (struct shared_storage *)_storage;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek static struct var_expand_table static_tab[] = {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek const char *domain = NULL, *username = NULL, *userdomain = NULL;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (*p != '%') {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek switch (*++p) {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* we checked this already above */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek next = strchr(name, *p != '\0' ? *p : _storage->ns->sep);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (*p != '\0') {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek (name[1] == '\0' && *name == _storage->ns->sep)) {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* trying to open <prefix>/<user> mailbox */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek "Invalid namespace prefix %s vs %s",
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* successfully matched the name. */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* expand the namespace prefix and see if it already exists.
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek this should normally happen only when the mailbox is being opened */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek var_expand(prefix, storage->ns_prefix_pattern, tab);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek owner = mail_user_alloc(userdomain, user->unexpanded_set);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (!var_has_key(storage->location, 'h', "home"))
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* we'll need to look up the user's home directory */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek mail_storage_set_critical(_storage, "Namespace '%s': "
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek "Could not lookup home for user %s",
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek "Couldn't create namespace '%s' for user %s: %s",
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek /* create the new namespace */
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek ns->flags = NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek get_nonexisting_user_location(storage, userdomain, location);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek ns_set->separator = p_strdup_printf(user->pool, "%c", ns->sep);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek ns_set->location = p_strdup(user->pool, str_c(location));
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (mail_storage_create(ns, NULL, _storage->flags, &error) < 0) {
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek mail_storage_set_critical(_storage, "Namespace '%s': %s",
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židekstatic void shared_mailbox_copy_error(struct mail_storage *shared_storage,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek const char *str;
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek str = mail_storage_get_last_error(backend_ns->storage, &error);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek mail_storage_set_error(shared_storage, error, str);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židekstatic int shared_mailbox_create(struct mail_storage *storage,
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek if (shared_storage_get_namespace(storage, &name, &ns) < 0)
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek ret = mail_storage_mailbox_create(ns->storage, name, directory);
35ecfab87a24031e55798b22975e02832ee0f2adMichal Židek MEMBER(mailbox_is_file) FALSE, /* unknown at this point */