mailbox-list.c revision 740dfc753f1f087f0c41082e4c551053129e875d
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2006-2007 Timo 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. */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen/* Message to show to users when critical error occurs */
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 Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid (*hook_mailbox_list_created)(struct mailbox_list *list);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int i, count;
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) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen unsigned int idx;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_append(&mailbox_list_drivers, &list, 1);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen unsigned int idx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_list **list_r, const char **error_r)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen unsigned int idx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0');
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
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 :
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.control_dir = set->control_dir == NULL ||
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen if (mkdir_parents(list->set.index_dir, 0700) < 0 &&
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_error("mkdir(%s) failed: %m", list->set.index_dir);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mkdir_parents(list->set.control_dir, 0700) < 0 &&
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_error("mkdir(%s) failed: %m", list->set.control_dir);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen p_strdup(list->pool, set->subscription_fname);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.maildir_name = p_strdup(list->pool, set->maildir_name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->set.mail_storage_flags = set->mail_storage_flags;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen list->set.index_dir == NULL ? "" : list->set.index_dir,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mailbox_list_deinit(struct mailbox_list *list)
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainenconst char *mailbox_list_get_driver_name(struct mailbox_list *list)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenchar mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenbool mailbox_list_is_valid_mask(struct mailbox_list *list, const char *mask)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->v.is_valid_existing_name(list, name);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return list->v.is_valid_create_name(list, name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenconst char *mailbox_list_join_refmask(struct mailbox_list *list,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* the default implementation: */
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* merge reference and mask */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen return list->v.get_mailbox_name_status(list, name, status);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenmailbox_list_iter_init(struct mailbox_list *list, const char *mask,
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenmailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenint mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen struct mailbox_list_iterate_context *ctx = *_ctx;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen return list->v.set_subscribed(list, name, set);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenint mailbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_error(list, "INBOX can't be deleted.");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint mailbox_list_rename_mailbox(struct mailbox_list *list,
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");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return list->v.rename_mailbox(list, oldname, newname);
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainenint mailbox_list_delete_index_control(struct mailbox_list *list,
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen /* delete the index directory first, so that if we crash we don't
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen leave indexes for deleted mailboxes lying around */
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen if (*index_dir != '\0' && strcmp(index_dir, path) != 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (unlink_directory(index_dir, TRUE) < 0 && errno != ENOENT) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen "unlink_directory(%s) failed: %m", index_dir);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* control directory next */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (unlink_directory(dir, TRUE) < 0 && errno != ENOENT) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenbool mailbox_list_name_is_too_large(const char *name, char sep)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenenum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen switch (d->d_type) {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenconst char *mailbox_list_get_last_error(struct mailbox_list *list,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_set_error(struct mailbox_list *list, const char *error)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvoid mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
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. */