mailbox-list.c revision e28fa207d1a097fa6e4a867f74ee0761472ef1ce
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "ioloop.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "str.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include "home-expand.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include "unlink-directory.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "imap-match.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "imap-utf7.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "mailbox-tree.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-private.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <time.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <unistd.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <dirent.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <sys/stat.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen then start renaming them to larger names from end to beginning, which
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen eventually would start causing the failures when trying to use too
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen long mailbox names. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILBOX_MAX_HIERARCHY_LEVELS 20
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Message to show to users when critical error occurs */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define CRITICAL_MSG \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "Internal error occurred. Refer to server log for more information."
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstruct ns_list_iterate_context {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct mailbox_list_iterate_context ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct mailbox_list_iterate_context *backend_ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct mail_namespace *namespaces;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen pool_t pool;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen const char **patterns;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen};
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid (*hook_mailbox_list_created)(struct mailbox_list *list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
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
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainenint mailbox_list_alloc(const char *driver, struct mailbox_list **list_r,
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen const char **error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list *const *class_p;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_list *list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen *error_r = t_strdup_printf("Unknown mailbox list driver: %s",
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen driver);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen list = *list_r = (*class_p)->v.alloc();
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen return 0;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen}
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainenstatic int fix_path(struct mail_namespace *ns, const char *path,
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen const char **path_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);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (mail_user_try_home_expand(ns->user, &path) < 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen *path_r = path;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenint mailbox_list_settings_parse(const char *data,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct mailbox_list_settings *set,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen struct mail_namespace *ns,
4645cc6c911a95991d7af43b40f88e99506ea5e9Timo Sirainen const char **layout, const char **alt_dir_r,
4645cc6c911a95991d7af43b40f88e99506ea5e9Timo Sirainen const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen const char *const *tmp, *key, *value, **dest;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_assert(*data != '\0');
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = NULL;
4645cc6c911a95991d7af43b40f88e99506ea5e9Timo Sirainen if (alt_dir_r != NULL)
4645cc6c911a95991d7af43b40f88e99506ea5e9Timo Sirainen *alt_dir_r = NULL;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* <root dir> */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen tmp = t_strsplit(data, ":");
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (fix_path(ns, *tmp, &set->root_dir) < 0) {
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen *error_r = t_strdup_printf(
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen "Home directory not set, can't expand ~/ for "
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen "mail root dir in: %s", data);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen tmp++;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen for (; *tmp != NULL; tmp++) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value = strchr(*tmp, '=');
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (value == NULL) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen key = *tmp;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value = "";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen } else {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen key = t_strdup_until(*tmp, value);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value++;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (strcmp(key, "INBOX") == 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen dest = &set->inbox_path;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "INDEX") == 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen dest = &set->index_dir;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "CONTROL") == 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen dest = &set->control_dir;
4645cc6c911a95991d7af43b40f88e99506ea5e9Timo Sirainen else if (strcmp(key, "ALT") == 0 && alt_dir_r != NULL)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen dest = alt_dir_r;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "LAYOUT") == 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen dest = layout;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "SUBSCRIPTIONS") == 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen dest = &set->subscription_fname;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "DIRNAME") == 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen dest = &set->maildir_name;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = t_strdup_printf("Unknown setting: %s", key);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (fix_path(ns, value, dest) < 0) {
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen *error_r = t_strdup_printf(
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen "Home directory not set, can't expand ~/ for "
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen "%s in: %s", key, data);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (set->index_dir != NULL && strcmp(set->index_dir, "MEMORY") == 0)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen set->index_dir = "";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainenvoid mailbox_list_init(struct mailbox_list *list, struct mail_namespace *ns,
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen const struct mailbox_list_settings *set,
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen enum mailbox_list_flags flags)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen{
740dfc753f1f087f0c41082e4c551053129e875dTimo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0');
740dfc753f1f087f0c41082e4c551053129e875dTimo Sirainen i_assert(set->subscription_fname == NULL ||
740dfc753f1f087f0c41082e4c551053129e875dTimo Sirainen *set->subscription_fname != '\0');
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen list->ns = ns;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->flags = flags;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen list->file_create_mode = (mode_t)-1;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen list->file_create_gid = (gid_t)-1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* copy settings */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.index_dir = set->index_dir == NULL ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p_strdup(list->pool, set->index_dir);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.control_dir = set->control_dir == NULL ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p_strdup(list->pool, set->control_dir);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.subscription_fname =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p_strdup(list->pool, set->subscription_fname);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.maildir_name = p_strdup(list->pool, set->maildir_name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen list->set.mail_storage_flags = set->mail_storage_flags;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen list->set.lock_method = set->lock_method;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
06f2599faace2943684f7b3d0de2bda6c60457c8Timo Sirainen list->name,
06f2599faace2943684f7b3d0de2bda6c60457c8Timo Sirainen list->set.root_dir == NULL ? "" : list->set.root_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.index_dir == NULL ? "" : list->set.index_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.control_dir == NULL ?
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "" : list->set.control_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->set.inbox_path == NULL ?
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "" : list->set.inbox_path);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (hook_mailbox_list_created != NULL)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen hook_mailbox_list_created(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen list->set.mail_storage_flags = NULL;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen list->set.lock_method = NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_deinit(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenchar mailbox_list_get_hierarchy_sep(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->hierarchy_sep;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainenvoid mailbox_list_get_permissions(struct mailbox_list *list,
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen mode_t *mode_r, gid_t *gid_r)
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen{
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen const char *path;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen struct stat st;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen if (list->file_create_mode != (mode_t)-1) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen *mode_r = list->file_create_mode;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen *gid_r = list->file_create_gid;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen return;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen path = mailbox_list_get_path(list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen if (stat(path, &st) < 0) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen if (!ENOTFOUND(errno)) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m",
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen path);
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen } else if ((list->flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen i_info("Namespace %s: Permission lookup failed from %s",
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen list->ns->prefix, path);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen /* return safe defaults */
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen *mode_r = 0600;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen *gid_r = (gid_t)-1;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen return;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen list->file_create_mode = st.st_mode & 0666;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen /* directory's GID is used automatically for new files */
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen list->file_create_gid = (gid_t)-1;
509daf558a54d7d1c8006c54ef799cb99e31662eTimo Sirainen } else if ((st.st_mode & 0060) == 0) {
509daf558a54d7d1c8006c54ef799cb99e31662eTimo Sirainen /* group doesn't have any permissions, so don't bother
509daf558a54d7d1c8006c54ef799cb99e31662eTimo Sirainen changing it */
509daf558a54d7d1c8006c54ef799cb99e31662eTimo Sirainen list->file_create_gid = (gid_t)-1;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen } else if (getegid() == st.st_gid) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen /* using our own gid, no need to change it */
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen list->file_create_gid = (gid_t)-1;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen } else {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen list->file_create_gid = st.st_gid;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen i_info("Namespace %s: Using permissions from %s: "
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen "mode=0%o gid=%ld", list->ns->prefix, path,
aaa340328f0c43b3ebdedd7bded70521d3f7a167Timo Sirainen (int)list->file_create_mode,
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen list->file_create_gid == (gid_t)-1 ? -1L :
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen (long)list->file_create_gid);
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen }
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen *mode_r = list->file_create_mode;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen *gid_r = list->file_create_gid;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen}
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainenvoid mailbox_list_get_dir_permissions(struct mailbox_list *list,
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen mode_t *mode_r, gid_t *gid_r)
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen{
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen mode_t mode;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen mailbox_list_get_permissions(list, &mode, gid_r);
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen /* add the execute bit if either read or write bit is set */
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen if ((mode & 0600) != 0) mode |= 0100;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen if ((mode & 0060) != 0) mode |= 0010;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen if ((mode & 0006) != 0) mode |= 0001;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen *mode_r = mode;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen}
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenbool mailbox_list_is_valid_pattern(struct mailbox_list *list,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen const char *pattern)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return list->v.is_valid_pattern(list, pattern);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->v.is_valid_existing_name(list, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen int ret;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen T_BEGIN {
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen string_t *str = t_str_new(256);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen ret = imap_utf7_to_utf8(name, str);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen } T_END;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen return ret < 0 ? FALSE :
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen list->v.is_valid_create_name(list, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_path_type type)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen mailbox_list_clear_error(list);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->v.get_path(list, name, type);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_name_status *status)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen mailbox_list_clear_error(list);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen *status = MAILBOX_NAME_INVALID;
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen return 0;
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen }
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->v.get_mailbox_name_status(list, name, status);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct mailbox_list_iterate_context *
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenmailbox_list_iter_init(struct mailbox_list *list, const char *pattern,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_iter_flags flags)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen const char *patterns[2];
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen patterns[0] = pattern;
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen patterns[1] = NULL;
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen return mailbox_list_iter_init_multiple(list, patterns, flags);
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen}
f97cacf16251b42f530c6a28686cc8c9aa7df3a2Timo Sirainen
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenstruct mailbox_list_iterate_context *
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenmailbox_list_iter_init_multiple(struct mailbox_list *list,
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen const char *const *patterns,
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen enum mailbox_list_iter_flags flags)
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen{
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen i_assert(*patterns != NULL);
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen mailbox_list_clear_error(list);
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen return list->v.iter_init(list, patterns, flags);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstatic const struct mailbox_info *
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenmailbox_list_ns_iter_next(struct mailbox_list_iterate_context *_ctx)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen{
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct ns_list_iterate_context *ctx =
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen (struct ns_list_iterate_context *)_ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen const struct mailbox_info *info;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen info = mailbox_list_iter_next(ctx->backend_ctx);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (info == NULL && ctx->namespaces != NULL) {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen /* go to the next namespace */
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen _ctx->failed = TRUE;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->backend_ctx =
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen mailbox_list_iter_init_multiple(ctx->namespaces->list,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->patterns,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen _ctx->flags);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->namespaces = ctx->namespaces->next;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return mailbox_list_ns_iter_next(_ctx);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen }
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return info;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen}
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstatic int
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenmailbox_list_ns_iter_deinit(struct mailbox_list_iterate_context *_ctx)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen{
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct ns_list_iterate_context *ctx =
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen (struct ns_list_iterate_context *)_ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen int ret;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen _ctx->failed = TRUE;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ret = _ctx->failed ? -1 : 0;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen pool_unref(&ctx->pool);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return ret;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen}
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstruct mailbox_list_iterate_context *
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenmailbox_list_iter_init_namespaces(struct mail_namespace *namespaces,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen const char *const *patterns,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen enum mailbox_list_iter_flags flags)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen{
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct ns_list_iterate_context *ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen unsigned int i, count;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen pool_t pool;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen i_assert(namespaces != NULL);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen pool = pool_alloconly_create("mailbox list namespaces", 256);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx = p_new(pool, struct ns_list_iterate_context, 1);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->pool = pool;
e7157fa0ad659fa7984f3e6c59c195221c53ac64Timo Sirainen ctx->ctx.flags = flags;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->ctx.list = p_new(pool, struct mailbox_list, 1);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->ctx.list->v.iter_next = mailbox_list_ns_iter_next;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->ctx.list->v.iter_deinit = mailbox_list_ns_iter_deinit;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen count = str_array_length(patterns);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->patterns = p_new(pool, const char *, count + 1);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen for (i = 0; i < count; i++)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->patterns[i] = p_strdup(pool, patterns[i]);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->backend_ctx = mailbox_list_iter_init_multiple(namespaces->list,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen patterns, flags);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->namespaces = namespaces->next;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return &ctx->ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen}
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
61e84692827b6a64912343f515c984853021483aTimo Sirainenconst struct mailbox_info *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return ctx->list->v.iter_next(ctx);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_list_iterate_context *ctx = *_ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *_ctx = NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return ctx->list->v.iter_deinit(ctx);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name, bool set)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen mailbox_list_clear_error(list);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->v.set_subscribed(list, name, set);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenint mailbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
25d9db0c00e8041165540e0829d7eab7548cbaa5Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Invalid mailbox name");
25d9db0c00e8041165540e0829d7eab7548cbaa5Timo Sirainen return -1;
25d9db0c00e8041165540e0829d7eab7548cbaa5Timo Sirainen }
1d266a7419fafa25f3505a12217452a8c647074fTimo Sirainen if (strcmp(name, "INBOX") == 0 &&
1d266a7419fafa25f3505a12217452a8c647074fTimo Sirainen (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "INBOX can't be deleted.");
7d7917f3b54749f667d8c98e881a965ae84f033eTimo Sirainen return -1;
7d7917f3b54749f667d8c98e881a965ae84f033eTimo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return list->v.delete_mailbox(list, name);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenint mailbox_list_rename_mailbox(struct mailbox_list *list,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *oldname, const char *newname)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, oldname) ||
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen !mailbox_list_is_valid_create_name(list, newname)) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Invalid mailbox name");
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen return -1;
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen }
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return list->v.rename_mailbox(list, oldname, newname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainenstatic int mailbox_list_try_delete(struct mailbox_list *list, const char *dir)
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen{
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen if (unlink_directory(dir, TRUE) == 0 || errno == ENOENT)
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen return 0;
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen if (errno == ENOTEMPTY) {
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen /* We're most likely using NFS and we can't delete
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen .nfs* files. */
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen "Mailbox is still open in another session, "
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen "can't delete it.");
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen } else {
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen mailbox_list_set_critical(list,
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen "unlink_directory(%s) failed: %m", dir);
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen }
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen return -1;
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen}
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenint mailbox_list_delete_index_control(struct mailbox_list *list,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *name)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *path, *index_dir, *dir;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen path = mailbox_list_get_path(list, name,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* delete the index directory first, so that if we crash we don't
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen leave indexes for deleted mailboxes lying around */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen index_dir = mailbox_list_get_path(list, name,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (*index_dir != '\0' && strcmp(index_dir, path) != 0) {
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen if (mailbox_list_try_delete(list, index_dir) < 0)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* control directory next */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (*dir != '\0' && strcmp(dir, path) != 0 &&
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen strcmp(dir, index_dir) != 0) {
3ac0d8763b06a39c95187fe6170b1bf822b28a1fTimo Sirainen if (mailbox_list_try_delete(list, index_dir) < 0)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenstatic void node_fix_parents(struct mailbox_node *node)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen{
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* If we happened to create any of the parents, we need to mark them
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen nonexistent. */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node = node->parent;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen for (; node != NULL; node = node->parent) {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if ((node->flags & MAILBOX_MATCHED) == 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags |= MAILBOX_NONEXISTENT;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen}
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainenmailbox_list_iter_update_real(struct mailbox_list_iter_update_context *ctx,
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen const char *name)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen{
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen struct mail_namespace *ns = ctx->iter_ctx->list->ns;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen struct mailbox_node *node;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen enum mailbox_info_flags create_flags = 0, always_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen enum imap_match_result match;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen const char *p;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen bool created, add_matched;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen if (ctx->update_only ||
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen (ctx->iter_ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0)
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen create_flags = MAILBOX_NONEXISTENT | MAILBOX_NOCHILDREN;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen always_flags = ctx->leaf_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen add_matched = TRUE;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen for (;;) {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen created = FALSE;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen match = imap_match(ctx->glob, name);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (match == IMAP_MATCH_YES) {
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen node = ctx->update_only ?
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen mailbox_tree_lookup(ctx->tree_ctx, name) :
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen mailbox_tree_get(ctx->tree_ctx, name, &created);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (created) {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags = create_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (create_flags != 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node_fix_parents(node);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (node != NULL) {
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen if (!ctx->update_only && add_matched)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags |= MAILBOX_MATCHED;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags |= always_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* We don't want to show the parent mailboxes unless
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen something else matches them, but if they are matched
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen we want to show them having child subscriptions */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen add_matched = FALSE;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen } else {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if ((match & IMAP_MATCH_PARENT) == 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen break;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* We've a (possibly) non-subscribed parent mailbox
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen which has a subscribed child mailbox. Make sure we
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen return the parent mailbox. */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen if (!ctx->match_parents)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen break;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* see if parent matches */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen p = strrchr(name, ns->sep);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (p == NULL)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen break;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen name = t_strdup_until(name, p);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen create_flags &= ~MAILBOX_NOCHILDREN;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen always_flags = MAILBOX_CHILDREN | ctx->parent_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainenvoid mailbox_list_iter_update(struct mailbox_list_iter_update_context *ctx,
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen const char *name)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen mailbox_list_iter_update_real(ctx, name);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen}
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_name_is_too_large(const char *name, char sep)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int levels = 1, level_len = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (; *name != '\0'; name++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*name == sep) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen levels++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen level_len = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen level_len++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenbool mailbox_list_try_get_absolute_path(struct mailbox_list *list,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen const char **name)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen{
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) == 0)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (**name == '/')
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (**name != '~')
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen /* try to expand home directory */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if ((*name)[1] == '/') {
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen /* ~/dir - use the configured home directory */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (mail_user_try_home_expand(list->ns->user, name) == 0)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen } else {
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen /* ~otheruser/dir - assume we're using system users */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (home_try_expand(name) == 0)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen }
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen /* fallback to using ~dir */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return FALSE;
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{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo 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
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
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
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct tm *tm;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen char str[256];
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen tm = localtime(&ioloop_time);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free(list->error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error_string =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_strdup(str) : i_strdup(CRITICAL_MSG);
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
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_start(va, fmt);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_end(va);
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}