bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen#include "lib.h"
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen#include "array.h"
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen#include "virtual-transaction.h"
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen#include "virtual-storage.h"
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenstruct virtual_save_context {
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct mail_save_context ctx;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct mail_save_context *backend_save_ctx;
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen struct mailbox *backend_box;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen char *open_errstr;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen enum mail_error open_error;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen};
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenstruct mail_save_context *
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenvirtual_save_alloc(struct mailbox_transaction_context *_t)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen{
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct virtual_transaction_context *t =
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen (struct virtual_transaction_context *)_t;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)_t->box;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct mailbox_transaction_context *backend_trans;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct virtual_save_context *ctx;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen const char *errstr;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
395682d473b161c86165e7b9323ce4e45afb94bdTimo Sirainen if (_t->save_ctx == NULL) {
395682d473b161c86165e7b9323ce4e45afb94bdTimo Sirainen ctx = i_new(struct virtual_save_context, 1);
072f06b60d69fe9456c3fffe20e72a7d09f2825dTimo Sirainen ctx->ctx.transaction = &t->t;
395682d473b161c86165e7b9323ce4e45afb94bdTimo Sirainen _t->save_ctx = &ctx->ctx;
395682d473b161c86165e7b9323ce4e45afb94bdTimo Sirainen } else {
395682d473b161c86165e7b9323ce4e45afb94bdTimo Sirainen ctx = (struct virtual_save_context *)_t->save_ctx;
395682d473b161c86165e7b9323ce4e45afb94bdTimo Sirainen }
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen if (mbox->save_bbox != NULL) {
395682d473b161c86165e7b9323ce4e45afb94bdTimo Sirainen i_assert(ctx->backend_save_ctx == NULL);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen i_assert(ctx->open_errstr == NULL);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
d979c1179d55ad86e40f869e48ef3e4db9c817b5Timo Sirainen if (!mbox->save_bbox->box->opened &&
d979c1179d55ad86e40f869e48ef3e4db9c817b5Timo Sirainen virtual_backend_box_open(mbox, mbox->save_bbox) < 0) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen errstr = mailbox_get_last_error(mbox->save_bbox->box,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen &ctx->open_error);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen ctx->open_errstr = i_strdup(errstr);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen } else {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen backend_trans =
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen virtual_transaction_get(_t, mbox->save_bbox->box);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen ctx->backend_save_ctx = mailbox_save_alloc(backend_trans);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
0eef579fa2714c8b6b6bc2e54c545d291e657f8fTimo Sirainen virtual_backend_box_accessed(mbox, mbox->save_bbox);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return _t->save_ctx;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen}
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainenstatic struct mail_keywords *
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainenvirtual_copy_keywords(struct mailbox *src_box,
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen const struct mail_keywords *src_keywords,
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen struct mailbox *dest_box)
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen{
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen struct mailbox_status status;
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen ARRAY_TYPE(keywords) kw_strings;
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen const char *const *kwp;
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen unsigned int i;
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen if (src_keywords == NULL || src_keywords->count == 0)
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen return NULL;
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen t_array_init(&kw_strings, src_keywords->count + 1);
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen for (i = 0; i < src_keywords->count; i++) {
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen kwp = array_idx(status.keywords, src_keywords->idx[i]);
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen array_append(&kw_strings, kwp, 1);
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen }
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen array_append_zero(&kw_strings);
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen return mailbox_keywords_create_valid(dest_box,
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen array_idx(&kw_strings, 0));
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen}
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenint virtual_save_begin(struct mail_save_context *_ctx, struct istream *input)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen{
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_data *mdata = &_ctx->data;
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi struct mail_keywords *keywords;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen if (ctx->backend_save_ctx == NULL) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (ctx->open_errstr != NULL) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen /* mailbox_open() failed */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen ctx->open_error, ctx->open_errstr);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen } else {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen MAIL_ERROR_NOTPOSSIBLE,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen "Can't save messages to this virtual mailbox");
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen return -1;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen }
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
363929157786b549c80630bda3c3575f5115c6c5Timo Sirainen ctx->backend_box = ctx->backend_save_ctx->transaction->box;
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi keywords = virtual_copy_keywords(_ctx->transaction->box, mdata->keywords,
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi ctx->backend_box);
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen mailbox_save_set_flags(ctx->backend_save_ctx,
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen mdata->flags | mdata->pvt_flags,
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi keywords);
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi if (keywords != NULL)
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi mail_index_keywords_unref(&keywords);
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen mailbox_save_set_received_date(ctx->backend_save_ctx,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mdata->received_date,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mdata->received_tz_offset);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen mailbox_save_set_from_envelope(ctx->backend_save_ctx,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mdata->from_envelope);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mailbox_save_set_guid(ctx->backend_save_ctx, mdata->guid);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mailbox_save_set_min_modseq(ctx->backend_save_ctx, mdata->min_modseq);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
8eba883232f80178b60fa416f73292bf5f990fecTimo Sirainen virtual_mail_set_unattached_backend_mail(_ctx->dest_mail,
8eba883232f80178b60fa416f73292bf5f990fecTimo Sirainen ctx->backend_save_ctx->dest_mail);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen return mailbox_save_begin(&ctx->backend_save_ctx, input);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen}
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenint virtual_save_continue(struct mail_save_context *_ctx)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen{
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen return mailbox_save_continue(ctx->backend_save_ctx);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen}
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenint virtual_save_finish(struct mail_save_context *_ctx)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen{
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi int ret;
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi ret = mailbox_save_finish(&ctx->backend_save_ctx);
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi index_save_context_free(_ctx);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65Aki Tuomi return ret;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen}
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenvoid virtual_save_cancel(struct mail_save_context *_ctx)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen{
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen if (ctx->backend_save_ctx != NULL)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen mailbox_save_cancel(&ctx->backend_save_ctx);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen i_free_and_null(ctx->open_errstr);
44320b37d20bb75e0d433423318db2f4e29d5b91Timo Sirainen _ctx->unfinished = FALSE;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen}
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenvoid virtual_save_free(struct mail_save_context *_ctx)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen{
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen virtual_save_cancel(_ctx);
c5f46e7c1c135f89627c6f1676d6e33b35ecb80aAki Tuomi mailbox_save_context_deinit(_ctx);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen i_free(ctx);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen}