mailbox-list.c revision adb6413686e52e00dded4932babcc08ff041876b
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* Copyright (c) 2006-2007 Dovecot authors, see the included COPYING file */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "lib.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "array.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "ioloop.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "home-expand.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "mkdir-parents.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "unlink-directory.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "mailbox-list-private.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include <time.h>
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include <unistd.h>
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include <dirent.h>
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include <sys/stat.h>
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen then start renaming them to larger names from end to beginning, which
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen eventually would start causing the failures when trying to use too
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen long mailbox names. */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define MAILBOX_MAX_HIERARCHY_LEVELS 20
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* Message to show to users when critical error occurs */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define CRITICAL_MSG \
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen "Internal error occurred. Refer to server log for more information."
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid (*hook_mailbox_list_created)(struct mailbox_list *list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
a21f618de284dc22a480af1371d5f5cea50a39dfTimo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const struct mailbox_list *const *drivers;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int i, count;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen for (i = 0; i < count; i++) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *idx_r = i;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return TRUE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return FALSE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (!array_is_created(&mailbox_list_drivers))
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_array_init(&mailbox_list_drivers, 4);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen else {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int idx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->name);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen array_append(&mailbox_list_drivers, &list, 1);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int idx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->name);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen array_delete(&mailbox_list_drivers, idx, 1);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (array_count(&mailbox_list_drivers) == 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen array_free(&mailbox_list_drivers);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenint mailbox_list_alloc(const char *driver, struct mailbox_list **list_r,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char **error_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const struct mailbox_list *const *class_p;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mailbox_list *list;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int idx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *error_r = t_strdup_printf("Unknown mailbox list driver: %s",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen driver);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list = *list_r = (*class_p)->v.alloc();
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic const char *fix_path(const char *path)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen size_t len = strlen(path);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (len > 1 && path[len-1] == '/')
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen path = t_strndup(path, len-1);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return home_expand(path);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenint mailbox_list_settings_parse(const char *data,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mailbox_list_settings *set,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char **layout, const char **error_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *const *tmp, *key, *value;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(*data != '\0');
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *error_r = NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* <root dir> */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen tmp = t_strsplit(data, ":");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen set->root_dir = fix_path(*tmp);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen tmp++;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
a327d9301f593433c228c4cc8cca05c95b37f6fbTimo Sirainen for (; *tmp != NULL; tmp++) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen value = strchr(*tmp, '=');
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (value == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen key = *tmp;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen value = "";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen } else {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen key = t_strdup_until(*tmp, value);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen value++;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (strcmp(key, "INBOX") == 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen set->inbox_path = fix_path(value);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen else if (strcmp(key, "INDEX") == 0)
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen set->index_dir = fix_path(value);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen else if (strcmp(key, "CONTROL") == 0)
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen set->control_dir = fix_path(value);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen else if (strcmp(key, "LAYOUT") == 0)
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen *layout = value;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen else if (strcmp(key, "SUBSCRIPTIONS") == 0)
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen set->subscription_fname = fix_path(value);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen else if (strcmp(key, "DIRNAME") == 0)
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen set->maildir_name = value;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen else {
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen *error_r = t_strdup_printf("Unknown setting: %s", key);
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen return -1;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen }
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (set->index_dir != NULL && strcmp(set->index_dir, "MEMORY") == 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen set->index_dir = "";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid mailbox_list_init(struct mailbox_list *list, struct mail_namespace *ns,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const struct mailbox_list_settings *set,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen enum mailbox_list_flags flags)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0');
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(set->subscription_fname == NULL ||
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *set->subscription_fname != '\0');
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->ns = ns;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->flags = flags;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->cached_uid = (uid_t)-1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->cached_gid = (gid_t)-1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* copy settings */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.index_dir = set->index_dir == NULL ||
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen p_strdup(list->pool, set->index_dir);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.control_dir = set->control_dir == NULL ||
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen p_strdup(list->pool, set->control_dir);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (list->set.index_dir != NULL &&
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *list->set.index_dir != '\0') {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mkdir_parents(list->set.index_dir, 0700) < 0 &&
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen errno != EEXIST)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_error("mkdir(%s) failed: %m", list->set.index_dir);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (list->set.control_dir != NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mkdir_parents(list->set.control_dir, 0700) < 0 &&
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen errno != EEXIST)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_error("mkdir(%s) failed: %m", list->set.control_dir);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.subscription_fname =
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen p_strdup(list->pool, set->subscription_fname);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.maildir_name = p_strdup(list->pool, set->maildir_name);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.mail_storage_flags = set->mail_storage_flags;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen list->set.lock_method = set->lock_method;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if ((flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->name, list->set.root_dir,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.index_dir == NULL ? "" : list->set.index_dir,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen list->set.control_dir == NULL ?
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen "" : list->set.control_dir,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.inbox_path == NULL ?
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen "" : list->set.inbox_path);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (hook_mailbox_list_created != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen hook_mailbox_list_created(list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.mail_storage_flags = NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->set.lock_method = NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid mailbox_list_deinit(struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_free_and_null(list->error_string);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->v.deinit(list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenconst char *mailbox_list_get_driver_name(struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen return list->name;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenchar mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->hierarchy_sep;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenenum mailbox_list_flags mailbox_list_get_flags(struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->flags;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct mail_namespace *mailbox_list_get_namespace(struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->ns;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenbool mailbox_list_is_valid_pattern(struct mailbox_list *list,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *pattern)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->v.is_valid_pattern(list, pattern);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *name)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->v.is_valid_existing_name(list, name);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *name)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->v.is_valid_create_name(list, name);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen enum mailbox_list_path_type type)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mailbox_list_clear_error(list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->v.get_path(list, name, type);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenint mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mode_t *mode_r, uid_t *uid_r, gid_t *gid_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *path;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct stat st;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mailbox_list_clear_error(list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen path = mailbox_list_get_path(list, name,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (*path == '\0')
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (stat(path, &st) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (ENOTFOUND(errno))
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *mode_r = st.st_mode & 0666;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (list->cached_uid == (uid_t)-1)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->cached_uid = geteuid();
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *uid_r = list->cached_uid == st.st_uid ? (uid_t)-1 : st.st_uid;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* directory's GID is used automatically for new files */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *gid_r = (gid_t)-1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen } else {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (list->cached_gid == (gid_t)-1)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen list->cached_gid = getegid();
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *gid_r = list->cached_gid == st.st_gid ? (gid_t)-1 : st.st_gid;
d368aabf3ff5411afee1b4af8261163296723e19Timo Sirainen }
d368aabf3ff5411afee1b4af8261163296723e19Timo Sirainen return 1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->v.get_temp_prefix(list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenconst char *mailbox_list_join_refpattern(struct mailbox_list *list,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *ref, const char *pattern)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (list->v.join_refpattern != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->v.join_refpattern(list, ref, pattern);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* the default implementation: */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (*ref != '\0') {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* merge reference and pattern */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen pattern = t_strconcat(ref, pattern, NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return pattern;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenint mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *name,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen enum mailbox_name_status *status)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mailbox_list_clear_error(list);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *status = MAILBOX_NAME_INVALID;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return list->v.get_mailbox_name_status(list, name, status);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct mailbox_list_iterate_context *
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenmailbox_list_iter_init(struct mailbox_list *list, const char *pattern,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen enum mailbox_list_iter_flags flags)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *patterns[2];
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen patterns[0] = pattern;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen patterns[1] = NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return mailbox_list_iter_init_multiple(list, patterns, flags);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstruct mailbox_list_iterate_context *
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenmailbox_list_iter_init_multiple(struct mailbox_list *list,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *const *patterns,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen enum mailbox_list_iter_flags flags)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(*patterns != NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
mailbox_list_clear_error(list);
return list->v.iter_init(list, patterns, flags);
}
const struct mailbox_info *
mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
{
return ctx->list->v.iter_next(ctx);
}
int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
{
struct mailbox_list_iterate_context *ctx = *_ctx;
*_ctx = NULL;
return ctx->list->v.iter_deinit(ctx);
}
int mailbox_list_set_subscribed(struct mailbox_list *list,
const char *name, bool set)
{
mailbox_list_clear_error(list);
return list->v.set_subscribed(list, name, set);
}
int mailbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
{
if (!mailbox_list_is_valid_existing_name(list, name)) {
mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
"Invalid mailbox name");
return -1;
}
if (strcmp(name, "INBOX") == 0) {
mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
"INBOX can't be deleted.");
return -1;
}
return list->v.delete_mailbox(list, name);
}
int mailbox_list_rename_mailbox(struct mailbox_list *list,
const char *oldname, const char *newname)
{
if (!mailbox_list_is_valid_existing_name(list, oldname) ||
!mailbox_list_is_valid_create_name(list, newname)) {
mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
"Invalid mailbox name");
return -1;
}
return list->v.rename_mailbox(list, oldname, newname);
}
int mailbox_list_delete_index_control(struct mailbox_list *list,
const char *name)
{
const char *path, *index_dir, *dir;
path = mailbox_list_get_path(list, name,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
/* delete the index directory first, so that if we crash we don't
leave indexes for deleted mailboxes lying around */
index_dir = mailbox_list_get_path(list, name,
MAILBOX_LIST_PATH_TYPE_INDEX);
if (*index_dir != '\0' && strcmp(index_dir, path) != 0) {
if (unlink_directory(index_dir, TRUE) < 0 && errno != ENOENT) {
mailbox_list_set_critical(list,
"unlink_directory(%s) failed: %m", index_dir);
return -1;
}
}
/* control directory next */
dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
if (*dir != '\0' && strcmp(dir, path) != 0 &&
strcmp(dir, index_dir) != 0) {
if (unlink_directory(dir, TRUE) < 0 && errno != ENOENT) {
mailbox_list_set_critical(list,
"unlink_directory(%s) failed: %m", dir);
return -1;
}
}
return 0;
}
bool mailbox_list_name_is_too_large(const char *name, char sep)
{
unsigned int levels = 1, level_len = 0;
for (; *name != '\0'; name++) {
if (*name == sep) {
if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
return TRUE;
levels++;
level_len = 0;
} else {
level_len++;
}
}
if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
return TRUE;
if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
return TRUE;
return FALSE;
}
enum mailbox_list_file_type
mailbox_list_get_file_type(const struct dirent *d ATTR_UNUSED)
{
enum mailbox_list_file_type type;
#ifdef HAVE_DIRENT_D_TYPE
switch (d->d_type) {
case DT_UNKNOWN:
type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
break;
case DT_REG:
type = MAILBOX_LIST_FILE_TYPE_FILE;
break;
case DT_DIR:
type = MAILBOX_LIST_FILE_TYPE_DIR;
break;
case DT_LNK:
type = MAILBOX_LIST_FILE_TYPE_SYMLINK;
break;
default:
type = MAILBOX_LIST_FILE_TYPE_OTHER;
break;
}
#else
type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
#endif
return type;
}
const char *mailbox_list_get_last_error(struct mailbox_list *list,
enum mail_error *error_r)
{
*error_r = list->error;
return list->error_string != NULL ? list->error_string :
"Unknown internal list error";
}
void mailbox_list_clear_error(struct mailbox_list *list)
{
i_free_and_null(list->error_string);
list->error = MAIL_ERROR_NONE;
}
void mailbox_list_set_error(struct mailbox_list *list,
enum mail_error error, const char *string)
{
i_free(list->error_string);
list->error_string = i_strdup(string);
list->error = error;
}
void mailbox_list_set_internal_error(struct mailbox_list *list)
{
struct tm *tm;
char str[256];
tm = localtime(&ioloop_time);
i_free(list->error_string);
list->error_string =
strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
i_strdup(str) : i_strdup(CRITICAL_MSG);
list->error = MAIL_ERROR_TEMP;
}
void mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
i_error("%s", t_strdup_vprintf(fmt, va));
va_end(va);
/* critical errors may contain sensitive data, so let user
see only "Internal error" with a timestamp to make it
easier to look from log files the actual error message. */
mailbox_list_set_internal_error(list);
}
bool mailbox_list_set_error_from_errno(struct mailbox_list *list)
{
const char *error_string;
enum mail_error error;
if (!mail_error_from_errno(&error, &error_string))
return FALSE;
mailbox_list_set_error(list, error, error_string);
return TRUE;
}