diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
commit | 0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch) | |
tree | 3f3789daa2f6db22da6e55e92bee0062a7d613fe /src/doveadm/doveadm-mail-mailbox.c | |
parent | Initial commit. (diff) | |
download | dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip |
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doveadm/doveadm-mail-mailbox.c')
-rw-r--r-- | src/doveadm/doveadm-mail-mailbox.c | 857 |
1 files changed, 857 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-mail-mailbox.c b/src/doveadm/doveadm-mail-mailbox.c new file mode 100644 index 0000000..2b2c453 --- /dev/null +++ b/src/doveadm/doveadm-mail-mailbox.c @@ -0,0 +1,857 @@ +/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "unichar.h" +#include "imap-utf7.h" +#include "mail-namespace.h" +#include "mail-storage.h" +#include "mail-search-build.h" +#include "doveadm-print.h" +#include "doveadm-mailbox-list-iter.h" +#include "doveadm-mail.h" + +#include <stdio.h> + +struct doveadm_mailbox_cmd_context { + struct doveadm_mail_cmd_context ctx; + bool subscriptions; +}; + +struct mailbox_cmd_context { + struct doveadm_mailbox_cmd_context ctx; + ARRAY_TYPE(const_string) mailboxes; +}; + +struct create_cmd_context { + struct doveadm_mailbox_cmd_context ctx; + ARRAY_TYPE(const_string) mailboxes; + struct mailbox_update update; +}; + +struct delete_cmd_context { + struct doveadm_mailbox_cmd_context ctx; + ARRAY_TYPE(const_string) mailboxes; + bool recursive; + bool require_empty; + bool unsafe; +}; + +struct rename_cmd_context { + struct doveadm_mailbox_cmd_context ctx; + const char *oldname, *newname; +}; + +struct list_cmd_context { + struct doveadm_mailbox_cmd_context ctx; + struct mail_search_args *search_args; + bool mutf7; +}; + +struct update_cmd_context { + struct doveadm_mailbox_cmd_context ctx; + const char *mailbox; + struct mailbox_update update; +}; + +struct path_cmd_context { + struct doveadm_mailbox_cmd_context ctx; + const char *mailbox; + enum mailbox_list_path_type path_type; +}; + +static const char *mailbox_list_path_type_names[] = { + "dir", "alt-dir", "mailbox", "alt-mailbox", + "control", "index", "index-private" +}; + +void doveadm_mailbox_args_check(const char *const args[]) +{ + unsigned int i; + + for (i = 0; args[i] != NULL; i++) { + if (!uni_utf8_str_is_valid(args[i])) { + i_fatal_status(EX_DATAERR, + "Mailbox name not valid UTF-8: %s", args[i]); + } + } +} + +static bool cmd_mailbox_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct doveadm_mailbox_cmd_context *ctx = + (struct doveadm_mailbox_cmd_context *)_ctx; + + switch (c) { + case 's': + ctx->subscriptions = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +#define doveadm_mailbox_cmd_alloc(type) \ + (type *)doveadm_mailbox_cmd_alloc_size(sizeof(type)) +static struct doveadm_mail_cmd_context * +doveadm_mailbox_cmd_alloc_size(size_t size) +{ + struct doveadm_mail_cmd_context *ctx; + + ctx = doveadm_mail_cmd_alloc_size(size); + ctx->getopt_args = "s"; + ctx->v.parse_arg = cmd_mailbox_parse_arg; + return ctx; +} + +static bool +cmd_mailbox_list_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx; + + switch (c) { + case '7': + ctx->mutf7 = TRUE; + break; + case '8': + ctx->mutf7 = FALSE; + break; + case 's': + ctx->ctx.subscriptions = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static int +cmd_mailbox_list_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx; + enum mailbox_list_iter_flags iter_flags = + MAILBOX_LIST_ITER_RETURN_NO_FLAGS; + struct doveadm_mailbox_list_iter *iter; + const struct mailbox_info *info; + string_t *str = t_str_new(256); + + if (ctx->ctx.subscriptions) + iter_flags |= MAILBOX_LIST_ITER_SELECT_SUBSCRIBED; + + iter = doveadm_mailbox_list_iter_full_init(_ctx, user, ctx->search_args, + iter_flags); + while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) { + if (!ctx->mutf7) + doveadm_print(info->vname); + else { + str_truncate(str, 0); + if (imap_utf8_to_utf7(info->vname, str) < 0) + i_unreached(); + doveadm_print(str_c(str)); + } + } + if (doveadm_mailbox_list_iter_deinit(&iter) < 0) + return -1; + return 0; +} + +struct mail_search_args * +doveadm_mail_mailbox_search_args_build(const char *const args[]) +{ + struct mail_search_args *search_args; + struct mail_search_arg *arg; + enum mail_search_arg_type type; + unsigned int i; + + doveadm_mailbox_args_check(args); + search_args = mail_search_build_init(); + for (i = 0; args[i] != NULL; i++) { + if (strchr(args[i], '*') != NULL || + strchr(args[i], '%') != NULL) + type = SEARCH_MAILBOX_GLOB; + else + type = SEARCH_MAILBOX; + arg = mail_search_build_add(search_args, type); + arg->value.str = p_strdup(search_args->pool, args[i]); + } + if (i > 1) { + struct mail_search_arg *subargs = search_args->args; + + search_args->args = NULL; + arg = mail_search_build_add(search_args, SEARCH_OR); + arg->value.subargs = subargs; + } + return search_args; +} + +static void cmd_mailbox_list_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx; + + doveadm_print_header("mailbox", "mailbox", + DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); + ctx->search_args = doveadm_mail_mailbox_search_args_build(args); +} + +static void cmd_mailbox_list_deinit(struct doveadm_mail_cmd_context *_ctx) +{ + struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx; + + if (ctx->search_args != NULL) + mail_search_args_unref(&ctx->search_args); +} + +static struct doveadm_mail_cmd_context *cmd_mailbox_list_alloc(void) +{ + struct list_cmd_context *ctx; + + ctx = doveadm_mailbox_cmd_alloc(struct list_cmd_context); + ctx->ctx.ctx.v.init = cmd_mailbox_list_init; + ctx->ctx.ctx.v.deinit = cmd_mailbox_list_deinit; + ctx->ctx.ctx.v.run = cmd_mailbox_list_run; + ctx->ctx.ctx.v.parse_arg = cmd_mailbox_list_parse_arg; + ctx->ctx.ctx.getopt_args = "78s"; + doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); + return &ctx->ctx.ctx; +} + +static int +cmd_mailbox_create_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct create_cmd_context *ctx = (struct create_cmd_context *)_ctx; + struct mail_namespace *ns; + struct mailbox *box; + const char *name; + int ret = 0; + + array_foreach_elem(&ctx->mailboxes, name) { + size_t len; + bool directory = FALSE; + + ns = mail_namespace_find(user->namespaces, name); + len = strlen(name); + if (len > 0 && name[len-1] == mail_namespace_get_sep(ns)) { + name = t_strndup(name, len-1); + directory = TRUE; + } + + box = mailbox_alloc(ns->list, name, 0); + if (mailbox_create(box, &ctx->update, directory) < 0) { + i_error("Can't create mailbox %s: %s", name, + mailbox_get_last_internal_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); + ret = -1; + } + if (ctx->ctx.subscriptions) { + if (mailbox_set_subscribed(box, TRUE) < 0) { + i_error("Can't subscribe to mailbox %s: %s", name, + mailbox_get_last_internal_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); + ret = -1; + } + } + mailbox_free(&box); + } + return ret; +} + +static void cmd_mailbox_create_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct mailbox_cmd_context *ctx = (struct mailbox_cmd_context *)_ctx; + const char *name; + unsigned int i; + + if (args[0] == NULL) + doveadm_mail_help_name("mailbox create"); + doveadm_mailbox_args_check(args); + + for (i = 0; args[i] != NULL; i++) { + name = p_strdup(ctx->ctx.ctx.pool, args[i]); + array_push_back(&ctx->mailboxes, &name); + } +} + +static bool +cmd_mailbox_create_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct create_cmd_context *ctx = (struct create_cmd_context *)_ctx; + + switch (c) { + case 'g': + if (guid_128_from_string(optarg, ctx->update.mailbox_guid) < 0) + doveadm_mail_help_name("mailbox create"); + break; + case 's': + ctx->ctx.subscriptions = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static struct doveadm_mail_cmd_context *cmd_mailbox_create_alloc(void) +{ + struct create_cmd_context *ctx; + + ctx = doveadm_mailbox_cmd_alloc(struct create_cmd_context); + ctx->ctx.ctx.v.init = cmd_mailbox_create_init; + ctx->ctx.ctx.v.run = cmd_mailbox_create_run; + ctx->ctx.ctx.v.parse_arg = cmd_mailbox_create_parse_arg; + ctx->ctx.ctx.getopt_args = "g:s"; + p_array_init(&ctx->mailboxes, ctx->ctx.ctx.pool, 16); + return &ctx->ctx.ctx; +} + +static int i_strcmp_reverse_p(const char *const *s1, const char *const *s2) +{ + return -strcmp(*s1, *s2); +} + +static int +get_child_mailboxes(struct mail_user *user, ARRAY_TYPE(const_string) *mailboxes, + const char *name) +{ + struct mailbox_list_iterate_context *iter; + struct mail_namespace *ns; + const struct mailbox_info *info; + const char *pattern, *child_name; + + ns = mail_namespace_find(user->namespaces, name); + pattern = name[0] == '\0' ? "*" : + t_strdup_printf("%s%c*", name, mail_namespace_get_sep(ns)); + iter = mailbox_list_iter_init(ns->list, pattern, + MAILBOX_LIST_ITER_RETURN_NO_FLAGS); + while ((info = mailbox_list_iter_next(iter)) != NULL) { + child_name = t_strdup(info->vname); + array_push_back(mailboxes, &child_name); + } + return mailbox_list_iter_deinit(&iter); +} + +static int +cmd_mailbox_delete_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct delete_cmd_context *ctx = (struct delete_cmd_context *)_ctx; + struct mail_namespace *ns; + struct mailbox *box; + struct mail_storage *storage; + const char *name; + ARRAY_TYPE(const_string) recursive_mailboxes; + const ARRAY_TYPE(const_string) *mailboxes = &ctx->mailboxes; + enum mailbox_flags mailbox_flags = 0; + int ret = 0, ret2; + + if (ctx->unsafe) + mailbox_flags |= MAILBOX_FLAG_DELETE_UNSAFE; + if (ctx->recursive) { + t_array_init(&recursive_mailboxes, 32); + array_foreach_elem(&ctx->mailboxes, name) { + if (get_child_mailboxes(user, &recursive_mailboxes, + name) < 0) { + doveadm_mail_failed_error(_ctx, MAIL_ERROR_TEMP); + ret = -1; + } + if (name[0] != '\0') + array_push_back(&recursive_mailboxes, &name); + } + array_sort(&recursive_mailboxes, i_strcmp_reverse_p); + mailboxes = &recursive_mailboxes; + } + + array_foreach_elem(mailboxes, name) { + ns = mail_namespace_find(user->namespaces, name); + box = mailbox_alloc(ns->list, name, mailbox_flags); + storage = mailbox_get_storage(box); + ret2 = ctx->require_empty ? mailbox_delete_empty(box) : + mailbox_delete(box); + if (ret2 < 0) { + i_error("Can't delete mailbox %s: %s", name, + mailbox_get_last_internal_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); + ret = -1; + } + if (ctx->ctx.subscriptions) { + if (mailbox_set_subscribed(box, FALSE) < 0) { + i_error("Can't unsubscribe mailbox %s: %s", name, + mail_storage_get_last_internal_error(storage, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); + ret = -1; + } + } + mailbox_free(&box); + } + return ret; +} + +static void cmd_mailbox_delete_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct delete_cmd_context *ctx = (struct delete_cmd_context *)_ctx; + const char *name; + unsigned int i; + + if (args[0] == NULL) + doveadm_mail_help_name("mailbox delete"); + doveadm_mailbox_args_check(args); + + for (i = 0; args[i] != NULL; i++) { + name = p_strdup(ctx->ctx.ctx.pool, args[i]); + array_push_back(&ctx->mailboxes, &name); + } + array_sort(&ctx->mailboxes, i_strcmp_reverse_p); +} + +static bool +cmd_mailbox_delete_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct delete_cmd_context *ctx = (struct delete_cmd_context *)_ctx; + + switch (c) { + case 'r': + ctx->recursive = TRUE; + break; + case 's': + ctx->ctx.subscriptions = TRUE; + break; + case 'e': + ctx->require_empty = TRUE; + break; + case 'Z': + ctx->unsafe = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static struct doveadm_mail_cmd_context *cmd_mailbox_delete_alloc(void) +{ + struct delete_cmd_context *ctx; + + ctx = doveadm_mailbox_cmd_alloc(struct delete_cmd_context); + ctx->ctx.ctx.v.init = cmd_mailbox_delete_init; + ctx->ctx.ctx.v.run = cmd_mailbox_delete_run; + ctx->ctx.ctx.v.parse_arg = cmd_mailbox_delete_parse_arg; + ctx->ctx.ctx.getopt_args = "ersZ"; + p_array_init(&ctx->mailboxes, ctx->ctx.ctx.pool, 16); + return &ctx->ctx.ctx; +} + +static int +cmd_mailbox_rename_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct rename_cmd_context *ctx = (struct rename_cmd_context *)_ctx; + struct mail_namespace *oldns, *newns; + struct mailbox *oldbox, *newbox; + const char *oldname = ctx->oldname; + const char *newname = ctx->newname; + int ret = 0; + + oldns = mail_namespace_find(user->namespaces, oldname); + newns = mail_namespace_find(user->namespaces, newname); + oldbox = mailbox_alloc(oldns->list, oldname, 0); + newbox = mailbox_alloc(newns->list, newname, 0); + if (mailbox_rename(oldbox, newbox) < 0) { + i_error("Can't rename mailbox %s to %s: %s", oldname, newname, + mailbox_get_last_internal_error(oldbox, NULL)); + doveadm_mail_failed_mailbox(_ctx, oldbox); + ret = -1; + } + if (ctx->ctx.subscriptions) { + if (mailbox_set_subscribed(oldbox, FALSE) < 0) { + i_error("Can't unsubscribe mailbox %s: %s", ctx->oldname, + mailbox_get_last_internal_error(oldbox, NULL)); + doveadm_mail_failed_mailbox(_ctx, oldbox); + ret = -1; + } + if (mailbox_set_subscribed(newbox, TRUE) < 0) { + i_error("Can't subscribe to mailbox %s: %s", ctx->newname, + mailbox_get_last_internal_error(newbox, NULL)); + doveadm_mail_failed_mailbox(_ctx, newbox); + ret = -1; + } + } + + mailbox_free(&oldbox); + mailbox_free(&newbox); + return ret; +} + +static void cmd_mailbox_rename_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct rename_cmd_context *ctx = (struct rename_cmd_context *)_ctx; + + if (str_array_length(args) != 2) + doveadm_mail_help_name("mailbox rename"); + doveadm_mailbox_args_check(args); + + ctx->oldname = p_strdup(ctx->ctx.ctx.pool, args[0]); + ctx->newname = p_strdup(ctx->ctx.ctx.pool, args[1]); +} + +static struct doveadm_mail_cmd_context *cmd_mailbox_rename_alloc(void) +{ + struct rename_cmd_context *ctx; + + ctx = doveadm_mailbox_cmd_alloc(struct rename_cmd_context); + ctx->ctx.ctx.v.init = cmd_mailbox_rename_init; + ctx->ctx.ctx.v.run = cmd_mailbox_rename_run; + return &ctx->ctx.ctx; +} + +static int +cmd_mailbox_subscribe_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct mailbox_cmd_context *ctx = (struct mailbox_cmd_context *)_ctx; + struct mail_namespace *ns; + struct mailbox *box; + const char *name; + int ret = 0; + + array_foreach_elem(&ctx->mailboxes, name) { + ns = mail_namespace_find(user->namespaces, name); + box = mailbox_alloc(ns->list, name, 0); + if (mailbox_set_subscribed(box, ctx->ctx.subscriptions) < 0) { + i_error("Can't %s mailbox %s: %s", name, + ctx->ctx.subscriptions ? "subscribe to" : + "unsubscribe", + mailbox_get_last_internal_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); + ret = -1; + } + mailbox_free(&box); + } + return ret; +} + +static void cmd_mailbox_subscribe_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct mailbox_cmd_context *ctx = (struct mailbox_cmd_context *)_ctx; + const char *name; + unsigned int i; + + if (args[0] == NULL) { + doveadm_mail_help_name(ctx->ctx.subscriptions ? + "mailbox subscribe" : + "mailbox unsubscribe"); + } + doveadm_mailbox_args_check(args); + + for (i = 0; args[i] != NULL; i++) { + name = p_strdup(ctx->ctx.ctx.pool, args[i]); + array_push_back(&ctx->mailboxes, &name); + } +} + +static struct doveadm_mail_cmd_context * +cmd_mailbox_subscriptions_alloc(bool subscriptions) +{ + struct mailbox_cmd_context *ctx; + + ctx = doveadm_mail_cmd_alloc(struct mailbox_cmd_context); + ctx->ctx.subscriptions = subscriptions; + + ctx->ctx.ctx.v.parse_arg = cmd_mailbox_parse_arg; + ctx->ctx.ctx.v.init = cmd_mailbox_subscribe_init; + ctx->ctx.ctx.v.run = cmd_mailbox_subscribe_run; + p_array_init(&ctx->mailboxes, ctx->ctx.ctx.pool, 16); + return &ctx->ctx.ctx; +} + +static struct doveadm_mail_cmd_context *cmd_mailbox_subscribe_alloc(void) +{ + return cmd_mailbox_subscriptions_alloc(TRUE); +} + +static struct doveadm_mail_cmd_context *cmd_mailbox_unsubscribe_alloc(void) +{ + return cmd_mailbox_subscriptions_alloc(FALSE); +} + +static +void cmd_mailbox_update_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct update_cmd_context *ctx = (struct update_cmd_context *)_ctx; + + if (str_array_length(args) != 1) + doveadm_mail_help_name("mailbox update"); + + doveadm_mailbox_args_check(args); + + ctx->mailbox = args[0]; + + if ((ctx->update.min_first_recent_uid != 0 || + ctx->update.min_next_uid != 0) && + ctx->update.min_first_recent_uid > ctx->update.min_next_uid) { + i_fatal_status(EX_DATAERR, + "min_first_recent_uid > min_next_uid"); + } +} + +static +bool cmd_mailbox_update_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct update_cmd_context *ctx = (struct update_cmd_context *)_ctx; + + switch (c) { + case 'g': + if (guid_128_from_string(optarg, ctx->update.mailbox_guid) < 0) + doveadm_mail_help_name("mailbox update"); + break; + case 'V': + if (str_to_uint32(optarg, &(ctx->update.uid_validity)) < 0) + doveadm_mail_help_name("mailbox update"); + break; + case 'N': + if (str_to_uint32(optarg, &(ctx->update.min_next_uid)) < 0) + doveadm_mail_help_name("mailbox update"); + break; + case 'R': + if (str_to_uint32(optarg, &(ctx->update.min_first_recent_uid)) < 0) + doveadm_mail_help_name("mailbox update"); + break; + case 'H': + if (str_to_uint64(optarg, &(ctx->update.min_highest_modseq)) < 0) + doveadm_mail_help_name("mailbox update"); + break; + case 'P': + if (str_to_uint64(optarg, &(ctx->update.min_highest_pvt_modseq)) < 0) + doveadm_mail_help_name("mailbox update"); + break; + default: + return FALSE; + } + return TRUE; +} + +static +int cmd_mailbox_update_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct update_cmd_context *ctx = (struct update_cmd_context *)_ctx; + struct mail_namespace *ns; + struct mailbox *box; + enum mail_error mail_error; + int ret = 0; + + ns = mail_namespace_find(user->namespaces, ctx->mailbox); + box = mailbox_alloc(ns->list, ctx->mailbox, 0); + + if ((ret = mailbox_update(box, &(ctx->update))) != 0) { + i_error("Cannot update %s: %s", + ctx->mailbox, + mailbox_get_last_internal_error(box, &mail_error)); + doveadm_mail_failed_error(_ctx, mail_error); + } + + mailbox_free(&box); + + return ret; +} + +static +struct doveadm_mail_cmd_context *cmd_mailbox_update_alloc(void) +{ + struct update_cmd_context *ctx; + ctx = doveadm_mail_cmd_alloc(struct update_cmd_context); + ctx->ctx.ctx.v.parse_arg = cmd_mailbox_update_parse_arg; + ctx->ctx.ctx.v.init = cmd_mailbox_update_init; + ctx->ctx.ctx.v.run = cmd_mailbox_update_run; + return &ctx->ctx.ctx; +} + +static void +cmd_mailbox_path_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct update_cmd_context *ctx = (struct update_cmd_context *)_ctx; + + if (str_array_length(args) != 1) + doveadm_mail_help_name("mailbox path"); + + doveadm_mailbox_args_check(args); + + ctx->mailbox = args[0]; + doveadm_print_header("path", "path", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); +} + +static bool +mailbox_list_path_type_name_parse(const char *name, + enum mailbox_list_path_type *type_r) +{ + enum mailbox_list_path_type type; + + for (type = 0; type < N_ELEMENTS(mailbox_list_path_type_names); type++) { + if (strcmp(mailbox_list_path_type_names[type], name) == 0) { + *type_r = type; + return TRUE; + } + } + return FALSE; +} + +static bool +cmd_mailbox_path_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct path_cmd_context *ctx = (struct path_cmd_context *)_ctx; + + switch (c) { + case 't': + if (!mailbox_list_path_type_name_parse(optarg, &ctx->path_type)) + doveadm_mail_help_name("mailbox path"); + break; + default: + return FALSE; + } + return TRUE; +} + +static int +cmd_mailbox_path_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct path_cmd_context *ctx = (struct path_cmd_context *)_ctx; + struct mail_namespace *ns; + enum mail_error mail_error; + const char *storage_name, *path; + int ret; + + ns = mail_namespace_find(user->namespaces, ctx->mailbox); + storage_name = mailbox_list_get_storage_name(ns->list, ctx->mailbox); + ret = mailbox_list_get_path(ns->list, storage_name, ctx->path_type, &path); + if (ret < 0) { + i_error("Failed to lookup mailbox %s path: %s", + ctx->mailbox, + mailbox_list_get_last_internal_error(ns->list, &mail_error)); + doveadm_mail_failed_error(_ctx, mail_error); + } else if (ret > 0) { + doveadm_print(path); + } + return ret; +} + +static struct doveadm_mail_cmd_context *cmd_mailbox_path_alloc(void) +{ + struct path_cmd_context *ctx; + + ctx = doveadm_mail_cmd_alloc(struct path_cmd_context); + ctx->path_type = MAILBOX_LIST_PATH_TYPE_INDEX; + ctx->ctx.ctx.v.parse_arg = cmd_mailbox_path_parse_arg; + ctx->ctx.ctx.v.init = cmd_mailbox_path_init; + ctx->ctx.ctx.v.run = cmd_mailbox_path_run; + doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_list_ver2 = { + .name = "mailbox list", + .mail_cmd = cmd_mailbox_list_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-7|-8] [-s] [<mailbox mask> [...]]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('7', "mutf7", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('8', "utf8", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('s', "subscriptions", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('\0', "mailbox-mask", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_create_ver2 = { + .name = "mailbox create", + .mail_cmd = cmd_mailbox_create_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-s] [-g <guid>] <mailbox> [...]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('s', "subscriptions", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('g', "guid", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_delete_ver2 = { + .name = "mailbox delete", + .mail_cmd = cmd_mailbox_delete_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-e] [-r] [-s] [-Z] <mailbox> [...]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('e', "require-empty", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('s', "subscriptions", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('r', "recursive", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('Z', "unsafe", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_rename_ver2 = { + .name = "mailbox rename", + .mail_cmd = cmd_mailbox_rename_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-s] <old name> <new name>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('s', "subscriptions", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAM('\0', "new-name", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_subscribe_ver2 = { + .name = "mailbox subscribe", + .mail_cmd = cmd_mailbox_subscribe_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<mailbox> [...]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_unsubscribe_ver2 = { + .name = "mailbox unsubscribe", + .mail_cmd = cmd_mailbox_unsubscribe_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<mailbox> [...]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_update_ver2 = { + .name = "mailbox update", + .mail_cmd = cmd_mailbox_update_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[--mailbox-guid guid] [--uid-validity uid] [--min-next-uid uid] [--min-first-recent-uid uid] [--min-highest-modseq seq] [--min-highest-pvt-modseq seq] <mailbox>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('g', "mailbox-guid", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('V', "uid-validity", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('N', "min-next-uid", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('R', "min-first-recent-uid", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('H', "min-highest-modseq", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('P', "min-highest-pvt-modseq", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_mailbox_path_ver2 = { + .name = "mailbox path", + .mail_cmd = cmd_mailbox_path_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-t <type>] <mailbox>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0', "mailbox", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAM('t', "type", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAMS_END +}; + |