mailbox-list.c revision 25d9db0c00e8041165540e0829d7eab7548cbaa5
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2006-2007 Timo Sirainen */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "lib.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "array.h"
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen#include "ioloop.h"
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen#include "mkdir-parents.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "unlink-directory.h"
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen#include "mailbox-list-private.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen#include <time.h>
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include <dirent.h>
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen then start renaming them to larger names from end to beginning, which
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen eventually would start causing the failures when trying to use too
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen long mailbox names. */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen#define MAILBOX_MAX_HIERARCHY_LEVELS 20
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen/* Message to show to users when critical error occurs */
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen#define CRITICAL_MSG \
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen "Internal error occurred. Refer to server log for more information."
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid (*hook_mailbox_list_created)(struct mailbox_list *list);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen const struct mailbox_list *const *drivers;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen unsigned int i, count;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen for (i = 0; i < count; i++) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen *idx_r = i;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return TRUE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen{
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (!array_is_created(&mailbox_list_drivers))
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen i_array_init(&mailbox_list_drivers, 4);
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen else {
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen unsigned int idx;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->name);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen array_append(&mailbox_list_drivers, &list, 1);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen unsigned int idx;
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
c1d4780bc0c9017e8e5d366b81e4fad31174c0adTimo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->name);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen array_delete(&mailbox_list_drivers, idx, 1);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (array_count(&mailbox_list_drivers) == 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen array_free(&mailbox_list_drivers);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_init(const char *driver,
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen const struct mailbox_list_settings *set,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen enum mailbox_list_flags flags,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mailbox_list **list_r, const char **error_r)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen const struct mailbox_list *const *class_p;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mailbox_list *list;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int idx;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen *error_r = "Unknown mailbox list driver";
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return -1;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen }
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_assert(*set->root_dir != '\0');
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_assert(*set->subscription_fname != '\0');
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list = (*class_p)->v.alloc();
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->flags = flags;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* copy settings */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen list->set.index_dir = set->index_dir == NULL ||
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen p_strdup(list->pool, set->index_dir);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen list->set.control_dir = set->control_dir == NULL ||
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen p_strdup(list->pool, set->control_dir);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (list->set.index_dir != NULL) {
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen if (mkdir_parents(list->set.index_dir, 0700) < 0 &&
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen errno != EEXIST)
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_error("mkdir(%s) failed: %m", list->set.index_dir);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen }
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (list->set.control_dir != NULL) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (mkdir_parents(list->set.control_dir, 0700) < 0 &&
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen errno != EEXIST)
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_error("mkdir(%s) failed: %m", list->set.control_dir);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen }
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen list->set.subscription_fname =
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen p_strdup(list->pool, set->subscription_fname);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen list->set.maildir_name = p_strdup(list->pool, set->maildir_name);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen list->set.mail_storage_flags = set->mail_storage_flags;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen list->set.lock_method = set->lock_method;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if ((flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen driver, list->set.root_dir,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->set.index_dir == NULL ? "" : list->set.index_dir,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->set.control_dir == NULL ?
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen "" : list->set.control_dir,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->set.inbox_path == NULL ?
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen "" : list->set.inbox_path);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (hook_mailbox_list_created != NULL)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hook_mailbox_list_created(list);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->set.mail_storage_flags = NULL;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->set.lock_method = NULL;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen *list_r = list;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return 0;
156736910057b280cb9999d4c6c7221c4c80f5c2Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid mailbox_list_deinit(struct mailbox_list *list)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_free_and_null(list->error);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->v.deinit(list);
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenconst char *mailbox_list_get_driver_name(struct mailbox_list *list)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen return list->name;
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen}
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainenchar mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->hierarchy_sep;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenbool mailbox_list_is_valid_mask(struct mailbox_list *list, const char *mask)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->v.is_valid_mask(list, mask);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen const char *name)
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen{
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen return list->v.is_valid_existing_name(list, name);
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen const char *name)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen return list->v.is_valid_create_name(list, name);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen}
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen enum mailbox_list_path_type type)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen mailbox_list_clear_error(list);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->v.get_path(list, name, type);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
5297aa3ceddf3a4ecc09f49c832bc424eff8f906Timo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->v.get_temp_prefix(list);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenconst char *mailbox_list_join_refmask(struct mailbox_list *list,
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen const char *ref, const char *mask)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (list->v.join_refmask != NULL)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return list->v.join_refmask(list, ref, mask);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* the default implementation: */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (*ref != '\0') {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* merge reference and mask */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mask = t_strconcat(ref, mask, NULL);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen }
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return mask;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen}
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenint mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen const char *name,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen enum mailbox_name_status *status)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen mailbox_list_clear_error(list);
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen *status = MAILBOX_NAME_INVALID;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return 0;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen }
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return list->v.get_mailbox_name_status(list, name, status);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen}
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenstruct mailbox_list_iterate_context *
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenmailbox_list_iter_init(struct mailbox_list *list, const char *mask,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen enum mailbox_list_iter_flags flags)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return list->v.iter_init(list, mask, flags);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen}
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstruct mailbox_info *
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenmailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen return ctx->list->v.iter_next(ctx);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainenint mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen{
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen struct mailbox_list_iterate_context *ctx = *_ctx;
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen *_ctx = NULL;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return ctx->list->v.iter_deinit(ctx);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen const char *name, bool set)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen mailbox_list_clear_error(list);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->v.set_subscribed(list, name, set);
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return -1;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->v.delete_mailbox(list, name);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_rename_mailbox(struct mailbox_list *list,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen const char *oldname, const char *newname)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, oldname) ||
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen !mailbox_list_is_valid_create_name(list, newname)) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return -1;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen }
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return list->v.rename_mailbox(list, oldname, newname);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen}
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_delete_index_control(struct mailbox_list *list,
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen const char *name)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen const char *path, *index_dir, *dir;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (strcmp(name, "INBOX") == 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mailbox_list_set_error(list, "INBOX can't be deleted.");
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return -1;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
1b9aae1cb53708b5a3d861b4db6ba96ac2eb35b4Timo Sirainen return -1;
1b9aae1cb53708b5a3d861b4db6ba96ac2eb35b4Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen path = mailbox_list_get_path(list, name,
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen /* delete the index directory first, so that if we crash we don't
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen leave indexes for deleted mailboxes lying around */
4da70fe8c9cb6e57b36103d78ab1e9c8654f76d9Timo Sirainen index_dir = mailbox_list_get_path(list, name,
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (*index_dir != '\0' && strcmp(index_dir, path) != 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (unlink_directory(index_dir, TRUE) < 0 && errno != ENOENT) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mailbox_list_set_critical(list,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen "unlink_directory(%s) failed: %m", index_dir);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen return -1;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* control directory next */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen if (*dir != '\0' && strcmp(dir, path) != 0 &&
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen strcmp(dir, index_dir) != 0) {
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen if (unlink_directory(dir, TRUE) < 0 && errno != ENOENT) {
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen mailbox_list_set_critical(list,
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen "unlink_directory(%s) failed: %m", dir);
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen return -1;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen }
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen }
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen return 0;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainenbool mailbox_list_name_is_too_large(const char *name, char sep)
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainen{
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen unsigned int levels = 1, level_len = 0;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen for (; *name != '\0'; name++) {
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen if (*name == sep) {
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen return TRUE;
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen levels++;
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen level_len = 0;
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainen } else {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen level_len++;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen return TRUE;
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen return TRUE;
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen return FALSE;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainenenum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d)
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen{
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen enum mailbox_list_file_type type;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#ifdef HAVE_DIRENT_D_TYPE
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen switch (d->d_type) {
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen case DT_UNKNOWN:
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen break;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen case DT_REG:
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_FILE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen break;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen case DT_DIR:
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_DIR;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen break;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen case DT_LNK:
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_SYMLINK;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen break;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen default:
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_OTHER;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen break;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#else
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen#endif
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen return type;
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen}
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainenconst char *mailbox_list_get_last_error(struct mailbox_list *list,
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen bool *temporary_error_r)
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen *temporary_error_r = list->temporary_error;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->error;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen i_free_and_null(list->error);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->temporary_error = FALSE;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen}
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenvoid mailbox_list_set_error(struct mailbox_list *list, const char *error)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_free(list->error);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen list->error = i_strdup(error);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->temporary_error = FALSE;
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen}
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
9511a40d933181045343110c8101b75887062aaeTimo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct tm *tm;
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen char str[256];
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen tm = localtime(&ioloop_time);
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen i_free(list->error);
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen list->error =
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen i_strdup(str) : i_strdup(CRITICAL_MSG);
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen list->temporary_error = TRUE;
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen}
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainenvoid mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen{
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen va_list va;
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen va_start(va, fmt);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen va_end(va);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen /* critical errors may contain sensitive data, so let user
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen see only "Internal error" with a timestamp to make it
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen easier to look from log files the actual error message. */
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen mailbox_list_set_internal_error(list);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen}
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen