shared-storage.c revision 7b64db32b95286235612eebb5d37d296a49306f7
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2008-2013 Dovecot authors, see the included COPYING file */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
f325d795b52ce2053f914072b22ebca9c4f0dc7eTimo Sirainen pool = pool_alloconly_create("shared storage", 1024);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage = p_new(pool, struct shared_storage, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char **error_r)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *driver, *p;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* location must begin with the actual mailbox driver */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen driver = t_strdup_until(ns->set->location, p);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
0f17bb103602d0c4394e3784cb96d788530fc79eTimo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen _storage->class_flags = storage_class->class_flags;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
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 *error_r = "Shared namespace prefix contains unknown variables";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
a5bb2908b44c8bf5ce41160a64c67fb840a20006Timo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* truncate prefix after the above checks are done, so they can log
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen the full prefix in error conditions */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainenget_nonexistent_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. */
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen str_append(location, storage->storage_class_name);
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen /* use a reachable but nonexistent path as the mail root directory */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen /* we can't know if this exists */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char **_name)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen static struct var_expand_table static_tab[] = {
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
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 */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen if (*p != '\0') {
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen /* trying to open <prefix>/<user> mailbox */
b1c42176a65dbe9c83a0af766e6bd8315530f3a5Timo Sirainen "Invalid namespace prefix %s vs %s",
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* successfully matched the name. */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* user@domain given */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen username = t_strdup_until(userdomain, domain);
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* trying to open namespace "shared/domain"
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen namespace prefix. */
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
0671e0ae0cfd8d5d671a0c2a75a070c8e2a39fecTimo Sirainen /* no domain given, use ours (if we have one) */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
d927bc5618696157fc55eb1f11b5cab05400ed52Timo Sirainen "Empty username doesn't exist");
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);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen "Couldn't create namespace '%s' for user %s: %s",
1453e7c587b98f93e1434aa0b147933948dbb50fTimo Sirainen } else 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) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': "
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen "Could not lookup home for user %s",
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* create the new namespace */
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;
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen get_nonexistent_user_location(storage, userdomain, location);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
d29e35631075b8c172ce781b85fd1cdaf0a400fdTimo Sirainen p_strdup(user->pool, storage->unexpanded_location);
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 */
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",
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* owner gets freed by namespace deinit */
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
512f492f410fdaefb2f58e19c2b067ef20fb4adfTimo Sirainen /* this user doesn't have a usable storage */
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen /* mark the shared namespace root as usable, since it now has
31327a74b86728e201fcedd0acaecf69d077bf1dTimo Sirainen child namespaces */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
708efcd8581258763289b95cde119ca9423641d8Timo Sirainen /* flags are unset if we were using "auto" storage */