mailbox-list.c revision eb64c3586d854cddd693f0b811d897399076a441
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2006-2010 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "ioloop.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "mkdir-parents.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "str.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "sha1.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include "home-expand.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "close-keep-errno.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "eacces-error.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "read-full.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "write-full.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "safe-mkstemp.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include "unlink-directory.h"
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen#include "settings-parser.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "imap-match.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "imap-utf7.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "mailbox-log.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "mailbox-tree.h"
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen#include "mail-storage-private.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-private.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <time.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <unistd.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <dirent.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <sys/stat.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen then start renaming them to larger names from end to beginning, which
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen eventually would start causing the failures when trying to use too
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen long mailbox names. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILBOX_MAX_HIERARCHY_LEVELS 20
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstruct ns_list_iterate_context {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct mailbox_list_iterate_context ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct mailbox_list_iterate_context *backend_ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct mail_namespace *namespaces;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen pool_t pool;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen const char **patterns, **patterns_ns_match;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen enum namespace_type type_mask;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen};
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mailbox_lists_init(void)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_array_init(&mailbox_list_drivers, 4);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mailbox_lists_deinit(void)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen array_free(&mailbox_list_drivers);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list *const *drivers;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i, count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < count; i++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *idx_r = i;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen unsigned int idx;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen list->name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_append(&mailbox_list_drivers, &list, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_delete(&mailbox_list_drivers, idx, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenconst struct mailbox_list *
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenmailbox_list_find_class(const char *driver)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const struct mailbox_list *const *class_p;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen unsigned int idx;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (!mailbox_list_driver_find(driver, &idx))
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return NULL;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return *class_p;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint mailbox_list_create(const char *driver, struct mail_namespace *ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct mailbox_list_settings *set,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen enum mailbox_list_flags flags, const char **error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list *const *class_p;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_list *list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(ns->list == NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(set->subscription_fname == NULL ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *set->subscription_fname != '\0');
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "Unknown driver name";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (((*class_p)->props & MAILBOX_LIST_PROP_NO_MAILDIR_NAME) != 0 &&
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen set->maildir_name != NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "maildir_name not supported by this driver";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (((*class_p)->props & MAILBOX_LIST_PROP_NO_ALT_DIR) != 0 &&
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen set->alt_dir != NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "alt_dir not supported by this driver";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0' ||
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ((*class_p)->props & MAILBOX_LIST_PROP_NO_ROOT) != 0);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list = (*class_p)->v.alloc();
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->ns = ns;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->mail_set = ns->mail_set;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->flags = flags;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->file_create_mode = (mode_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->dir_create_mode = (mode_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->file_create_gid = (gid_t)-1;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp = (time_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* copy settings */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (set->root_dir != NULL) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.index_dir = set->index_dir == NULL ||
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen p_strdup(list->pool, set->index_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.control_dir = set->control_dir == NULL ||
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen p_strdup(list->pool, set->control_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.subscription_fname =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->subscription_fname);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen list->set.maildir_name = set->maildir_name == NULL ? "" :
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->maildir_name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->mailbox_dir_name);
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen list->set.alt_dir = p_strdup(list->pool, set->alt_dir);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (set->mailbox_dir_name == NULL || *set->mailbox_dir_name == '\0')
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name = "";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else if (set->mailbox_dir_name[strlen(set->mailbox_dir_name)-1] == '/') {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->mailbox_dir_name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strconcat(list->pool, set->mailbox_dir_name, "/", NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ns->mail_set->mail_debug) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("%s: root=%s, index=%s, control=%s, inbox=%s",
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->name,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.root_dir == NULL ? "" : list->set.root_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.index_dir == NULL ? "" : list->set.index_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.control_dir == NULL ?
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk "" : list->set.control_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.inbox_path == NULL ?
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk "" : list->set.inbox_path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_namespace_finish_list_init(ns, list);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen hook_mailbox_list_created(list);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen return 0;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen}
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenstatic int fix_path(struct mail_user *user, const char *path,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen const char **path_r, const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen size_t len = strlen(path);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (len > 1 && path[len-1] == '/')
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen path = t_strndup(path, len-1);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (path[0] == '~' && path[1] != '/') {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* ~otheruser/dir */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (home_try_expand(&path) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "No home directory for system user. "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Can't expand ", t_strcut(path, '/'),
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen " for ", NULL);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen } else {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (mail_user_try_home_expand(user, &path) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = "Home directory not set for user. "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Can't expand ~/ for ";
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen *path_r = path;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic const char *split_next_arg(const char *const **_args)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen const char *const *args = *_args;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen const char *str = args[0];
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen while (*args != NULL && **args == '\0') {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (*args == NULL) {
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen /* string ends with ":", just ignore it. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen break;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = t_strconcat(str, ":", *args, NULL);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *_args = args;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return str;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenint mailbox_list_settings_parse(struct mail_user *user, const char *data,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct mailbox_list_settings *set_r,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen const char *const *tmp, *key, *value, **dest, *str, *error;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen memset(set_r, 0, sizeof(*set_r));
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (*data == '\0')
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* <root dir> */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen tmp = t_strsplit(data, ":");
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = split_next_arg(&tmp);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (fix_path(user, str, &set_r->root_dir, &error) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(error, "mail root dir in: ", data, NULL);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen while (*tmp != NULL) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = split_next_arg(&tmp);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen value = strchr(str, '=');
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (value == NULL) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen key = str;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value = "";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen } else {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen key = t_strdup_until(str, value);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value++;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (strcmp(key, "INBOX") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->inbox_path;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "INDEX") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->index_dir;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "CONTROL") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->control_dir;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else if (strcmp(key, "ALT") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->alt_dir;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "LAYOUT") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->layout;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "SUBSCRIPTIONS") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->subscription_fname;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "DIRNAME") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->maildir_name;
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen else if (strcmp(key, "MAILBOXDIR") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->mailbox_dir_name;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = t_strdup_printf("Unknown setting: %s", key);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (fix_path(user, value, dest, &error) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(error, key, " in: ", data, NULL);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (set_r->index_dir != NULL && strcmp(set_r->index_dir, "MEMORY") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen set_r->index_dir = "";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenconst char *mailbox_list_get_unexpanded_path(struct mailbox_list *list,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen enum mailbox_list_path_type type)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const struct mail_storage_settings *mail_set;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *location = list->ns->unexpanded_set->location;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mail_user *user = list->ns->user;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mailbox_list_settings set;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *p, *error;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (*location == SETTING_STRVAR_EXPANDED[0]) {
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen /* set using -o or userdb lookup. */
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen return "";
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen }
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen i_assert(*location == SETTING_STRVAR_UNEXPANDED[0]);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (*location == '\0') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_set = mail_user_set_get_driver_settings(user->set_info,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen user->unexpanded_set, MAIL_STORAGE_SET_DRIVER_NAME);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i_assert(mail_set != NULL);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location = mail_set->mail_location;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (*location == SETTING_STRVAR_EXPANDED[0])
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen return "";
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen i_assert(*location == SETTING_STRVAR_UNEXPANDED[0]);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* type:settings */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strchr(location, ':');
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mailbox_list_settings_parse(user, p + 1, &set, &error) < 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return mailbox_list_get_root_path(&set, type);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid mailbox_list_destroy(struct mailbox_list **_list)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mailbox_list *list = *_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *_list = NULL;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen if (list->changelog != NULL)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen mailbox_log_free(&list->changelog);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->v.deinit(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenconst char *mailbox_list_get_driver_name(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->name;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenchar mailbox_list_get_hierarchy_sep(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->hierarchy_sep;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenenum mailbox_list_flags mailbox_list_get_flags(const struct mailbox_list *list)
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen{
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen return list->flags;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenstruct mail_namespace *
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenmailbox_list_get_namespace(const struct mailbox_list *list)
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen{
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen return list->ns;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainenstatic mode_t get_dir_mode(mode_t mode)
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen{
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen /* add the execute bit if either read or write bit is set */
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0600) != 0) mode |= 0100;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0060) != 0) mode |= 0010;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0006) != 0) mode |= 0001;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen return mode;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen}
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstruct mail_user *
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenmailbox_list_get_user(const struct mailbox_list *list)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return list->ns->user;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint mailbox_list_get_storage(struct mailbox_list **list, const char **name,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage **storage_r)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((*list)->v.get_storage != NULL)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return (*list)->v.get_storage(list, name, storage_r);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *storage_r = (*list)->ns->storage;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid mailbox_list_get_closest_storage(struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage **storage)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *storage = list->ns->storage;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainenstatic void
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainenmailbox_list_get_permissions_full(struct mailbox_list *list, const char *name,
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen mode_t *file_mode_r, mode_t *dir_mode_r,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen gid_t *gid_r, const char **gid_origin_r)
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen{
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen const char *path;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen struct stat st;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* use safe defaults */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen *file_mode_r = 0600;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen *dir_mode_r = 0700;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen *gid_r = (gid_t)-1;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen *gid_origin_r = "defaults";
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
b82d6d7f02734007c129fa25bc876049c8d9bddeTimo Sirainen path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (path == NULL) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* no filesystem support in storage */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen } else if (stat(path, &st) < 0) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen if (!ENOTFOUND(errno)) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m",
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen path);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else if (list->mail_set->mail_debug) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("Namespace %s: Permission lookup failed from %s",
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen list->ns->prefix, path);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (name != NULL) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* return defaults */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mailbox_list_get_permissions_full(list, NULL,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen file_mode_r,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen dir_mode_r, gid_r,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen gid_origin_r);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen } else {
0910ea0672c0295c442eb686cc41e98656831f37Timo Sirainen *file_mode_r = (st.st_mode & 0666) | 0600;
0910ea0672c0295c442eb686cc41e98656831f37Timo Sirainen *dir_mode_r = (st.st_mode & 0777) | 0700;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen *gid_origin_r = path;
e91543761d0b7b97a1dc28e036e44d76405545c2Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (!S_ISDIR(st.st_mode)) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* we're getting permissions from a file.
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen apply +x modes as necessary. */
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *dir_mode_r = get_dir_mode(*dir_mode_r);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* directory's GID is used automatically for new
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen files */
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *gid_r = (gid_t)-1;
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen } else if ((st.st_mode & 0070) >> 3 == (st.st_mode & 0007)) {
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen /* group has same permissions as world, so don't bother
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen changing it */
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *gid_r = (gid_t)-1;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen } else if (getegid() == st.st_gid) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* using our own gid, no need to change it */
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *gid_r = (gid_t)-1;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen } else {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *gid_r = st.st_gid;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen }
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (name == NULL) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen list->file_create_mode = *file_mode_r;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen list->dir_create_mode = *dir_mode_r;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen list->file_create_gid = *gid_r;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen list->file_create_gid_origin =
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen p_strdup(list->pool, *gid_origin_r);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen if (list->mail_set->mail_debug && name == NULL) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("Namespace %s: Using permissions from %s: "
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen "mode=0%o gid=%ld", list->ns->prefix,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen path != NULL ? path : "",
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk (int)list->dir_create_mode,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->file_create_gid == (gid_t)-1 ? -1L :
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk (long)list->file_create_gid);
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen }
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen}
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenvoid mailbox_list_get_permissions(struct mailbox_list *list,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen const char *name,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen mode_t *mode_r, gid_t *gid_r,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen const char **gid_origin_r)
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen{
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen mode_t dir_mode;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (list->file_create_mode != (mode_t)-1 && name == NULL) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *mode_r = list->file_create_mode;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *gid_r = list->file_create_gid;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen *gid_origin_r = list->file_create_gid_origin;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen return;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen mailbox_list_get_permissions_full(list, name, mode_r, &dir_mode, gid_r,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen gid_origin_r);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen}
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainenvoid mailbox_list_get_dir_permissions(struct mailbox_list *list,
b82d6d7f02734007c129fa25bc876049c8d9bddeTimo Sirainen const char *name,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen mode_t *mode_r, gid_t *gid_r,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen const char **gid_origin_r)
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen{
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen mode_t file_mode;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (list->dir_create_mode != (mode_t)-1 && name == NULL) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *mode_r = list->dir_create_mode;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *gid_r = list->file_create_gid;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen *gid_origin_r = list->file_create_gid_origin;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen return;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen mailbox_list_get_permissions_full(list, name, &file_mode,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen mode_r, gid_r, gid_origin_r);
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen}
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic int
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenmailbox_list_stat_parent(struct mailbox_list *list, const char *path,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char **root_dir_r, struct stat *st_r)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *p;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen while (stat(path, st_r) < 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (errno != ENOENT || strcmp(path, "/") == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m",
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen path);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strrchr(path, '/');
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen path = "/";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen else
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen path = t_strdup_until(path, p);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen *root_dir_r = path;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic const char *
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenget_expanded_path(const char *unexpanded_start, const char *unexpanded_stop,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *expanded_full)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unsigned int i, slash_count = 0, slash2_count = 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* get the expanded path up to the same amount of '/' characters.
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if there isn't the same amount of '/' characters, it means %variable
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expansion added more of them and we can't handle this. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; unexpanded_start+i != unexpanded_stop; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (unexpanded_start[i] == '/')
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash_count++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (; unexpanded_start[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (unexpanded_start[i] == '/')
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash2_count++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; expanded_full[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (expanded_full[i] == '/') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash_count == 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen break;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash_count--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash_count != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen ret = t_strndup(expanded_full, i);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (; expanded_full[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (expanded_full[i] == '/') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash2_count == 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash2_count--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash2_count != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint mailbox_list_mkdir(struct mailbox_list *list, const char *path,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen enum mailbox_list_path_type type)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *expanded, *unexpanded, *root_dir, *p, *origin;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct stat st;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mode_t mode;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen gid_t gid;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* get the directory path up to last %variable. for example
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unexpanded path may be "/var/mail/%d/%2n/%n/Maildir", and we want
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen to get expanded="/var/mail/domain/nn" */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unexpanded = mailbox_list_get_unexpanded_path(list, type);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strrchr(unexpanded, '%');
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen while (p != unexpanded && *p != '/') p--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == unexpanded)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = mailbox_list_get_path(list, NULL, type);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = get_expanded_path(unexpanded, p, expanded);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (*expanded != '\0') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* up to this directory get the permissions from the first
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen parent directory that exists, if it has setgid bit
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen enabled. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mailbox_list_stat_parent(list, expanded,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen &root_dir, &st) < 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if ((st.st_mode & S_ISGID) != 0 && root_dir != expanded) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mkdir_parents_chgrp(expanded, st.st_mode,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (gid_t)-1, root_dir) < 0 &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen errno != EEXIST) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mailbox_list_set_critical(list,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "mkdir(%s) failed: %m", expanded);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (gid == (gid_t)-1 && (mode & S_ISGID) == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* change the group for user directories */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen gid = getegid();
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* the rest of the directories exist only for one user. create them
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen with default directory permissions */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mkdir_parents_chgrp(path, mode, gid, origin) < 0 &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen errno != EEXIST) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mailbox_list_set_critical(list, "mkdir(%s) failed: %m", path);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenbool mailbox_list_is_valid_pattern(struct mailbox_list *list,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen const char *pattern)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen bool ret;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen T_BEGIN {
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen ret = list->v.is_valid_pattern(list, pattern);
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen } T_END;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen return ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen bool ret;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen
9f1a154d6f436e67f22f737f66bb148b502d4d2aTimo Sirainen if (*name == '\0' && *list->ns->prefix != '\0') {
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen /* an ugly way to get to mailbox root (e.g. Maildir/ when
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen it's not the INBOX) */
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen return TRUE;
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen }
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen T_BEGIN {
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen ret = list->v.is_valid_existing_name(list, name);
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen } T_END;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen return ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen const char *p;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen int ret;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen /* safer to just disallow all control characters */
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen for (p = name; *p != '\0'; p++) {
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen if (*p < ' ')
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen return FALSE;
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen }
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen T_BEGIN {
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen string_t *str = t_str_new(256);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen ret = imap_utf7_to_utf8(name, str);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen } T_END;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen return ret < 0 ? FALSE :
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen list->v.is_valid_create_name(list, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_path_type type)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->v.get_path(list, name, type);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainenconst char *
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainenmailbox_list_get_root_path(const struct mailbox_list_settings *set,
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen enum mailbox_list_path_type type)
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen{
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen const char *path;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen switch (type) {
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->alt_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (*set->mailbox_dir_name == '\0')
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen path = t_strconcat(set->root_dir, "/",
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->mailbox_dir_name, NULL);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return t_strndup(path, strlen(path)-1);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (*set->mailbox_dir_name == '\0')
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen path = t_strconcat(set->alt_dir, "/",
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->mailbox_dir_name, NULL);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return t_strndup(path, strlen(path)-1);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->control_dir != NULL ?
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->control_dir : set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->index_dir != NULL ?
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->index_dir : set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen }
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen i_unreached();
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen}
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return list->v.get_temp_prefix(list, FALSE);
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen}
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainenconst char *mailbox_list_get_global_temp_prefix(struct mailbox_list *list)
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen{
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return list->v.get_temp_prefix(list, TRUE);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenconst char *mailbox_list_join_refpattern(struct mailbox_list *list,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen const char *ref, const char *pattern)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen{
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen if (list->v.join_refpattern != NULL)
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return list->v.join_refpattern(list, ref, pattern);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen /* the default implementation: */
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen if (*ref != '\0') {
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen /* merge reference and pattern */
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen pattern = t_strconcat(ref, pattern, NULL);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen }
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return pattern;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen}
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_name_status *status)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen *status = MAILBOX_NAME_INVALID;
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen return 0;
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->v.get_mailbox_name_status(list, name, status);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct mailbox_list_iterate_context *
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenmailbox_list_iter_init(struct mailbox_list *list, const char *pattern,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_iter_flags flags)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen const char *patterns[2];
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen patterns[0] = pattern;
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen patterns[1] = NULL;
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen return mailbox_list_iter_init_multiple(list, patterns, flags);
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen}
f97cacf16251b42f530c6a28686cc8c9aa7df3a2Timo Sirainen
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenstruct mailbox_list_iterate_context *
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenmailbox_list_iter_init_multiple(struct mailbox_list *list,
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen const char *const *patterns,
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen enum mailbox_list_iter_flags flags)
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen{
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen i_assert(*patterns != NULL);
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen /* we'll want to remove MAILBOX_LIST_ITER_VIRTUAL_NAMES flag completely.
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen this assert will be here until it's sure that there are no more
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen non-virtual users and it can be safely removed. (and if there are,
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen this assert can still be easily removed) */
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen i_assert((flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0);
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen return list->v.iter_init(list, patterns, flags);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenstatic bool
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenns_match_simple(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen{
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if ((ctx->type_mask & ns->type) == 0)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return FALSE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SKIP_ALIASES) != 0) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (ns->alias_for != NULL)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return FALSE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return TRUE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen}
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainenstatic bool
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainenns_match_inbox(struct mail_namespace *ns, const char *pattern)
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen{
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen struct imap_match_glob *glob;
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) == 0)
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen return FALSE;
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen glob = imap_match_init(pool_datastack_create(), pattern,
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen TRUE, ns->sep);
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen return imap_match(glob, "INBOX") == IMAP_MATCH_YES;
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen}
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenstatic bool
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenns_match_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen const char *pattern)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen{
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen struct imap_match_glob *glob;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen enum imap_match_result result;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen const char *prefix_without_sep;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen unsigned int len;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen len = ns->prefix_len;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (len > 0 && ns->prefix[len-1] == ns->sep)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen len--;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) == 0) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* non-listable namespace matches only with exact prefix */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (strncmp(ns->prefix, pattern, ns->prefix_len) != 0)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return FALSE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen prefix_without_sep = t_strndup(ns->prefix, len);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (*prefix_without_sep == '\0')
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen result = IMAP_MATCH_CHILDREN;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen else {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen glob = imap_match_init(pool_datastack_create(), pattern,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen TRUE, ns->sep);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen result = imap_match(glob, prefix_without_sep);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if ((ctx->ctx.flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) == 0) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen switch (result) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_YES:
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_CHILDREN:
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return TRUE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_NO:
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_PARENT:
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen break;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return FALSE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen switch (result) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_YES:
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* allow matching prefix only when it's done without
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen wildcards */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (strcmp(prefix_without_sep, pattern) == 0)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return TRUE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen break;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_CHILDREN: {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* allow this only if there isn't another namespace
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen with longer prefix that matches this pattern
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen (namespaces are sorted by prefix length) */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen struct mail_namespace *tmp;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen T_BEGIN {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen for (tmp = ns->next; tmp != NULL; tmp = tmp->next) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (ns_match_simple(ctx, tmp) &&
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen ns_match_next(ctx, tmp, pattern))
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen break;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen } T_END;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (tmp == NULL)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return TRUE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen break;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_NO:
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen case IMAP_MATCH_PARENT:
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen break;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return FALSE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen}
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenstatic bool
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenns_match(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen{
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen unsigned int i;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (!ns_match_simple(ctx, ns))
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return FALSE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if ((ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* filter out namespaces whose prefix doesn't match.
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen this same code handles both with and without
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen STAR_WITHIN_NS, so the "without" case is slower than
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen necessary, but this shouldn't matter much */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen T_BEGIN {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen for (i = 0; ctx->patterns_ns_match[i] != NULL; i++) {
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen if (ns_match_inbox(ns, ctx->patterns_ns_match[i]))
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen break;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (ns_match_next(ctx, ns,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen ctx->patterns_ns_match[i]))
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen break;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen } T_END;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (ctx->patterns_ns_match[i] == NULL)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return FALSE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return ns;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen}
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainenstatic struct mail_namespace *
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainenns_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen{
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen for (; ns != NULL; ns = ns->next) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (ns_match(ctx, ns))
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen break;
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen }
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen return ns;
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen}
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstatic const struct mailbox_info *
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenmailbox_list_ns_iter_next(struct mailbox_list_iterate_context *_ctx)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen{
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct ns_list_iterate_context *ctx =
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen (struct ns_list_iterate_context *)_ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen const struct mailbox_info *info;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen info = ctx->backend_ctx == NULL ? NULL :
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen mailbox_list_iter_next(ctx->backend_ctx);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (info == NULL && ctx->namespaces != NULL) {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen /* go to the next namespace */
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen _ctx->failed = TRUE;
407453d06e5622ac3bf099cc76bfcbfb5860b444Timo Sirainen ctx->ctx.list->ns = ctx->namespaces;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->backend_ctx =
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen mailbox_list_iter_init_multiple(ctx->namespaces->list,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->patterns,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen _ctx->flags);
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen ctx->namespaces = ns_next(ctx, ctx->namespaces->next);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return mailbox_list_ns_iter_next(_ctx);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen }
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return info;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen}
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstatic int
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenmailbox_list_ns_iter_deinit(struct mailbox_list_iterate_context *_ctx)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen{
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct ns_list_iterate_context *ctx =
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen (struct ns_list_iterate_context *)_ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen int ret;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (ctx->backend_ctx != NULL) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen _ctx->failed = TRUE;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ret = _ctx->failed ? -1 : 0;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen pool_unref(&ctx->pool);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return ret;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen}
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenstatic const char **
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainendup_patterns_without_stars(pool_t pool, const char *const *patterns,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen unsigned int count)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen{
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen const char **dup;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen unsigned int i;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen dup = p_new(pool, const char *, count + 1);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen for (i = 0; i < count; i++) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen char *p = p_strdup(pool, patterns[i]);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen dup[i] = p;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen for (; *p != '\0'; p++) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (*p == '*')
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen *p = '%';
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen return dup;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen}
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstruct mailbox_list_iterate_context *
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenmailbox_list_iter_init_namespaces(struct mail_namespace *namespaces,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen const char *const *patterns,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen enum namespace_type type_mask,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen enum mailbox_list_iter_flags flags)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen{
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen struct ns_list_iterate_context *ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen unsigned int i, count;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen pool_t pool;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen i_assert(namespaces != NULL);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen i_assert((flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) == 0 ||
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen (flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen pool = pool_alloconly_create("mailbox list namespaces", 1024);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx = p_new(pool, struct ns_list_iterate_context, 1);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->pool = pool;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen ctx->type_mask = type_mask;
e7157fa0ad659fa7984f3e6c59c195221c53ac64Timo Sirainen ctx->ctx.flags = flags;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->ctx.list = p_new(pool, struct mailbox_list, 1);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->ctx.list->v.iter_next = mailbox_list_ns_iter_next;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->ctx.list->v.iter_deinit = mailbox_list_ns_iter_deinit;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen count = str_array_length(patterns);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->patterns = p_new(pool, const char *, count + 1);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen for (i = 0; i < count; i++)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen ctx->patterns[i] = p_strdup(pool, patterns[i]);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if ((flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) != 0) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* create copies of patterns with '*' wildcard changed to '%' */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen ctx->patterns_ns_match =
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen dup_patterns_without_stars(pool, ctx->patterns, count);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen } else {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen ctx->patterns_ns_match = ctx->patterns;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen namespaces = ns_next(ctx, namespaces);
407453d06e5622ac3bf099cc76bfcbfb5860b444Timo Sirainen ctx->ctx.list->ns = namespaces;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (namespaces != NULL) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen ctx->backend_ctx =
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen mailbox_list_iter_init_multiple(namespaces->list,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen patterns, flags);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen ctx->namespaces = ns_next(ctx, namespaces->next);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen }
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen return &ctx->ctx;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen}
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
61e84692827b6a64912343f515c984853021483aTimo Sirainenconst struct mailbox_info *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
b337d3b6871b878d6467d7d8ed600433af5da5a1Timo Sirainen const struct mailbox_info *info;
b337d3b6871b878d6467d7d8ed600433af5da5a1Timo Sirainen
b337d3b6871b878d6467d7d8ed600433af5da5a1Timo Sirainen info = ctx->list->v.iter_next(ctx);
b337d3b6871b878d6467d7d8ed600433af5da5a1Timo Sirainen if (info != NULL)
b337d3b6871b878d6467d7d8ed600433af5da5a1Timo Sirainen ctx->list->ns->flags |= NAMESPACE_FLAG_USABLE;
b337d3b6871b878d6467d7d8ed600433af5da5a1Timo Sirainen return info;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_list_iterate_context *ctx = *_ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *_ctx = NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return ctx->list->v.iter_deinit(ctx);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainenint mailbox_list_mailbox(struct mailbox_list *list, const char *name,
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen enum mailbox_info_flags *flags_r)
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen{
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen const char *path, *fname, *rootdir, *inbox;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen struct stat st;
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen unsigned int len;
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen rootdir = mailbox_list_get_path(list, NULL,
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
81fa2cf342657ee5ed02b7b36014dc08a254b006Timo Sirainen if (rootdir == NULL) {
af86c8415338fc2ea1819dc091b971c93cbee5d2Timo Sirainen /* shouldn't happen with anything except shared mailboxes */
af86c8415338fc2ea1819dc091b971c93cbee5d2Timo Sirainen return 0;
af86c8415338fc2ea1819dc091b971c93cbee5d2Timo Sirainen }
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen len = strlen(rootdir);
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen if (strncmp(path, rootdir, len) == 0 && path[len] == '/') {
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen fname = strrchr(path, '/');
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen if (fname == NULL) {
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen fname = path;
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen path = "/";
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen } else {
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen path = t_strdup_until(path, fname);
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen fname++;
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen }
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen } else {
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen /* a) looking up INBOX that's elsewhere
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen b) looking up the root dir itself (as INBOX or "") */
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen fname = "";
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen }
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen if (*fname == '\0' && *name == '\0' &&
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen /* if INBOX is in e.g. ~/Maildir, it shouldn't be possible to
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen access it also via namespace prefix. */
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen inbox = mailbox_list_get_path(list, "INBOX",
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen if (strcmp(inbox, path) == 0) {
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen *flags_r |= MAILBOX_NONEXISTENT;
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen return 0;
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen }
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen }
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen return list->v.get_mailbox_flags(list, path, fname,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen MAILBOX_LIST_FILE_TYPE_UNKNOWN,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen &st, flags_r);
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen}
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainenstatic bool mailbox_list_init_changelog(struct mailbox_list *list)
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen{
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen const char *path;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen mode_t mode;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen gid_t gid;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen const char *gid_origin;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen if (list->changelog != NULL)
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return TRUE;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen /* don't do this in mailbox_list_create(), because _get_path() might be
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen overridden by storage (mbox). */
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen path = mailbox_list_get_path(list, NULL, MAILBOX_LIST_PATH_TYPE_INDEX);
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen if (path == NULL)
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return FALSE;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen path = t_strconcat(path, "/"MAILBOX_LOG_FILE_NAME, NULL);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen list->changelog = mailbox_log_alloc(path);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen mailbox_list_get_permissions(list, NULL, &mode, &gid, &gid_origin);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen mailbox_log_set_permissions(list->changelog, mode, gid, gid_origin);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen return TRUE;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen}
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenvoid mailbox_list_add_change(struct mailbox_list *list,
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen enum mailbox_log_record_type type,
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen const uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen{
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen struct mailbox_log_record rec;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen time_t stamp;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen if (!mailbox_list_init_changelog(list) ||
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen mail_guid_128_is_empty(mailbox_guid))
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen stamp = list->changelog_timestamp != (time_t)-1 ?
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp : ioloop_time;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen memset(&rec, 0, sizeof(rec));
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen rec.type = type;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen memcpy(rec.mailbox_guid, mailbox_guid, sizeof(rec.mailbox_guid));
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen mailbox_log_record_set_timestamp(&rec, stamp);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen (void)mailbox_log_append(list->changelog, &rec);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen}
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name, bool set)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen uint8_t guid[MAIL_GUID_128_SIZE];
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen if (list->v.set_subscribed(list, name, set) < 0)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return -1;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen /* subscriptions are about names, not about mailboxes. it's possible
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen to have a subscription to non-existing mailbox. renames also don't
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen change subscriptions. so instead of using actual GUIDs, we'll use
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen hash of the name. */
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen mailbox_name_get_sha128(name, guid);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen mailbox_list_add_change(list, set ? MAILBOX_LOG_RECORD_SUBSCRIBE :
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen MAILBOX_LOG_RECORD_UNSUBSCRIBE, guid);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainenint mailbox_list_delete_dir(struct mailbox_list *list, const char *name)
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen{
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen if (!mailbox_list_is_valid_existing_name(list, name) || *name == '\0') {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen "Invalid mailbox name");
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen }
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return list->v.delete_dir(list, name);
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen}
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainenvoid mailbox_name_get_sha128(const char *name, uint8_t guid[MAIL_GUID_128_SIZE])
0185427dd52fddec6fc76d6e99c7659620d4366eTimo Sirainen{
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen unsigned char sha[SHA1_RESULTLEN];
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen sha1_get_digest(name, strlen(name), sha);
ed704d95cc94390bba7ebf085945caf5957b0c9fTimo Sirainen memcpy(guid, sha, I_MIN(MAIL_GUID_128_SIZE, sizeof(sha)));
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen}
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstruct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen{
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return !mailbox_list_init_changelog(list) ? NULL : list->changelog;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen}
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainenvoid mailbox_list_set_changelog_timestamp(struct mailbox_list *list,
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen time_t stamp)
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen{
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp = stamp;
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen}
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenstatic void node_fix_parents(struct mailbox_node *node)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen{
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* If we happened to create any of the parents, we need to mark them
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen nonexistent. */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node = node->parent;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen for (; node != NULL; node = node->parent) {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if ((node->flags & MAILBOX_MATCHED) == 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags |= MAILBOX_NONEXISTENT;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen}
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainenmailbox_list_iter_update_real(struct mailbox_list_iter_update_context *ctx,
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen const char *name)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen{
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen struct mail_namespace *ns = ctx->iter_ctx->list->ns;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen struct mailbox_node *node;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen enum mailbox_info_flags create_flags = 0, always_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen enum imap_match_result match;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen const char *p;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen bool created, add_matched;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen if (ctx->update_only ||
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen (ctx->iter_ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0)
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen create_flags = MAILBOX_NONEXISTENT | MAILBOX_NOCHILDREN;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen always_flags = ctx->leaf_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen add_matched = TRUE;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen for (;;) {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen created = FALSE;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen match = imap_match(ctx->glob, name);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (match == IMAP_MATCH_YES) {
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen node = ctx->update_only ?
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen mailbox_tree_lookup(ctx->tree_ctx, name) :
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen mailbox_tree_get(ctx->tree_ctx, name, &created);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (created) {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags = create_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (create_flags != 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node_fix_parents(node);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (node != NULL) {
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen if (!ctx->update_only && add_matched)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags |= MAILBOX_MATCHED;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen node->flags |= always_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* We don't want to show the parent mailboxes unless
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen something else matches them, but if they are matched
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen we want to show them having child subscriptions */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen add_matched = FALSE;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen } else {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if ((match & IMAP_MATCH_PARENT) == 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen break;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* We've a (possibly) non-subscribed parent mailbox
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen which has a subscribed child mailbox. Make sure we
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen return the parent mailbox. */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen if (!ctx->match_parents)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen break;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen /* see if parent matches */
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen p = strrchr(name, ns->sep);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (p == NULL)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen break;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen name = t_strdup_until(name, p);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen create_flags &= ~MAILBOX_NOCHILDREN;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen always_flags = MAILBOX_CHILDREN | ctx->parent_flags;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainenvoid mailbox_list_iter_update(struct mailbox_list_iter_update_context *ctx,
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen const char *name)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen mailbox_list_iter_update_real(ctx, name);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen}
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_name_is_too_large(const char *name, char sep)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int levels = 1, level_len = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (; *name != '\0'; name++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*name == sep) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen levels++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen level_len = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen level_len++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff4bb2dfb5714eeb0408d3bb862de1646351d097Timo Sirainenenum mailbox_list_file_type
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenmailbox_list_get_file_type(const struct dirent *d ATTR_UNUSED)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_file_type type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#ifdef HAVE_DIRENT_D_TYPE
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen switch (d->d_type) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_UNKNOWN:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_REG:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_FILE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_DIR:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_DIR;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_LNK:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_SYMLINK;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen default:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_OTHER;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#else
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#endif
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenstatic bool
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenmailbox_list_try_get_home_path(struct mailbox_list *list, const char **name)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen{
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if ((*name)[1] == '/') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* ~/dir - use the configured home directory */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (mail_user_try_home_expand(list->ns->user, name) < 0)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen } else {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* ~otheruser/dir - assume we're using system users */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (home_try_expand(name) < 0)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return TRUE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen}
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenbool mailbox_list_try_get_absolute_path(struct mailbox_list *list,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen const char **name)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen{
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen const char *root_dir, *path, *mailbox_name;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen unsigned int len;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (!list->mail_set->mail_full_filesystem_access)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (**name == '~') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* try to expand home directory */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (!mailbox_list_try_get_home_path(list, name)) {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* fallback to using actual "~name" mailbox */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen } else {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (**name != '/')
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* okay, we have an absolute path now. but check first if it points to
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen same directory as one of our regular mailboxes. */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen root_dir = mailbox_list_get_path(list, NULL,
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen len = strlen(root_dir);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (strncmp(root_dir, *name, len) == 0 && (*name)[len] == '/') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen mailbox_name = *name + len + 1;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen path = mailbox_list_get_path(list, mailbox_name,
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (strcmp(path, *name) == 0) {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* yeah, we can replace the full path with mailbox
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen name. this way we can use indexes. */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen *name = mailbox_name;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen}
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainenint mailbox_list_create_parent_dir(struct mailbox_list *list,
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen const char *mailbox, const char *path)
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen{
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen const char *p, *dir, *origin;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen gid_t gid;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen mode_t mode;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen p = strrchr(path, '/');
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen if (p == NULL)
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen return 0;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen dir = t_strdup_until(path, p);
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen mailbox_list_get_dir_permissions(list, mailbox, &mode, &gid, &origin);
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen if (mkdir_parents_chgrp(dir, mode, gid, origin) < 0 &&
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen errno != EEXIST) {
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen mailbox_list_set_critical(list, "mkdir_parents(%s) failed: %m",
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen dir);
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen return -1;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen }
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen return 0;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen}
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_last_error(struct mailbox_list *list,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error *error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (error_r != NULL)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen *error_r = list->error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return list->error_string != NULL ? list->error_string :
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Unknown internal list error";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = MAIL_ERROR_NONE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenvoid mailbox_list_set_error(struct mailbox_list *list,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error error, const char *string)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free(list->error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error_string = i_strdup(string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct tm *tm;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen char str[256];
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen tm = localtime(&ioloop_time);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free(list->error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error_string =
ac4e6609cbdca594db1b1c02afb1e372ab22e060Timo Sirainen strftime(str, sizeof(str),
ac4e6609cbdca594db1b1c02afb1e372ab22e060Timo Sirainen MAIL_ERRSTR_CRITICAL_MSG_STAMP, tm) > 0 ?
ac4e6609cbdca594db1b1c02afb1e372ab22e060Timo Sirainen i_strdup(str) : i_strdup(MAIL_ERRSTR_CRITICAL_MSG);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = MAIL_ERROR_TEMP;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_list va;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_start(va, fmt);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_end(va);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* critical errors may contain sensitive data, so let user
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen see only "Internal error" with a timestamp to make it
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen easier to look from log files the actual error message. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_internal_error(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenbool mailbox_list_set_error_from_errno(struct mailbox_list *list)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char *error_string;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error error;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return FALSE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, error, error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return TRUE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen}