doveadm-mail-mailbox.c revision a18da4410dcd47ab8d9b40c09a76a54fa55b9c86
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2010-2016 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#include "array.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "str.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "unichar.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "imap-utf7.h"
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen#include "mail-namespace.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-storage.h"
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen#include "mail-search-build.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "doveadm-print.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "doveadm-mailbox-list-iter.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "doveadm-mail.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen#include <stdio.h>
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstruct doveadm_mailbox_cmd_context {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct doveadm_mail_cmd_context ctx;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen bool subscriptions;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mailbox_cmd_context {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct doveadm_mailbox_cmd_context ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ARRAY_TYPE(const_string) mailboxes;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct create_cmd_context {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct doveadm_mailbox_cmd_context ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ARRAY_TYPE(const_string) mailboxes;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen struct mailbox_update update;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen};
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainenstruct delete_cmd_context {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct doveadm_mailbox_cmd_context ctx;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen ARRAY_TYPE(const_string) mailboxes;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen bool recursive;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen};
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainenstruct rename_cmd_context {
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen struct doveadm_mailbox_cmd_context ctx;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen const char *oldname, *newname;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen};
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainenstruct list_cmd_context {
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen struct doveadm_mailbox_cmd_context ctx;
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen struct mail_search_args *search_args;
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen bool mutf7;
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen};
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenvoid doveadm_mailbox_args_check(const char *const args[])
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen{
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen unsigned int i;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen for (i = 0; args[i] != NULL; i++) {
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen if (!uni_utf8_str_is_valid(args[i])) {
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen i_fatal_status(EX_DATAERR,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Mailbox name not valid UTF-8: %s", args[i]);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen }
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen}
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
a9c8c1f74e5d2911d3c15657727a30b649d3bbc4Timo Sirainenstatic bool cmd_mailbox_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct doveadm_mailbox_cmd_context *ctx =
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen (struct doveadm_mailbox_cmd_context *)_ctx;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen switch (c) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen case 's':
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen ctx->subscriptions = TRUE;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen break;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen default:
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen return FALSE;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen }
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen return TRUE;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen}
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen#define doveadm_mailbox_cmd_alloc(type) \
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen (type *)doveadm_mailbox_cmd_alloc_size(sizeof(type))
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainenstatic struct doveadm_mail_cmd_context *
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainendoveadm_mailbox_cmd_alloc_size(size_t size)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen{
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen struct doveadm_mail_cmd_context *ctx;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen ctx = doveadm_mail_cmd_alloc_size(size);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ctx->getopt_args = "s";
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ctx->v.parse_arg = cmd_mailbox_parse_arg;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return ctx;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen}
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic bool
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainencmd_mailbox_list_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen{
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx;
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen switch (c) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen case '7':
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ctx->mutf7 = TRUE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen break;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen case '8':
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ctx->mutf7 = FALSE;
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen break;
749b9176d6d1da2f0cbdeea5377ff7a8c77fc7e3Timo Sirainen case 's':
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen ctx->ctx.subscriptions = TRUE;
5af8ea0a24c5930a8e310ebc4f33fba1d084217cTimo Sirainen break;
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen default:
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return FALSE;
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen }
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen return TRUE;
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen}
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainencmd_mailbox_list_run(struct doveadm_mail_cmd_context *_ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_user *user)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen{
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen enum mailbox_list_iter_flags iter_flags =
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen struct doveadm_mailbox_list_iter *iter;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen const struct mailbox_info *info;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen string_t *str = t_str_new(256);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (ctx->ctx.subscriptions)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen iter_flags |= MAILBOX_LIST_ITER_SELECT_SUBSCRIBED;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen iter = doveadm_mailbox_list_iter_full_init(_ctx, user, ctx->search_args,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen iter_flags);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) {
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen if (!ctx->mutf7)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen doveadm_print(info->vname);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen else {
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen str_truncate(str, 0);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (imap_utf8_to_utf7(info->vname, str) < 0)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen i_unreached();
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen doveadm_print(str_c(str));
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return -1;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return 0;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mail_search_args *
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainendoveadm_mail_mailbox_search_args_build(const char *const args[])
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen{
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct mail_search_args *search_args;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct mail_search_arg *arg;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen enum mail_search_arg_type type;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen unsigned int i;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen doveadm_mailbox_args_check(args);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen search_args = mail_search_build_init();
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; args[i] != NULL; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strchr(args[i], '*') != NULL ||
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen strchr(args[i], '%') != NULL)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen type = SEARCH_MAILBOX_GLOB;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen else
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen type = SEARCH_MAILBOX;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen arg = mail_search_build_add(search_args, type);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen arg->value.str = p_strdup(search_args->pool, args[i]);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen }
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen if (i > 1) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_search_arg *subargs = search_args->args;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen search_args->args = NULL;
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen arg = mail_search_build_add(search_args, SEARCH_OR);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen arg->value.subargs = subargs;
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return search_args;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainenstatic void cmd_mailbox_list_init(struct doveadm_mail_cmd_context *_ctx,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen const char *const args[])
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen doveadm_print_header("mailbox", "mailbox",
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->search_args = doveadm_mail_mailbox_search_args_build(args);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void cmd_mailbox_list_deinit(struct doveadm_mail_cmd_context *_ctx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->search_args != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_search_args_unref(&ctx->search_args);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_mailbox_list_alloc(void)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct list_cmd_context *ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx = doveadm_mailbox_cmd_alloc(struct list_cmd_context);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->ctx.ctx.v.init = cmd_mailbox_list_init;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->ctx.ctx.v.deinit = cmd_mailbox_list_deinit;
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen ctx->ctx.ctx.v.run = cmd_mailbox_list_run;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen ctx->ctx.ctx.v.parse_arg = cmd_mailbox_list_parse_arg;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ctx->ctx.ctx.getopt_args = "78s";
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen return &ctx->ctx.ctx;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen}
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainenstatic int
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainencmd_mailbox_create_run(struct doveadm_mail_cmd_context *_ctx,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen struct mail_user *user)
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen{
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen struct create_cmd_context *ctx = (struct create_cmd_context *)_ctx;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen struct mail_namespace *ns;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen struct mailbox *box;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen const char *const *namep;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen int ret = 0;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen array_foreach(&ctx->mailboxes, namep) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen const char *name = *namep;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen unsigned int len;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen bool directory = FALSE;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen ns = mail_namespace_find(user->namespaces, name);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen len = strlen(name);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (len > 0 && name[len-1] == mail_namespace_get_sep(ns)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen name = t_strndup(name, len-1);
adea1e1e46ccb4ae107767fd930e3d1fb4f1d11dTimo Sirainen directory = TRUE;
adea1e1e46ccb4ae107767fd930e3d1fb4f1d11dTimo Sirainen }
adea1e1e46ccb4ae107767fd930e3d1fb4f1d11dTimo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen box = mailbox_alloc(ns->list, name, 0);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (mailbox_create(box, &ctx->update, directory) < 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("Can't create mailbox %s: %s", name,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mailbox_get_last_error(box, NULL));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen doveadm_mail_failed_mailbox(_ctx, box);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen ret = -1;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (ctx->ctx.subscriptions) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (mailbox_set_subscribed(box, TRUE) < 0) {
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen i_error("Can't subscribe to mailbox %s: %s", name,
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen mailbox_get_last_error(box, NULL));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen doveadm_mail_failed_mailbox(_ctx, box);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ret = -1;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mailbox_free(&box);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen return ret;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic void cmd_mailbox_create_init(struct doveadm_mail_cmd_context *_ctx,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen const char *const args[])
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen{
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen struct mailbox_cmd_context *ctx = (struct mailbox_cmd_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *name;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen unsigned int i;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen if (args[0] == NULL)
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen doveadm_mail_help_name("mailbox create");
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen doveadm_mailbox_args_check(args);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
74674a53a72dab535c61f455b2246ef2797844eaTimo Sirainen for (i = 0; args[i] != NULL; i++) {
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen name = p_strdup(ctx->ctx.ctx.pool, args[i]);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen array_append(&ctx->mailboxes, &name, 1);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
f3d506e525a720f214020ca0f989a1966b30edaeTimo Sirainenstatic bool
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainencmd_mailbox_create_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct create_cmd_context *ctx = (struct create_cmd_context *)_ctx;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen switch (c) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen case 'g':
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (guid_128_from_string(optarg, ctx->update.mailbox_guid) < 0)
f8a86fdfb0048f9c87bf223373b35416ceb5856bTimo Sirainen doveadm_mail_help_name("mailbox create");
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen break;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen case 's':
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen ctx->ctx.subscriptions = TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen default:
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return TRUE;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen}
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic struct doveadm_mail_cmd_context *cmd_mailbox_create_alloc(void)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct create_cmd_context *ctx;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen ctx = doveadm_mailbox_cmd_alloc(struct create_cmd_context);
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen ctx->ctx.ctx.v.init = cmd_mailbox_create_init;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->ctx.ctx.v.run = cmd_mailbox_create_run;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->ctx.ctx.v.parse_arg = cmd_mailbox_create_parse_arg;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->ctx.ctx.getopt_args = "g:s";
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen p_array_init(&ctx->mailboxes, ctx->ctx.ctx.pool, 16);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return &ctx->ctx.ctx;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int i_strcmp_reverse_p(const char *const *s1, const char *const *s2)
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen{
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen return -strcmp(*s1, *s2);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic 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_append(mailboxes, &child_name, 1);
}
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 *const *namep;
ARRAY_TYPE(const_string) recursive_mailboxes;
const ARRAY_TYPE(const_string) *mailboxes = &ctx->mailboxes;
int ret = 0;
if (ctx->recursive) {
t_array_init(&recursive_mailboxes, 32);
array_foreach(&ctx->mailboxes, namep) {
if (get_child_mailboxes(user, &recursive_mailboxes,
*namep) < 0) {
doveadm_mail_failed_error(_ctx, MAIL_ERROR_TEMP);
ret = -1;
}
if ((*namep)[0] != '\0')
array_append(&recursive_mailboxes, namep, 1);
}
array_sort(&recursive_mailboxes, i_strcmp_reverse_p);
mailboxes = &recursive_mailboxes;
}
array_foreach(mailboxes, namep) {
const char *name = *namep;
ns = mail_namespace_find(user->namespaces, name);
box = mailbox_alloc(ns->list, name, 0);
storage = mailbox_get_storage(box);
if (mailbox_delete(box) < 0) {
i_error("Can't delete mailbox %s: %s", name,
mailbox_get_last_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_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_append(&ctx->mailboxes, &name, 1);
}
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;
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 = "rs";
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_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_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_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 *const *namep;
int ret = 0;
array_foreach(&ctx->mailboxes, namep) {
const char *name = *namep;
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_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_append(&ctx->mailboxes, &name, 1);
}
}
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);
}
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"[-s] <mailbox> [...]",
DOVEADM_CMD_PARAMS_START
DOVEADM_CMD_MAIL_COMMON
DOVEADM_CMD_PARAM('s', "subscriptions", 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
};