mailbox-list.c revision 740dfc753f1f087f0c41082e4c551053129e875d
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2006-2007 Timo Sirainen */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "lib.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "array.h"
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include "ioloop.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "mkdir-parents.h"
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen#include "unlink-directory.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "mailbox-list-private.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include <time.h>
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include <dirent.h>
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen then start renaming them to larger names from end to beginning, which
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen eventually would start causing the failures when trying to use too
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen long mailbox names. */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define MAILBOX_MAX_HIERARCHY_LEVELS 20
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen/* Message to show to users when critical error occurs */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#define CRITICAL_MSG \
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "Internal error occurred. Refer to server log for more information."
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid (*hook_mailbox_list_created)(struct mailbox_list *list);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mailbox_list *const *drivers;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int i, count;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen for (i = 0; i < count; i++) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen *idx_r = i;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return FALSE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!array_is_created(&mailbox_list_drivers))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_array_init(&mailbox_list_drivers, 4);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen unsigned int idx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen list->name);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_append(&mailbox_list_drivers, &list, 1);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen unsigned int idx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list->name);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen array_delete(&mailbox_list_drivers, idx, 1);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (array_count(&mailbox_list_drivers) == 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen array_free(&mailbox_list_drivers);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenint mailbox_list_init(const char *driver,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const struct mailbox_list_settings *set,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen enum mailbox_list_flags flags,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_list **list_r, const char **error_r)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const struct mailbox_list *const *class_p;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_list *list;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen unsigned int idx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *error_r = "Unknown mailbox list driver";
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0');
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_assert(set->subscription_fname == NULL ||
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *set->subscription_fname != '\0');
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list = (*class_p)->v.alloc();
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list->flags = flags;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* copy settings */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen list->set.index_dir = set->index_dir == NULL ||
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen p_strdup(list->pool, set->index_dir);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.control_dir = set->control_dir == NULL ||
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen p_strdup(list->pool, set->control_dir);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen if (list->set.index_dir != NULL) {
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen if (mkdir_parents(list->set.index_dir, 0700) < 0 &&
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen errno != EEXIST)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_error("mkdir(%s) failed: %m", list->set.index_dir);
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen if (list->set.control_dir != NULL) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mkdir_parents(list->set.control_dir, 0700) < 0 &&
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen errno != EEXIST)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_error("mkdir(%s) failed: %m", list->set.control_dir);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.subscription_fname =
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen p_strdup(list->pool, set->subscription_fname);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.maildir_name = p_strdup(list->pool, set->maildir_name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.mail_storage_flags = set->mail_storage_flags;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.lock_method = set->lock_method;
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if ((flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen driver, list->set.root_dir,
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen list->set.index_dir == NULL ? "" : list->set.index_dir,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.control_dir == NULL ?
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "" : list->set.control_dir,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.inbox_path == NULL ?
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "" : list->set.inbox_path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (hook_mailbox_list_created != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen hook_mailbox_list_created(list);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.mail_storage_flags = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.lock_method = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *list_r = list;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mailbox_list_deinit(struct mailbox_list *list)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_free_and_null(list->error);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->v.deinit(list);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainenconst char *mailbox_list_get_driver_name(struct mailbox_list *list)
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen{
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen return list->name;
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenchar mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->hierarchy_sep;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenbool mailbox_list_is_valid_mask(struct mailbox_list *list, const char *mask)
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen{
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen return list->v.is_valid_mask(list, mask);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *name)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->v.is_valid_existing_name(list, name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
a5e89374cb2fb2cad575fee6c3b33a9487ab9b3aTimo Sirainen const char *name)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return list->v.is_valid_create_name(list, name);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen enum mailbox_list_path_type type)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mailbox_list_clear_error(list);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->v.get_path(list, name, type);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->v.get_temp_prefix(list);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenconst char *mailbox_list_join_refmask(struct mailbox_list *list,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const char *ref, const char *mask)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (list->v.join_refmask != NULL)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return list->v.join_refmask(list, ref, mask);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* the default implementation: */
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (*ref != '\0') {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* merge reference and mask */
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen mask = t_strconcat(ref, mask, NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen return mask;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const char *name,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen enum mailbox_name_status *status)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen mailbox_list_clear_error(list);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *status = MAILBOX_NAME_INVALID;
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen return 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen return list->v.get_mailbox_name_status(list, name, status);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen}
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenstruct mailbox_list_iterate_context *
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenmailbox_list_iter_init(struct mailbox_list *list, const char *mask,
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen enum mailbox_list_iter_flags flags)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen{
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen mailbox_list_clear_error(list);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen return list->v.iter_init(list, mask, flags);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mailbox_info *
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenmailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen return ctx->list->v.iter_next(ctx);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
437a8b0fe254057b0c1f1723d689bafa91cae2abTimo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenint mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen{
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen struct mailbox_list_iterate_context *ctx = *_ctx;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *_ctx = NULL;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen return ctx->list->v.iter_deinit(ctx);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen const char *name, bool set)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen mailbox_list_clear_error(list);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen return list->v.set_subscribed(list, name, set);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenint mailbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (strcmp(name, "INBOX") == 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_error(list, "INBOX can't be deleted.");
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->v.delete_mailbox(list, name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint mailbox_list_rename_mailbox(struct mailbox_list *list,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *oldname, const char *newname)
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!mailbox_list_is_valid_existing_name(list, oldname) ||
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen !mailbox_list_is_valid_create_name(list, newname)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->v.rename_mailbox(list, oldname, newname);
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen}
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainenint mailbox_list_delete_index_control(struct mailbox_list *list,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const char *name)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const char *path, *index_dir, *dir;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen path = mailbox_list_get_path(list, name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen /* delete the index directory first, so that if we crash we don't
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen leave indexes for deleted mailboxes lying around */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen index_dir = mailbox_list_get_path(list, name,
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen if (*index_dir != '\0' && strcmp(index_dir, path) != 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (unlink_directory(index_dir, TRUE) < 0 && errno != ENOENT) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_critical(list,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen "unlink_directory(%s) failed: %m", index_dir);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* control directory next */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen if (*dir != '\0' && strcmp(dir, path) != 0 &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen strcmp(dir, index_dir) != 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (unlink_directory(dir, TRUE) < 0 && errno != ENOENT) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_critical(list,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "unlink_directory(%s) failed: %m", dir);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen }
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenbool mailbox_list_name_is_too_large(const char *name, char sep)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen unsigned int levels = 1, level_len = 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (; *name != '\0'; name++) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (*name == sep) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen levels++;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen level_len = 0;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen } else {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen level_len++;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen return TRUE;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen return FALSE;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenenum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen enum mailbox_list_file_type type;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen#ifdef HAVE_DIRENT_D_TYPE
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen switch (d->d_type) {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen case DT_UNKNOWN:
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen break;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen case DT_REG:
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen type = MAILBOX_LIST_FILE_TYPE_FILE;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen break;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen case DT_DIR:
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen type = MAILBOX_LIST_FILE_TYPE_DIR;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen break;
fd14806f879f6cd4f023750e0c4cac27a7f94fbbTimo Sirainen case DT_LNK:
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen type = MAILBOX_LIST_FILE_TYPE_SYMLINK;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen break;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen default:
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_OTHER;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen break;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen }
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen#else
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen#endif
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen return type;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenconst char *mailbox_list_get_last_error(struct mailbox_list *list,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen bool *temporary_error_r)
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen{
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen *temporary_error_r = list->temporary_error;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return list->error;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_free_and_null(list->error);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list->temporary_error = FALSE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_set_error(struct mailbox_list *list, const char *error)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_free(list->error);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list->error = i_strdup(error);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list->temporary_error = FALSE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct tm *tm;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen char str[256];
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen tm = localtime(&ioloop_time);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_free(list->error);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list->error =
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_strdup(str) : i_strdup(CRITICAL_MSG);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list->temporary_error = TRUE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen va_list va;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen va_start(va, fmt);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen va_end(va);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* critical errors may contain sensitive data, so let user
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen see only "Internal error" with a timestamp to make it
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen easier to look from log files the actual error message. */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mailbox_list_set_internal_error(list);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen