bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
dfa2201c6ac8ddb2d2798dee15662cfe774e644eMartti Rannanjärvi#include "path-util.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "ioloop.h"
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen#include "file-create-locked.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "mkdir-parents.h"
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen#include "hex-binary.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "str.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "sha1.h"
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#include "hash.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include "home-expand.h"
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen#include "time-util.h"
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#include "unichar.h"
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen#include "settings-parser.h"
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen#include "iostream-ssl.h"
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen#include "fs-api-private.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "imap-utf7.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "mailbox-log.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "mailbox-tree.h"
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen#include "mail-storage-private.h"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen#include "mail-storage-hooks.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-private.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <time.h>
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen#include <ctype.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <unistd.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <dirent.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <sys/stat.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen#define MAILBOX_LIST_LOCK_FNAME "mailboxes.lock"
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen#define MAILBOX_LIST_LOCK_SECS 60
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen#define MAILBOX_LIST_FS_CONTEXT(obj) \
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen MODULE_CONTEXT(obj, mailbox_list_fs_module)
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenstruct mailbox_list_fs_context {
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen union fs_api_module_context module_ctx;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen struct mailbox_list *list;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen};
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ARRAY(const struct mailbox_list *) mailbox_list_drivers;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_list_fs_module,
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen &fs_api_module_register);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mailbox_lists_init(void)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_array_init(&mailbox_list_drivers, 4);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mailbox_lists_deinit(void)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen array_free(&mailbox_list_drivers);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list *const *drivers;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i, count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < count; i++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *idx_r = i;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen unsigned int idx;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen list->name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_append(&mailbox_list_drivers, &list, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_delete(&mailbox_list_drivers, idx, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenconst struct mailbox_list *
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenmailbox_list_find_class(const char *driver)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const struct mailbox_list *const *class_p;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen unsigned int idx;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (!mailbox_list_driver_find(driver, &idx))
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return NULL;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return *class_p;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint mailbox_list_create(const char *driver, struct mail_namespace *ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct mailbox_list_settings *set,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen enum mailbox_list_flags flags,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen struct mailbox_list **list_r, const char **error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek const struct mailbox_list *class;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_list *list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen i_assert(ns->list == NULL ||
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen (flags & MAILBOX_LIST_FLAG_SECONDARY) != 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(set->subscription_fname == NULL ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *set->subscription_fname != '\0');
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek if ((class = mailbox_list_find_class(driver)) == NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "Unknown driver name";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek if ((class->props & MAILBOX_LIST_PROP_NO_MAILDIR_NAME) != 0 &&
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen *set->maildir_name != '\0') {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "maildir_name not supported by this driver";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek if ((class->props & MAILBOX_LIST_PROP_NO_ALT_DIR) != 0 &&
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen set->alt_dir != NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "alt_dir not supported by this driver";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0' ||
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek (class->props & MAILBOX_LIST_PROP_NO_ROOT) != 0);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek list = class->v.alloc();
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->ns = ns;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->mail_set = ns->mail_set;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->flags = flags;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen list->root_permissions.file_create_mode = (mode_t)-1;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen list->root_permissions.dir_create_mode = (mode_t)-1;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen list->root_permissions.file_create_gid = (gid_t)-1;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp = (time_t)-1;
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen if (set->no_noselect)
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen list->props |= MAILBOX_LIST_PROP_NO_NOSELECT;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* copy settings */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (set->root_dir != NULL) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.index_dir = set->index_dir == NULL ||
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen p_strdup(list->pool, set->index_dir);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen list->set.index_pvt_dir = set->index_pvt_dir == NULL ||
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen strcmp(set->index_pvt_dir, set->root_dir) == 0 ? NULL :
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen p_strdup(list->pool, set->index_pvt_dir);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen list->set.index_cache_dir = set->index_cache_dir == NULL ||
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen strcmp(set->index_cache_dir, set->root_dir) == 0 ? NULL :
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen p_strdup(list->pool, set->index_cache_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.control_dir = set->control_dir == NULL ||
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen p_strdup(list->pool, set->control_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.subscription_fname =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->subscription_fname);
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen list->set.list_index_fname =
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen p_strdup(list->pool, set->list_index_fname);
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen list->set.list_index_dir =
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen p_strdup(list->pool, set->list_index_dir);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen list->set.maildir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->maildir_name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->mailbox_dir_name);
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen list->set.alt_dir = p_strdup(list->pool, set->alt_dir);
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen list->set.alt_dir_nocheck = set->alt_dir_nocheck;
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen list->set.volatile_dir = p_strdup(list->pool, set->volatile_dir);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen list->set.index_control_use_maildir_name =
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen set->index_control_use_maildir_name;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen list->set.iter_from_index_dir = set->iter_from_index_dir;
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen list->set.no_noselect = set->no_noselect;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen if (*set->mailbox_dir_name == '\0')
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name = "";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else if (set->mailbox_dir_name[strlen(set->mailbox_dir_name)-1] == '/') {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->mailbox_dir_name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strconcat(list->pool, set->mailbox_dir_name, "/", NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
f0d09be40bd0c4423873128ae2f88a4020075dc4Timo Sirainen list->set.escape_char = set->escape_char;
f0d09be40bd0c4423873128ae2f88a4020075dc4Timo Sirainen list->set.broken_char = set->broken_char;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen list->set.utf8 = set->utf8;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (list->v.init != NULL) {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (list->v.init(list, error_r) < 0) {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen list->v.deinit(list);
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen return -1;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ns->mail_set->mail_debug) {
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen i_debug("%s: root=%s, index=%s, indexpvt=%s, control=%s, inbox=%s, alt=%s",
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->name,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.root_dir == NULL ? "" : list->set.root_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.index_dir == NULL ? "" : list->set.index_dir,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen list->set.index_pvt_dir == NULL ? "" : list->set.index_pvt_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.control_dir == NULL ?
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk "" : list->set.control_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.inbox_path == NULL ?
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen "" : list->set.inbox_path,
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen list->set.alt_dir == NULL ? "" : list->set.alt_dir);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen if ((flags & MAILBOX_LIST_FLAG_SECONDARY) == 0)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen mail_namespace_finish_list_init(ns, list);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen *list_r = list;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen hook_mailbox_list_created(list);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen return 0;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen}
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainenstatic int fix_path(struct mail_user *user, const char *path, bool expand_home,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen const char **path_r, const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen size_t len = strlen(path);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (len > 1 && path[len-1] == '/')
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen path = t_strndup(path, len-1);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (!expand_home) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* no ~ expansion */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen } else if (path[0] == '~' && path[1] != '/' && path[1] != '\0') {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* ~otheruser/dir */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (home_try_expand(&path) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "No home directory for system user. "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Can't expand ", t_strcut(path, '/'),
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen " for ", NULL);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen } else {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (mail_user_try_home_expand(user, &path) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = "Home directory not set for user. "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Can't expand ~/ for ";
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen *path_r = path;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic const char *split_next_arg(const char *const **_args)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen const char *const *args = *_args;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen const char *str = args[0];
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen while (*args != NULL && **args == '\0') {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (*args == NULL) {
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen /* string ends with ":", just ignore it. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen break;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = t_strconcat(str, ":", *args, NULL);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *_args = args;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return str;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainenvoid mailbox_list_settings_init_defaults(struct mailbox_list_settings *set_r)
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen{
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(set_r);
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen set_r->mailbox_dir_name = "";
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen set_r->maildir_name = "";
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen set_r->list_index_fname = MAILBOX_LIST_INDEX_DEFAULT_PREFIX;
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen}
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainenstatic int
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainenmailbox_list_settings_parse_full(struct mail_user *user, const char *data,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen bool expand_home,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen struct mailbox_list_settings *set_r,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen const char *const *tmp, *key, *value, **dest, *str, *fname, *error;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen mailbox_list_settings_init_defaults(set_r);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (*data == '\0')
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* <root dir> */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen tmp = t_strsplit(data, ":");
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = split_next_arg(&tmp);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (fix_path(user, str, expand_home, &set_r->root_dir, &error) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(error, "mail root dir in: ", data, NULL);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen if (strncmp(set_r->root_dir, "INBOX=", 6) == 0) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* probably mbox user trying to avoid root_dir */
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen *error_r = t_strconcat("Mail root directory not given: ",
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen data, NULL);
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen return -1;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen while (*tmp != NULL) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = split_next_arg(&tmp);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (strcmp(str, "UTF-8") == 0) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen set_r->utf8 = TRUE;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen continue;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen value = strchr(str, '=');
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (value == NULL) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen key = str;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value = "";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen } else {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen key = t_strdup_until(str, value);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value++;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (strcmp(key, "INBOX") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->inbox_path;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "INDEX") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->index_dir;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen else if (strcmp(key, "INDEXPVT") == 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen dest = &set_r->index_pvt_dir;
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen else if (strcmp(key, "INDEXCACHE") == 0)
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen dest = &set_r->index_cache_dir;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "CONTROL") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->control_dir;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else if (strcmp(key, "ALT") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->alt_dir;
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen else if (strcmp(key, "ALTNOCHECK") == 0) {
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen set_r->alt_dir_nocheck = TRUE;
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen continue;
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen } else if (strcmp(key, "LAYOUT") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->layout;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "SUBSCRIPTIONS") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->subscription_fname;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "DIRNAME") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->maildir_name;
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen else if (strcmp(key, "MAILBOXDIR") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->mailbox_dir_name;
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen else if (strcmp(key, "VOLATILEDIR") == 0)
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen dest = &set_r->volatile_dir;
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen else if (strcmp(key, "LISTINDEX") == 0)
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen dest = &set_r->list_index_fname;
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen else if (strcmp(key, "FULLDIRNAME") == 0) {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen set_r->index_control_use_maildir_name = TRUE;
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen dest = &set_r->maildir_name;
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen } else if (strcmp(key, "BROKENCHAR") == 0) {
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen if (strlen(value) != 1) {
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen *error_r = "BROKENCHAR value must be a single character";
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen return -1;
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen }
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen set_r->broken_char = value[0];
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen continue;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen } else if (strcmp(key, "ITERINDEX") == 0) {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen set_r->iter_from_index_dir = TRUE;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen continue;
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen } else if (strcmp(key, "NO-NOSELECT") == 0) {
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen set_r->no_noselect = TRUE;
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen continue;
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi } else if (strcmp(key, "NO-FS-VALIDATION") == 0) {
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi set_r->no_fs_validation = TRUE;
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi continue;
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen } else {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = t_strdup_printf("Unknown setting: %s", key);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (fix_path(user, value, expand_home, dest, &error) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(error, key, " in: ", data, NULL);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (set_r->index_dir != NULL && strcmp(set_r->index_dir, "MEMORY") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen set_r->index_dir = "";
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (set_r->iter_from_index_dir &&
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen (set_r->index_dir == NULL || set_r->index_dir[0] == '\0')) {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen *error_r = "ITERINDEX requires INDEX to be explicitly set";
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen return -1;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen }
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (set_r->list_index_fname != NULL &&
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen (fname = strrchr(set_r->list_index_fname, '/')) != NULL) {
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen /* non-default LISTINDEX directory */
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen set_r->list_index_dir =
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen t_strdup_until(set_r->list_index_fname, fname);
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen set_r->list_index_fname = fname+1;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (set_r->list_index_dir[0] != '/' &&
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen set_r->index_dir != NULL && set_r->index_dir[0] == '\0') {
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen *error_r = "LISTINDEX directory is relative but INDEX=MEMORY";
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen return -1;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen }
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainenint mailbox_list_settings_parse(struct mail_user *user, const char *data,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen struct mailbox_list_settings *set_r,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen const char **error_r)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen{
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return mailbox_list_settings_parse_full(user, data, TRUE,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen set_r, error_r);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen}
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenconst char *mailbox_list_get_unexpanded_path(struct mailbox_list *list,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen enum mailbox_list_path_type type)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const struct mail_storage_settings *mail_set;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *location = list->ns->unexpanded_set->location;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mail_user *user = list->ns->user;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mailbox_list_settings set;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen const char *p, *path, *error;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (*location == SETTING_STRVAR_EXPANDED[0]) {
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen /* set using -o or userdb lookup. */
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen return "";
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen }
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen i_assert(*location == SETTING_STRVAR_UNEXPANDED[0]);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (*location == '\0') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_set = mail_user_set_get_driver_settings(user->set_info,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen user->unexpanded_set, MAIL_STORAGE_SET_DRIVER_NAME);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i_assert(mail_set != NULL);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location = mail_set->mail_location;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (*location == SETTING_STRVAR_EXPANDED[0])
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen return "";
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen i_assert(*location == SETTING_STRVAR_UNEXPANDED[0]);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* type:settings */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strchr(location, ':');
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (mailbox_list_settings_parse_full(user, p + 1, FALSE,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen &set, &error) < 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen if (!mailbox_list_set_get_root_path(&set, type, &path))
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return "";
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return path;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainenstatic bool need_escape_dirstart(const char *vname, const char *maildir_name)
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (vname[0] == '.') {
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (vname[1] == '\0' || vname[1] == '/')
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen return TRUE; /* "." */
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (vname[1] == '.' && (vname[2] == '\0' || vname[2] == '/'))
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen return TRUE; /* ".." */
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (*maildir_name != '\0') {
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen len = strlen(maildir_name);
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (strncmp(maildir_name, vname, len) == 0 &&
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen (vname[len] == '\0' || vname[len] == '/'))
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen return TRUE; /* e.g. dbox-Mails */
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen return FALSE;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen}
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d3e5a14ea363264dcc7640ca7226249d0c27a793Timo Sirainenconst char *
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainenmailbox_list_escape_name_params(const char *vname, const char *ns_prefix,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen char ns_sep, char list_sep, char escape_char,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen const char *maildir_name)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t ns_prefix_len = strlen(ns_prefix);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen string_t *escaped_name = t_str_new(64);
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen bool dirstart = TRUE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* no escaping of namespace prefix */
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (strncmp(ns_prefix, vname, ns_prefix_len) == 0) {
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen str_append_n(escaped_name, vname, ns_prefix_len);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen vname += ns_prefix_len;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* escape the mailbox name */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (*vname == '~') {
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen str_printfa(escaped_name, "%c%02x", escape_char, *vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname++;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen dirstart = FALSE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen for (; *vname != '\0'; vname++) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (*vname == ns_sep)
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen str_append_c(escaped_name, list_sep);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else if (*vname == list_sep ||
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen *vname == escape_char ||
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen *vname == '/' ||
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen (dirstart &&
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen need_escape_dirstart(vname, maildir_name))) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_printfa(escaped_name, "%c%02x",
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen escape_char, *vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(escaped_name, *vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen dirstart = *vname == '/';
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return str_c(escaped_name);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainenconst char *
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainenmailbox_list_escape_name(struct mailbox_list *list, const char *vname)
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen{
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen return mailbox_list_escape_name_params(vname, list->ns->prefix,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen mail_namespace_get_sep(list->ns),
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen mailbox_list_get_hierarchy_sep(list),
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen list->set.escape_char, list->set.maildir_name);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen}
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenstatic int
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenmailbox_list_unescape_broken_chars(struct mailbox_list *list, char *name)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen{
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen char *src, *dest;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen unsigned char chr;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if ((src = strchr(name, list->set.broken_char)) == NULL)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 0;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen dest = src;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen while (*src != '\0') {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (*src == list->set.broken_char) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (src[1] >= '0' && src[1] <= '9')
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen chr = (src[1]-'0') * 0x10;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen else if (src[1] >= 'a' && src[1] <= 'f')
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen chr = (src[1]-'a' + 10) * 0x10;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen else
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return -1;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (src[2] >= '0' && src[2] <= '9')
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen chr += src[2]-'0';
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen else if (src[2] >= 'a' && src[2] <= 'f')
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen chr += src[2]-'a' + 10;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen else
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return -1;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen *dest++ = chr;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen src += 3;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen } else {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen *dest++ = *src++;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen *dest++ = '\0';
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 0;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen}
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenstatic char *mailbox_list_convert_sep(const char *storage_name, char src, char dest)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen{
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen char *ret, *p;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ret = p_strdup(unsafe_data_stack_pool, storage_name);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen for (p = ret; *p != '\0'; p++) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (*p == src)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen *p = dest;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return ret;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen}
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_default_get_storage_name(struct mailbox_list *list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *vname)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mail_namespace *ns = list->ns;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t prefix_len = strlen(ns->prefix);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen const char *storage_name = vname;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen string_t *str;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen char list_sep, ns_sep, *ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen if (strcasecmp(storage_name, "INBOX") == 0 &&
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen storage_name = "INBOX";
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else if (list->set.escape_char != '\0')
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen storage_name = mailbox_list_escape_name(list, vname);
494a5de15db3b2806ab31d5ecc3e1c306ae14d06Timo Sirainen
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen if (prefix_len > 0 && (strcmp(storage_name, "INBOX") != 0 ||
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen (ns->flags & NAMESPACE_FLAG_INBOX_USER) == 0)) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* skip namespace prefix, except if this is INBOX */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (strncmp(ns->prefix, storage_name, prefix_len) == 0)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen storage_name += prefix_len;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen else if (strncmp(ns->prefix, storage_name, prefix_len-1) == 0 &&
9d4c027e7de01ab948d6221bc27c9b45d32d1ea5Timo Sirainen strlen(storage_name) == prefix_len-1 &&
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns->prefix[prefix_len-1] == mail_namespace_get_sep(ns)) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* trying to access the namespace prefix itself */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen storage_name = "";
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else {
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen /* we're converting a nonexistent mailbox name,
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen such as a LIST pattern. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (!list->set.utf8) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen /* UTF-8 -> mUTF-7 conversion */
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen str = t_str_new(strlen(storage_name)*2);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (imap_utf8_to_utf7(storage_name, str) < 0)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_panic("Mailbox name not UTF-8: %s", vname);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen storage_name = str_c(str);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list_sep = mailbox_list_get_hierarchy_sep(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns_sep = mail_namespace_get_sep(ns);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen if (*storage_name == '\0' && ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen (ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0 &&
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen !list->mail_set->mail_shared_explicit_inbox) {
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen /* opening shared/$user. it's the same as INBOX. */
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen storage_name = "INBOX";
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen }
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen if (list_sep != ns_sep && list->set.escape_char == '\0') {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* shared namespace root. the backend storage's
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen hierarchy separator isn't known yet, so do
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen nothing. */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return storage_name;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ret = mailbox_list_convert_sep(storage_name, ns_sep, list_sep);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen } else if (list->set.broken_char == '\0' ||
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen strchr(storage_name, list->set.broken_char) == NULL) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* no need to convert broken chars */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen return storage_name;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen } else {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ret = p_strdup(unsafe_data_stack_pool, storage_name);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (list->set.broken_char != '\0') {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (mailbox_list_unescape_broken_chars(list, ret) < 0) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ret = mailbox_list_convert_sep(storage_name,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ns_sep, list_sep);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_get_storage_name(struct mailbox_list *list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *vname)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->v.get_storage_name(list, vname);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
d3e5a14ea363264dcc7640ca7226249d0c27a793Timo Sirainenconst char *
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainenmailbox_list_unescape_name_params(const char *src, const char *ns_prefix,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen char ns_sep, char list_sep, char escape_char)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t ns_prefix_len = strlen(ns_prefix);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen string_t *dest = t_str_new(strlen(src));
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen unsigned int num;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (strncmp(src, ns_prefix, ns_prefix_len) == 0) {
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen str_append_n(dest, src, ns_prefix_len);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen src += ns_prefix_len;
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen }
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen for (; *src != '\0'; src++) {
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (*src == escape_char &&
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_isxdigit(src[1]) && i_isxdigit(src[2])) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (src[1] >= '0' && src[1] <= '9')
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num = src[1] - '0';
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num = i_toupper(src[1]) - 'A' + 10;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num *= 16;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (src[2] >= '0' && src[2] <= '9')
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num += src[2] - '0';
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num += i_toupper(src[2]) - 'A' + 10;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(dest, num);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen src += 2;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else if (*src == list_sep)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(dest, ns_sep);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(dest, *src);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return str_c(dest);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainenconst char *
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainenmailbox_list_unescape_name(struct mailbox_list *list, const char *src)
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen{
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen return mailbox_list_unescape_name_params(src, list->ns->prefix,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen mail_namespace_get_sep(list->ns),
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen mailbox_list_get_hierarchy_sep(list),
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen list->set.escape_char);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen}
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenstatic void
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenmailbox_list_escape_broken_chars(struct mailbox_list *list, string_t *str)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen{
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen unsigned int i;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen char buf[3];
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (strchr(str_c(str), list->set.broken_char) == NULL)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen for (i = 0; i < str_len(str); i++) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (str_c(str)[i] == list->set.broken_char) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen i_snprintf(buf, sizeof(buf), "%02x",
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen list->set.broken_char);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen str_insert(str, i+1, buf);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen i += 2;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen}
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenstatic void
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenmailbox_list_escape_broken_name(struct mailbox_list *list,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen const char *vname, string_t *str)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen{
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen str_truncate(str, 0);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen for (; *vname != '\0'; vname++) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (*vname == '&' || (unsigned char)*vname >= 0x80) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen str_printfa(str, "%c%02x", list->set.broken_char,
1f4399a277b861419b82758ab0462e90c00a4c41Timo Sirainen (unsigned char)*vname);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen } else {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen str_append_c(str, *vname);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen}
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_default_get_vname(struct mailbox_list *list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *storage_name)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t i, prefix_len, name_len;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen const char *vname = storage_name;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen char list_sep, ns_sep, *ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen strcmp(vname, "INBOX") == 0 &&
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list->ns->user == list->ns->owner) {
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen /* user's INBOX - use as-is. NOTE: don't do case-insensitive
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen comparison, otherwise we can't differentiate between INBOX
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen and <ns prefix>/inBox. */
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen return vname;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen if (strcmp(vname, "INBOX") == 0 &&
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen list->ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen (list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0 &&
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen !list->mail_set->mail_shared_explicit_inbox) {
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen /* convert to shared/$user, we don't really care about the
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen INBOX suffix here. */
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen vname = "";
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (*vname == '\0') {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* return namespace prefix without the separator */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (list->ns->prefix_len == 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->ns->prefix;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen else {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return t_strndup(list->ns->prefix,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list->ns->prefix_len - 1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen } else if (!list->set.utf8) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* mUTF-7 -> UTF-8 conversion */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen string_t *str = t_str_new(strlen(vname));
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (imap_utf7_to_utf8(vname, str) == 0) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (list->set.broken_char != '\0')
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mailbox_list_escape_broken_chars(list, str);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen vname = str_c(str);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen } else if (list->set.broken_char != '\0') {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mailbox_list_escape_broken_name(list, vname, str);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen vname = str_c(str);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen prefix_len = strlen(list->ns->prefix);
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen if (list->set.escape_char != '\0') {
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen vname = mailbox_list_unescape_name(list, vname);
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen return prefix_len == 0 ? vname :
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen t_strconcat(list->ns->prefix, vname, NULL);
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen }
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list_sep = mailbox_list_get_hierarchy_sep(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns_sep = mail_namespace_get_sep(list->ns);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (list_sep != ns_sep || prefix_len > 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* @UNSAFE */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen name_len = strlen(vname);
e7d0bea63a08b08c47c4b5c187d2cb7127859657Timo Sirainen ret = t_malloc_no0(MALLOC_ADD(prefix_len, name_len) + 1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen memcpy(ret, list->ns->prefix, prefix_len);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen for (i = 0; i < name_len; i++) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ret[i + prefix_len] =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname[i] == list_sep ? ns_sep : vname[i];
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ret[i + prefix_len] = '\0';
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname = ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return vname;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_get_vname(struct mailbox_list *list, const char *name)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->v.get_vname(list, name);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid mailbox_list_destroy(struct mailbox_list **_list)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mailbox_list *list = *_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *_list = NULL;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi i_free(list->last_internal_error);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (hash_table_is_created(list->guid_cache)) {
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen hash_table_destroy(&list->guid_cache);
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen pool_unref(&list->guid_cache_pool);
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen }
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen if (list->subscriptions != NULL)
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen mailbox_tree_deinit(&list->subscriptions);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen if (list->changelog != NULL)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen mailbox_log_free(&list->changelog);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen if (array_is_created(&list->error_stack)) {
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen i_assert(array_count(&list->error_stack) == 0);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen array_free(&list->error_stack);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->v.deinit(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenconst char *mailbox_list_get_driver_name(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->name;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainenconst struct mailbox_list_settings *
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainenmailbox_list_get_settings(const struct mailbox_list *list)
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen{
e36574dadcac802d6780fa94ee45951e75594c96Timo Sirainen return &list->set;
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen}
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenenum mailbox_list_flags mailbox_list_get_flags(const struct mailbox_list *list)
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen{
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen return list->flags;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenstruct mail_namespace *
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenmailbox_list_get_namespace(const struct mailbox_list *list)
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen{
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen return list->ns;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainenstatic mode_t get_dir_mode(mode_t mode)
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen{
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen /* add the execute bit if either read or write bit is set */
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0600) != 0) mode |= 0100;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0060) != 0) mode |= 0010;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0006) != 0) mode |= 0001;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen return mode;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen}
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstruct mail_user *
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenmailbox_list_get_user(const struct mailbox_list *list)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return list->ns->user;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainenstatic int
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainenmailbox_list_get_storage_driver(struct mailbox_list *list, const char *driver,
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen struct mail_storage **storage_r)
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen{
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen struct mail_storage *const *storagep;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen const char *error, *data;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen array_foreach(&list->ns->all_storages, storagep) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen if (strcmp((*storagep)->name, driver) == 0) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen *storage_r = *storagep;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return 0;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen }
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen }
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
4b1781e4c64be52e25b5994e5242dbe696cc7d29Timo Sirainen data = i_strchr_to_next(list->ns->set->location, ':');
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen if (data == NULL)
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen data = "";
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen if (mail_storage_create_full(list->ns, driver, data, 0,
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen storage_r, &error) < 0) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen mailbox_list_set_critical(list,
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen "Namespace %s: Failed to create storage '%s': %s",
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen list->ns->prefix, driver, error);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return -1;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen }
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return 0;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen}
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenint mailbox_list_get_storage(struct mailbox_list **list, const char *vname,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage **storage_r)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen const struct mailbox_settings *set;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((*list)->v.get_storage != NULL)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return (*list)->v.get_storage(list, vname, storage_r);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
15bfe73fb3988bb80e6afe6a60b9a715c7207600Timo Sirainen set = mailbox_settings_find((*list)->ns, vname);
4809537f0c5a2e1cee9559ec842cc869884d2cb7Timo Sirainen if (set != NULL && set->driver != NULL && set->driver[0] != '\0') {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return mailbox_list_get_storage_driver(*list, set->driver,
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen storage_r);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen *storage_r = mail_namespace_get_default_storage((*list)->ns);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
8709b2fe6ec2b5ca1d90a63490f8371472062efdTimo Sirainenvoid mailbox_list_get_default_storage(struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage **storage)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
949fa97a4ab5c62e4db73c3973e35ae3b73a2b23Timo Sirainen *storage = mail_namespace_get_default_storage(list->ns);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenchar mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen /* the current API doesn't allow returning an error, so imap code
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen looks at the list's last error. make sure the error is cleared
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen so the error-check doesn't return something irrelevant */
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen mailbox_list_clear_error(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->v.get_hierarchy_sep(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainenstatic bool
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainenmailbox_list_get_permissions_stat(struct mailbox_list *list, const char *path,
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen struct mailbox_permissions *permissions_r)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen{
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen struct stat st;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (stat(path, &st) < 0) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (errno == EACCES) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mailbox_list_set_critical(list, "%s",
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mail_error_eacces_msg("stat", path));
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else if (!ENOTFOUND(errno)) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m",
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen path);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else if (list->mail_set->mail_debug) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen i_debug("Namespace %s: %s doesn't exist yet, "
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen "using default permissions",
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen list->ns->prefix, path);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return FALSE;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_uid = st.st_uid;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_gid = st.st_gid;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_mode = (st.st_mode & 0666) | 0600;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->dir_create_mode = (st.st_mode & 0777) | 0700;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_gid_origin = path;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (!S_ISDIR(st.st_mode)) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* we're getting permissions from a file.
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen apply +x modes as necessary. */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->dir_create_mode =
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen get_dir_mode(permissions_r->dir_create_mode);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* directory's GID is used automatically for new files */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_gid = (gid_t)-1;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else if ((st.st_mode & 0070) >> 3 == (st.st_mode & 0007)) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* group has same permissions as world, so don't bother
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen changing it */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_gid = (gid_t)-1;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else if (getegid() == st.st_gid) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* using our own gid, no need to change it */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_gid = (gid_t)-1;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_gid = st.st_gid;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (!S_ISDIR(st.st_mode) &&
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_gid != (gid_t)-1) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* we need to stat() the parent directory to see if
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen it has setgid-bit set */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen const char *p = strrchr(path, '/');
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen const char *parent_path = p == NULL ? NULL :
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen t_strdup_until(path, p);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (parent_path != NULL &&
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen stat(parent_path, &st) == 0 &&
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen (st.st_mode & S_ISGID) != 0) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* directory's GID is used automatically for
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen new files */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->file_create_gid = (gid_t)-1;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return TRUE;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen}
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void ATTR_NULL(2)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenmailbox_list_get_permissions_internal(struct mailbox_list *list,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen const char *name,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen struct mailbox_permissions *permissions_r)
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen{
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen const char *path = NULL, *parent_name, *p;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(permissions_r);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* use safe defaults */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_uid = (uid_t)-1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_gid = (gid_t)-1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_mode = 0600;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->dir_create_mode = 0700;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid = (gid_t)-1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid_origin = "defaults";
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen if (list->set.iter_from_index_dir ||
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen (list->flags & MAILBOX_LIST_FLAG_NO_MAIL_FILES) != 0) {
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen /* a) iterating from index dir. Use the index dir's permissions
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen as well, since they might be in a faster storage.
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen b) mail files don't exist in storage, but index files
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen might. */
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen (void)mailbox_list_get_path(list, name,
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX, &path);
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen }
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen if (name != NULL && path == NULL) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path) < 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen name = NULL;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen if (name == NULL && path == NULL) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen (void)mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_DIR,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
758d8b46f9e8fd87cf58bb4912cddf6bf28918cfTimo Sirainen
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen if (path == NULL) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* no filesystem support in storage */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else if (mailbox_list_get_permissions_stat(list, path, permissions_r)) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* got permissions from the given path */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r->gid_origin_is_mailbox_path = name != NULL;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else if (name != NULL) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* path couldn't be stat()ed, try parent mailbox */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen p = strrchr(name, mailbox_list_get_hierarchy_sep(list));
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (p == NULL) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* return root defaults */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen parent_name = NULL;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen parent_name = t_strdup_until(name, p);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mailbox_list_get_permissions(list, parent_name,
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen permissions_r);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else {
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen /* assume current defaults for mailboxes that don't exist or
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen can't be looked up for some other reason */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_uid = geteuid();
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_gid = getegid();
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen }
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (name == NULL) {
2f552aa8fb0fc86473c2d7dea85d8237373fb35fTimo Sirainen mailbox_permissions_copy(&list->root_permissions, permissions_r,
2f552aa8fb0fc86473c2d7dea85d8237373fb35fTimo Sirainen list->pool);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen if (list->mail_set->mail_debug && name == NULL) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("Namespace %s: Using permissions from %s: "
dbc86748934bc34826d9cc8c43d24df09b3ba402Timo Sirainen "mode=0%o gid=%s", list->ns->prefix,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen path != NULL ? path : "",
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen (int)permissions_r->dir_create_mode,
dbc86748934bc34826d9cc8c43d24df09b3ba402Timo Sirainen permissions_r->file_create_gid == (gid_t)-1 ? "default" :
dbc86748934bc34826d9cc8c43d24df09b3ba402Timo Sirainen dec2str(permissions_r->file_create_gid));
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen }
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen}
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenvoid mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen struct mailbox_permissions *permissions_r)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen{
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen mailbox_list_get_permissions_internal(list, name, permissions_r);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen}
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainenvoid mailbox_list_get_root_permissions(struct mailbox_list *list,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen struct mailbox_permissions *permissions_r)
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainen{
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (list->root_permissions.file_create_mode != (mode_t)-1)
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen *permissions_r = list->root_permissions;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen else {
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen mailbox_list_get_permissions_internal(list, NULL,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen permissions_r);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen}
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainenvoid mailbox_permissions_copy(struct mailbox_permissions *dest,
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen const struct mailbox_permissions *src,
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen pool_t pool)
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen{
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen *dest = *src;
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen dest->file_create_gid_origin =
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen p_strdup(pool, src->file_create_gid_origin);
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen}
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic const char *
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenget_expanded_path(const char *unexpanded_start, const char *unexpanded_stop,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *expanded_full)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unsigned int i, slash_count = 0, slash2_count = 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* get the expanded path up to the same amount of '/' characters.
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if there isn't the same amount of '/' characters, it means %variable
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expansion added more of them and we can't handle this. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; unexpanded_start+i != unexpanded_stop; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (unexpanded_start[i] == '/')
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash_count++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (; unexpanded_start[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (unexpanded_start[i] == '/')
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash2_count++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; expanded_full[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (expanded_full[i] == '/') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash_count == 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen break;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash_count--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash_count != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen ret = t_strndup(expanded_full, i);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (; expanded_full[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (expanded_full[i] == '/') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash2_count == 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash2_count--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash2_count != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainenstatic int
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainenmailbox_list_try_mkdir_root_parent(struct mailbox_list *list,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen enum mailbox_list_path_type type,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen struct mailbox_permissions *perm,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen const char **error_r)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen const char *expanded, *unexpanded, *root_dir, *p;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct stat st;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen bool home = FALSE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* get the directory path up to last %variable. for example
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unexpanded path may be "/var/mail/%d/%2n/%n/Maildir", and we want
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen to get expanded="/var/mail/domain/nn" */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unexpanded = mailbox_list_get_unexpanded_path(list, type);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strrchr(unexpanded, '%');
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if ((p == unexpanded && p[1] == 'h') ||
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen (p == NULL && unexpanded[0] == '~')) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* home directory used */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (!mailbox_list_get_root_path(list, type, &expanded))
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen i_unreached();
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen home = TRUE;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen } else if (p == NULL) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return 0;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen } else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen while (p != unexpanded && *p != '/') p--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == unexpanded)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return 0;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (!mailbox_list_get_root_path(list, type, &expanded))
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen i_unreached();
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen expanded = get_expanded_path(unexpanded, p, expanded);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (*expanded == '\0')
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* get the first existing parent directory's permissions */
70a2782edc5cb342ed67a46ce30a95ca316f86c9Timo Sirainen if (stat_first_parent(expanded, &root_dir, &st) < 0) {
c905571984fe8ccdb6f2a266b813f19b0643a66cTimo Sirainen *error_r = errno == EACCES ?
c905571984fe8ccdb6f2a266b813f19b0643a66cTimo Sirainen mail_error_eacces_msg("stat", root_dir) :
c905571984fe8ccdb6f2a266b813f19b0643a66cTimo Sirainen t_strdup_printf("stat(%s) failed: %m", root_dir);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return -1;
70a2782edc5cb342ed67a46ce30a95ca316f86c9Timo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* if the parent directory doesn't have setgid-bit enabled, we don't
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen copy any permissions from it. */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if ((st.st_mode & S_ISGID) == 0)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return 0;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (!home) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* assuming we have e.g. /var/vmail/%d/%n directory, here we
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen want to create up to /var/vmail/%d with permissions from
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen the parent directory. we never want to create the %n
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen directory itself. */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (root_dir == expanded) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* this is the %n directory */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen } else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mkdir_parents_chgrp(expanded, st.st_mode,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (gid_t)-1, root_dir) < 0 &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen errno != EEXIST) {
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen *error_r = t_strdup_printf(
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "mkdir(%s) failed: %m", expanded);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (perm->file_create_gid == (gid_t)-1 &&
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen (perm->dir_create_mode & S_ISGID) == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* change the group for user directories */
2cb0a0438b625cd399a4aaa0615d69f4b54d349aTimo Sirainen perm->dir_create_mode |= S_ISGID;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen perm->file_create_gid = getegid();
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen perm->file_create_gid_origin = "egid";
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen perm->gid_origin_is_mailbox_path = FALSE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen } else {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* when using %h and the parent has setgid-bit,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen copy the permissions from it for the home we're creating */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen perm->file_create_mode = st.st_mode & 0666;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen perm->dir_create_mode = st.st_mode;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen perm->file_create_gid = (gid_t)-1;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen perm->file_create_gid_origin = "parent";
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen perm->gid_origin_is_mailbox_path = FALSE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen return 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen}
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainenint mailbox_list_try_mkdir_root(struct mailbox_list *list, const char *path,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen enum mailbox_list_path_type type,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen const char **error_r)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen{
4a14ae55292476bc0b8eb314d602a262ab094a52Timo Sirainen const char *root_dir;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen struct stat st;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen struct mailbox_permissions perm;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (stat(path, &st) == 0) {
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen /* looks like it already exists, don't bother checking
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen further. */
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen if (!S_ISDIR(st.st_mode)) {
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen *error_r = t_strdup_printf(
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen "Root directory is a file: %s", path);
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen return -1;
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen }
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen return 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen }
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen mailbox_list_get_root_permissions(list, &perm);
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (!mailbox_list_get_root_path(list, type, &root_dir))
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen i_assert(strncmp(root_dir, path, strlen(root_dir)) == 0);
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (strcmp(root_dir, path) != 0 && stat(root_dir, &st) == 0) {
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen /* creating a subdirectory under an already existing root dir.
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen use the root's permissions */
4a14ae55292476bc0b8eb314d602a262ab094a52Timo Sirainen } else {
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (mailbox_list_try_mkdir_root_parent(list, type,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen &perm, error_r) < 0)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen return -1;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* the rest of the directories exist only for one user. create them
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen with default directory permissions */
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (mkdir_parents_chgrp(path, perm.dir_create_mode,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen perm.file_create_gid,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen perm.file_create_gid_origin) < 0 &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen errno != EEXIST) {
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen if (errno == EACCES)
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen *error_r = mail_error_create_eacces_msg("mkdir", path);
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen else
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen *error_r = t_strdup_printf("mkdir(%s) failed: %m", path);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainenint mailbox_list_mkdir_root(struct mailbox_list *list, const char *path,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen enum mailbox_list_path_type type)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen{
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen const char *error;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (mailbox_list_try_mkdir_root(list, path, type, &error) < 0) {
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen mailbox_list_set_critical(list, "%s", error);
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen return -1;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen }
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen if (type == MAILBOX_LIST_PATH_TYPE_INDEX)
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen list->index_root_dir_created = TRUE;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen return 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen}
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainenstatic bool
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainenmailbox_list_is_valid_fs_name(struct mailbox_list *list, const char *name,
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen const char **error_r)
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen{
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen bool ret, allow_internal_dirs;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = NULL;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi if (list->mail_set->mail_full_filesystem_access ||
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi list->set.no_fs_validation)
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen return TRUE;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen /* either the list backend uses '/' as the hierarchy separator or
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen it doesn't use filesystem at all (PROP_NO_ROOT) */
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen if ((list->props & MAILBOX_LIST_PROP_NO_ROOT) == 0 &&
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen mailbox_list_get_hierarchy_sep(list) != '/' &&
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen strchr(name, '/') != NULL) {
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen *error_r = "Name must not have '/' characters";
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen return FALSE;
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen }
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen /* make sure it's not absolute path */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (*name == '/') {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = "Begins with '/'";
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return FALSE;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (*name == '~') {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = "Begins with '~'";
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen return FALSE;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen /* make sure the mailbox name doesn't contain any foolishness:
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen "../" could give access outside the mailbox directory.
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen "./" and "//" could fool ACL checks.
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen some mailbox formats have reserved directory names, such as
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen Maildir's cur/new/tmp. if any of those would conflict with the
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen mailbox directory name, it's not valid. */
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen allow_internal_dirs = list->v.is_internal_name == NULL ||
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen *list->set.maildir_name != '\0' ||
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen (list->props & MAILBOX_LIST_PROP_NO_INTERNAL_NAMES) != 0;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen T_BEGIN {
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen const char *const *names;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen names = t_strsplit(name, "/");
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen for (; *names != NULL; names++) {
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen const char *n = *names;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (*n == '\0') {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = "Has adjacent '/' chars";
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen break; /* // */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen if (*n == '.') {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (n[1] == '\0') {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = "Contains '.' part";
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen break; /* ./ */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (n[1] == '.' && n[2] == '\0') {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = "Contains '..' part";
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen break; /* ../ */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen if (*list->set.maildir_name != '\0' &&
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen strcmp(list->set.maildir_name, n) == 0) {
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen /* don't allow maildir_name to be used as part
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen of the mailbox name */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = "Contains reserved name";
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen break;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen if (!allow_internal_dirs &&
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen list->v.is_internal_name(list, n)) {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *error_r = "Contains reserved name";
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen break;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen ret = *names == NULL;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen } T_END;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen return ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainenbool mailbox_list_is_valid_name(struct mailbox_list *list,
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen const char *name, const char **error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen if (*name == '\0') {
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen if (*list->ns->prefix != '\0') {
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen /* an ugly way to get to mailbox root (e.g. Maildir/
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen when it's not the INBOX) */
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen return TRUE;
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen }
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen *error_r = "Name is empty";
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen return FALSE;
625042f95d7eb71f6b94a61ea4f461866be1bef9Timo Sirainen }
625042f95d7eb71f6b94a61ea4f461866be1bef9Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return mailbox_list_is_valid_fs_name(list, name, error_r);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenint mailbox_list_get_path(struct mailbox_list *list, const char *name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen enum mailbox_list_path_type type,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen const char **path_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen int ret;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if ((ret = list->v.get_path(list, name, type, path_r)) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = NULL;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen else
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_assert(*path_r != NULL);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenbool mailbox_list_get_root_path(struct mailbox_list *list,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen enum mailbox_list_path_type type,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen const char **path_r)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen int ret;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if ((ret = list->v.get_path(list, NULL, type, path_r)) < 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (ret == 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = NULL;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen else
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_assert(*path_r != NULL);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return ret > 0;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen}
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenconst char *mailbox_list_get_root_forced(struct mailbox_list *list,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen enum mailbox_list_path_type type)
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen{
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen const char *path;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (!mailbox_list_get_root_path(list, type, &path))
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return path;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen}
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenbool mailbox_list_set_get_root_path(const struct mailbox_list_settings *set,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen enum mailbox_list_path_type type,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen const char **path_r)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen const char *path = NULL;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen switch (type) {
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = set->root_dir;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen break;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = set->alt_dir;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen break;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (*set->mailbox_dir_name == '\0')
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = set->root_dir;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen else {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = t_strconcat(set->root_dir, "/",
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen set->mailbox_dir_name, NULL);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = t_strndup(path, strlen(path)-1);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen break;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (*set->mailbox_dir_name == '\0')
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = set->root_dir;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen else if (set->alt_dir != NULL) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = t_strconcat(set->alt_dir, "/",
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen set->mailbox_dir_name, NULL);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = t_strndup(path, strlen(path)-1);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen break;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = set->control_dir != NULL ?
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->control_dir : set->root_dir;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen break;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (set->list_index_dir != NULL) {
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (set->list_index_dir[0] == '/') {
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen path = set->list_index_dir;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen break;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen }
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen /* relative path */
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (!mailbox_list_set_get_root_path(set,
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX, &path))
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen i_unreached();
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen path = t_strconcat(path, "/", set->list_index_dir, NULL);
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen break;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen }
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen /* fall through - default to index directory */
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX_CACHE:
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen if (set->index_cache_dir != NULL &&
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen type == MAILBOX_LIST_PATH_TYPE_INDEX_CACHE) {
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen path = set->index_cache_dir;
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen break;
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen }
82e7761750881b85128ccb2e4d4d06075ca36050Martti Rannanjärvi /* fall through */
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX:
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen if (set->index_dir != NULL) {
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen if (set->index_dir[0] == '\0') {
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen /* in-memory indexes */
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen return 0;
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen }
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen path = set->index_dir;
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen } else {
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen path = set->root_dir;
5c95939662dc6e4317f4eec60289bb12fd51982bTimo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen break;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = set->index_pvt_dir;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen break;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = path;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return path != NULL;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen}
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return list->v.get_temp_prefix(list, FALSE);
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen}
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainenconst char *mailbox_list_get_global_temp_prefix(struct mailbox_list *list)
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen{
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return list->v.get_temp_prefix(list, TRUE);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenconst char *mailbox_list_join_refpattern(struct mailbox_list *list,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen const char *ref, const char *pattern)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen{
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen if (list->v.join_refpattern != NULL)
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return list->v.join_refpattern(list, ref, pattern);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen /* the default implementation: */
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen if (*ref != '\0') {
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen /* merge reference and pattern */
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen pattern = t_strconcat(ref, pattern, NULL);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen }
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return pattern;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen}
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainenint mailbox_has_children(struct mailbox_list *list, const char *name)
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen{
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen struct mailbox_list_iterate_context *iter;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen const char *pattern;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen int ret;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen pattern = t_strdup_printf("%s%c%%", name,
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen mail_namespace_get_sep(list->ns));
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen iter = mailbox_list_iter_init(list, pattern,
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen ret = mailbox_list_iter_next(iter) != NULL ? 1 : 0;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen if (mailbox_list_iter_deinit(&iter) < 0)
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen ret = -1;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen return ret;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen}
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainenint mailbox_list_mailbox(struct mailbox_list *list, const char *name,
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen enum mailbox_info_flags *flags_r)
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen{
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen const char *path, *fname, *rootdir, *dir, *inbox;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len;
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
688d869f3449827ac9b5a0a02dbc1b27177b6d20Timo Sirainen *flags_r = 0;
688d869f3449827ac9b5a0a02dbc1b27177b6d20Timo Sirainen
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen strcasecmp(name, "INBOX") == 0) {
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen /* special handling for INBOX, mainly because with Maildir++
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen layout it needs to check if the cur/ directory exists,
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen which the Maildir++ layout backend itself can't do.. */
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen struct mailbox *box;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen enum mailbox_existence existence;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen int ret;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen /* kludge: with imapc backend we can get here with
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen list=Maildir++ (for indexes), but list->ns->list=imapc */
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen box = mailbox_alloc(list->ns->list, "INBOX", 0);
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen ret = mailbox_exists(box, FALSE, &existence);
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen if (ret < 0) {
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen const char *errstr;
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen enum mail_error error;
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen /* internal error or with imapc we can get here with
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen login failures */
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen errstr = mailbox_get_last_error(box, &error);
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen mailbox_list_set_error(list, error, errstr);
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen }
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen mailbox_free(&box);
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen if (ret < 0)
d3d2e50d6217e29fbc9c72d14c812c02dee291efTimo Sirainen return -1;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen switch (existence) {
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen case MAILBOX_EXISTENCE_NONE:
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen case MAILBOX_EXISTENCE_NOSELECT:
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen *flags_r |= MAILBOX_NONEXISTENT;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen return 0;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen case MAILBOX_EXISTENCE_SELECT:
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen break;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen }
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen return 1;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen }
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen if (list->v.get_mailbox_flags == NULL) {
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen /* can't do this optimized. do it the slow way. */
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen struct mailbox_list_iterate_context *iter;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen const struct mailbox_info *info;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen const char *vname;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen vname = mailbox_list_get_vname(list, name);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen iter = mailbox_list_iter_init(list, vname, 0);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen info = mailbox_list_iter_next(iter);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen if (info == NULL)
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen *flags_r = MAILBOX_NONEXISTENT;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen else
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen *flags_r = info->flags;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen return mailbox_list_iter_deinit(&iter);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen }
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (!list->set.iter_from_index_dir) {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen rootdir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_MAILBOX);
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR, &path) <= 0)
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen i_unreached();
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen } else {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen rootdir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_INDEX);
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX, &path) <= 0)
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen i_unreached();
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen }
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen fname = strrchr(path, '/');
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen if (fname == NULL) {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen fname = path;
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen dir = "/";
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen } else {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen dir = t_strdup_until(path, fname);
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen fname++;
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen }
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen len = strlen(rootdir);
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen if (strncmp(path, rootdir, len) == 0 && path[len] == '/') {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen /* looking up a regular mailbox under mail root dir */
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen } else if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen strcasecmp(name, "INBOX") == 0) {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen /* looking up INBOX that's elsewhere */
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen } else {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen /* looking up the root dir itself */
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen dir = path;
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen fname = "";
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen }
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen if (*fname == '\0' && *name == '\0' &&
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen /* if INBOX is in e.g. ~/Maildir, it shouldn't be possible to
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen access it also via namespace prefix. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, "INBOX",
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &inbox) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen if (strcmp(inbox, dir) == 0) {
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen *flags_r |= MAILBOX_NONEXISTENT;
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen return 0;
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen }
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen }
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen return list->v.get_mailbox_flags(list, dir, fname,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen MAILBOX_LIST_FILE_TYPE_UNKNOWN,
fb365addee8210c28e6856e34d690dd8d1636993Timo Sirainen flags_r);
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen}
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainenstatic bool mailbox_list_init_changelog(struct mailbox_list *list)
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen{
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen struct mailbox_permissions perm;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen const char *path;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen if (list->changelog != NULL)
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return TRUE;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen /* don't do this in mailbox_list_create(), because _get_path() might be
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen overridden by storage (mbox). */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX, &path))
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return FALSE;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen path = t_strconcat(path, "/"MAILBOX_LOG_FILE_NAME, NULL);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen list->changelog = mailbox_log_alloc(path);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen mailbox_list_get_root_permissions(list, &perm);
db7ca286e3ef53f73a3e8e46104a31247ebfe213Timo Sirainen mailbox_log_set_permissions(list->changelog, perm.file_create_mode,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen perm.file_create_gid,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen perm.file_create_gid_origin);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen return TRUE;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen}
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainenint mailbox_list_mkdir_missing_index_root(struct mailbox_list *list)
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen{
d95773f272b0475ac0e51b96f603a28e8674e8f1Timo Sirainen const char *index_dir;
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen if (list->index_root_dir_created)
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen return 1;
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen
d95773f272b0475ac0e51b96f603a28e8674e8f1Timo Sirainen /* If index root dir hasn't been created yet, do it now.
d95773f272b0475ac0e51b96f603a28e8674e8f1Timo Sirainen Do this here even if the index directory is the same as mail root
d95773f272b0475ac0e51b96f603a28e8674e8f1Timo Sirainen directory, because it may not have been created elsewhere either. */
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX,
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen &index_dir))
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen return 0;
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen
d95773f272b0475ac0e51b96f603a28e8674e8f1Timo Sirainen if (mailbox_list_mkdir_root(list, index_dir,
d95773f272b0475ac0e51b96f603a28e8674e8f1Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX) < 0)
d95773f272b0475ac0e51b96f603a28e8674e8f1Timo Sirainen return -1;
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen list->index_root_dir_created = TRUE;
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen return 1;
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen}
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainenint mailbox_list_mkdir_missing_list_index_root(struct mailbox_list *list)
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen{
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen const char *index_dir;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (list->set.list_index_dir == NULL)
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen return mailbox_list_mkdir_missing_index_root(list);
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen /* LISTINDEX points outside the index root directory */
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (list->list_index_root_dir_created)
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen return 1;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_LIST_INDEX,
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen &index_dir))
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen return 0;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (mailbox_list_mkdir_root(list, index_dir,
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen MAILBOX_LIST_PATH_TYPE_LIST_INDEX) < 0)
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen return -1;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen list->list_index_root_dir_created = TRUE;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen return 1;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen}
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenvoid mailbox_list_add_change(struct mailbox_list *list,
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen enum mailbox_log_record_type type,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen const guid_128_t mailbox_guid)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen{
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen struct mailbox_log_record rec;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen time_t stamp;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen if (!mailbox_list_init_changelog(list) ||
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_is_empty(mailbox_guid))
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen if (mailbox_list_mkdir_missing_index_root(list) <= 0)
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen return;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen stamp = list->changelog_timestamp != (time_t)-1 ?
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp : ioloop_time;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&rec);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen rec.type = type;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen memcpy(rec.mailbox_guid, mailbox_guid, sizeof(rec.mailbox_guid));
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen mailbox_log_record_set_timestamp(&rec, stamp);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen (void)mailbox_log_append(list->changelog, &rec);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen}
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name, bool set)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen int ret;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen /* make sure we'll refresh the file on next list */
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen list->subscriptions_mtime = (time_t)-1;
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen if ((ret = list->v.set_subscribed(list, name, set)) <= 0)
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen return ret;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainenint mailbox_list_delete_dir(struct mailbox_list *list, const char *name)
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen{
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen const char *error;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (!mailbox_list_is_valid_name(list, name, &error) || *name == '\0') {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen "Invalid mailbox name");
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen }
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return list->v.delete_dir(list, name);
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen}
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainenint mailbox_list_delete_symlink(struct mailbox_list *list, const char *name)
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen{
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen const char *error;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (!mailbox_list_is_valid_name(list, name, &error) || *name == '\0') {
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen "Invalid mailbox name");
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen return -1;
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen }
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen return list->v.delete_symlink(list, name);
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen}
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainenvoid mailbox_name_get_sha128(const char *name, guid_128_t guid_128_r)
0185427dd52fddec6fc76d6e99c7659620d4366eTimo Sirainen{
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen unsigned char sha[SHA1_RESULTLEN];
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen sha1_get_digest(name, strlen(name), sha);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen memcpy(guid_128_r, sha, I_MIN(GUID_128_SIZE, sizeof(sha)));
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen}
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstruct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen{
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return !mailbox_list_init_changelog(list) ? NULL : list->changelog;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen}
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainenvoid mailbox_list_set_changelog_timestamp(struct mailbox_list *list,
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen time_t stamp)
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen{
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp = stamp;
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen}
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen
ff4bb2dfb5714eeb0408d3bb862de1646351d097Timo Sirainenenum mailbox_list_file_type
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenmailbox_list_get_file_type(const struct dirent *d ATTR_UNUSED)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_file_type type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#ifdef HAVE_DIRENT_D_TYPE
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen switch (d->d_type) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_UNKNOWN:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_REG:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_FILE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_DIR:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_DIR;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_LNK:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_SYMLINK;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen default:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_OTHER;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#else
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#endif
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainenint mailbox_list_dirent_is_alias_symlink(struct mailbox_list *list,
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen const char *dir_path,
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen const struct dirent *d)
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen{
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen struct stat st;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen int ret;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen if (mailbox_list_get_file_type(d) == MAILBOX_LIST_FILE_TYPE_SYMLINK)
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen return 1;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen T_BEGIN {
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi const char *path, *linkpath, *error;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen path = t_strconcat(dir_path, "/", d->d_name, NULL);
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen if (lstat(path, &st) < 0) {
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen mailbox_list_set_critical(list,
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen "lstat(%s) failed: %m", path);
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen ret = -1;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen } else if (!S_ISLNK(st.st_mode)) {
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen ret = 0;
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi } else if (t_readlink(path, &linkpath, &error) < 0) {
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi i_error("t_readlink(%s) failed: %s", path, error);
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen ret = -1;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen } else {
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen /* it's an alias only if it points to the same
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen directory */
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen ret = strchr(linkpath, '/') == NULL ? 1 : 0;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen }
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen } T_END;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen return ret;
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen}
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen
77b5fd56e5a06d624f3ab92198272287333114f4Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenstatic bool
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenmailbox_list_try_get_home_path(struct mailbox_list *list, const char **name)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen{
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if ((*name)[1] == '/') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* ~/dir - use the configured home directory */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (mail_user_try_home_expand(list->ns->user, name) < 0)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen } else {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* ~otheruser/dir - assume we're using system users */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (home_try_expand(name) < 0)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return TRUE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen}
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenbool mailbox_list_try_get_absolute_path(struct mailbox_list *list,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen const char **name)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen{
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen const char *root_dir, *path, *mailbox_name;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (!list->mail_set->mail_full_filesystem_access)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (**name == '~') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* try to expand home directory */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (!mailbox_list_try_get_home_path(list, name)) {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* fallback to using actual "~name" mailbox */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen } else {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (**name != '/')
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* okay, we have an absolute path now. but check first if it points to
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen same directory as one of our regular mailboxes. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_MAILBOX);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen len = strlen(root_dir);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (strncmp(root_dir, *name, len) == 0 && (*name)[len] == '/') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen mailbox_name = *name + len + 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, mailbox_name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (strcmp(path, *name) == 0) {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* yeah, we can replace the full path with mailbox
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen name. this way we can use indexes. */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen *name = mailbox_name;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen}
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_last_error(struct mailbox_list *list,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error *error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (error_r != NULL)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen *error_r = list->error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return list->error_string != NULL ? list->error_string :
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Unknown internal list error";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3e0b3ae576483a96b88802b27e93f3caeba09ddcTimo Sirainenenum mail_error mailbox_list_get_last_mail_error(struct mailbox_list *list)
3e0b3ae576483a96b88802b27e93f3caeba09ddcTimo Sirainen{
3e0b3ae576483a96b88802b27e93f3caeba09ddcTimo Sirainen return list->error;
3e0b3ae576483a96b88802b27e93f3caeba09ddcTimo Sirainen}
3e0b3ae576483a96b88802b27e93f3caeba09ddcTimo Sirainen
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärviconst char *mailbox_list_get_last_internal_error(struct mailbox_list *list,
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi enum mail_error *error_r)
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi{
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi if (error_r != NULL)
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi *error_r = list->error;
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi if (list->last_error_is_internal) {
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi i_assert(list->last_internal_error != NULL);
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi return list->last_internal_error;
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi }
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi return mailbox_list_get_last_error(list, error_r);
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi}
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi i_free(list->last_internal_error);
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi list->last_error_is_internal = FALSE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = MAIL_ERROR_NONE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenvoid mailbox_list_set_error(struct mailbox_list *list,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error error, const char *string)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free(list->error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error_string = i_strdup(string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi list->last_error_is_internal = FALSE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen const char *str;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free(list->error_string);
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen list->error_string = i_strdup(str);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = MAIL_ERROR_TEMP;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_list va;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi i_free(list->last_internal_error);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_start(va, fmt);
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi list->last_internal_error = i_strdup_vprintf(fmt, va);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_end(va);
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi list->last_error_is_internal = TRUE;
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi i_error("%s", list->last_internal_error);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* critical errors may contain sensitive data, so let user
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen see only "Internal error" with a timestamp to make it
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen easier to look from log files the actual error message. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_internal_error(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenbool mailbox_list_set_error_from_errno(struct mailbox_list *list)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char *error_string;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error error;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return FALSE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, error, error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return TRUE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen}
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen
4654cf737f538f5de032b8c9908913f121917366Timo Sirainenvoid mailbox_list_last_error_push(struct mailbox_list *list)
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen{
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen struct mail_storage_error *err;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen if (!array_is_created(&list->error_stack))
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen i_array_init(&list->error_stack, 2);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen err = array_append_space(&list->error_stack);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen err->error_string = i_strdup(list->error_string);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen err->error = list->error;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen err->last_error_is_internal = list->last_error_is_internal;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen if (err->last_error_is_internal)
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen err->last_internal_error = i_strdup(list->last_internal_error);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen}
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen
4654cf737f538f5de032b8c9908913f121917366Timo Sirainenvoid mailbox_list_last_error_pop(struct mailbox_list *list)
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen{
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen unsigned int count = array_count(&list->error_stack);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen const struct mail_storage_error *err =
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen array_idx(&list->error_stack, count-1);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen i_free(list->error_string);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen i_free(list->last_internal_error);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen list->error_string = err->error_string;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen list->error = err->error;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen list->last_error_is_internal = err->last_error_is_internal;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen list->last_internal_error = err->last_internal_error;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen array_delete(&list->error_stack, count-1, 1);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen}
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainenint mailbox_list_init_fs(struct mailbox_list *list, const char *driver,
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen const char *args, const char *root_dir,
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen struct fs **fs_r, const char **error_r)
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen{
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen struct fs_settings fs_set;
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen struct ssl_iostream_settings ssl_set;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen struct mailbox_list_fs_context *ctx;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen struct fs *parent_fs;
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ssl_set);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&fs_set);
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen mail_user_init_fs_settings(list->ns->user, &fs_set, &ssl_set);
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen fs_set.root_path = root_dir;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen fs_set.temp_file_prefix = mailbox_list_get_global_temp_prefix(list);
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen if (fs_init(driver, args, &fs_set, fs_r, error_r) < 0)
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen return -1;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen /* add mailbox_list context to the parent fs, which allows
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen mailbox_list_fs_get_list() to work */
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen for (parent_fs = *fs_r; parent_fs->parent != NULL;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen parent_fs = parent_fs->parent) ;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen ctx = p_new(list->pool, struct mailbox_list_fs_context, 1);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen ctx->list = list;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen MODULE_CONTEXT_SET(parent_fs, mailbox_list_fs_module, ctx);
e0f57c552d2f436458163f722a7d0cc9a95d0709Timo Sirainen
e0f57c552d2f436458163f722a7d0cc9a95d0709Timo Sirainen /* a bit kludgy notification to the fs that we're now finished setting
e0f57c552d2f436458163f722a7d0cc9a95d0709Timo Sirainen up the module context. */
e0f57c552d2f436458163f722a7d0cc9a95d0709Timo Sirainen (void)fs_get_properties(*fs_r);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen return 0;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen}
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenstruct mailbox_list *mailbox_list_fs_get_list(struct fs *fs)
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen{
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen struct mailbox_list_fs_context *ctx;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen while (fs->parent != NULL)
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen fs = fs->parent;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen ctx = MAILBOX_LIST_FS_CONTEXT(fs);
a41f6dd2a2434206d2a445ac73c79861d3496a2aTimo Sirainen return ctx == NULL ? NULL : ctx->list;
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen}
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainenint mailbox_list_lock(struct mailbox_list *list)
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen{
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen struct mailbox_permissions perm;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen struct file_create_settings set;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen const char *lock_dir, *lock_fname, *lock_path, *error;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen if (list->lock_refcount > 0) {
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen list->lock_refcount++;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen return 0;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen }
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen mailbox_list_get_root_permissions(list, &perm);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen i_zero(&set);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen set.lock_timeout_secs = list->mail_set->mail_max_lock_timeout == 0 ?
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen MAILBOX_LIST_LOCK_SECS :
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen I_MIN(MAILBOX_LIST_LOCK_SECS, list->mail_set->mail_max_lock_timeout);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen set.lock_method = list->mail_set->parsed_lock_method;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen set.mode = perm.file_create_mode;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen set.gid = perm.file_create_gid;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen set.gid_origin = perm.file_create_gid_origin;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen lock_fname = MAILBOX_LIST_LOCK_FNAME;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen if (list->set.volatile_dir != NULL) {
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen /* Use VOLATILEDIR. It's shared with all mailbox_lists, so use
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen hash of the namespace prefix as a way to make this lock name
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen unique across the namespaces. */
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen unsigned char ns_prefix_hash[SHA1_RESULTLEN];
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen sha1_get_digest(list->ns->prefix, list->ns->prefix_len,
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen ns_prefix_hash);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen lock_fname = t_strconcat(MAILBOX_LIST_LOCK_FNAME,
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen binary_to_hex(ns_prefix_hash, sizeof(ns_prefix_hash)), NULL);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen lock_dir = list->set.volatile_dir;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen set.mkdir_mode = 0700;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen } else if (mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX,
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen &lock_dir)) {
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen /* use index root directory */
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen if (mailbox_list_mkdir_missing_index_root(list) < 0)
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen return -1;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen } else if (mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_DIR,
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen &lock_dir)) {
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen /* use mailbox root directory */
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen if (mailbox_list_mkdir_root(list, lock_dir,
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR) < 0)
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen return -1;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen } else {
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen /* No filesystem used by mailbox list (e.g. imapc).
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen Just assume it's locked */
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen list->lock_refcount = 1;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen return 0;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen }
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen lock_path = t_strdup_printf("%s/%s", lock_dir, lock_fname);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen if (mail_storage_lock_create(lock_path, &set, list->mail_set,
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen &list->lock, &error) <= 0) {
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen mailbox_list_set_critical(list,
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen "Couldn't create mailbox list lock %s: %s",
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen lock_path, error);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen return -1;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen }
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen list->lock_refcount = 1;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen return 0;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen}
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainenvoid mailbox_list_unlock(struct mailbox_list *list)
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen{
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen i_assert(list->lock_refcount > 0);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen if (--list->lock_refcount > 0)
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen return;
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen file_lock_free(&list->lock);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen}