virtual-save.c revision 18a41cbd38f83429b790414c1159c097af4a59b8
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2009-2014 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "array.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "virtual-transaction.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "virtual-storage.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct virtual_save_context {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_save_context ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_save_context *backend_save_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mailbox *backend_box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_keywords *backend_keywords;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen char *open_errstr;
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen enum mail_error open_error;
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen};
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct mail_save_context *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvirtual_save_alloc(struct mailbox_transaction_context *_t)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_transaction_context *t =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (struct virtual_transaction_context *)_t;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)_t->box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mailbox_transaction_context *backend_trans;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_save_context *ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *errstr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (_t->save_ctx == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx = i_new(struct virtual_save_context, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->ctx.transaction = &t->t;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _t->save_ctx = &ctx->ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx = (struct virtual_save_context *)_t->save_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (mbox->save_bbox != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(ctx->backend_save_ctx == NULL);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(ctx->open_errstr == NULL);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mailbox_open(mbox->save_bbox->box) < 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen errstr = mailbox_get_last_error(mbox->save_bbox->box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &ctx->open_error);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->open_errstr = i_strdup(errstr);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen backend_trans =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen virtual_transaction_get(_t, mbox->save_bbox->box);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->backend_save_ctx = mailbox_save_alloc(backend_trans);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return _t->save_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct mail_keywords *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvirtual_copy_keywords(struct mailbox *src_box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mail_keywords *src_keywords,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mailbox *dest_box)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mailbox_status status;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ARRAY_TYPE(keywords) kw_strings;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *const *kwp;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (src_keywords == NULL || src_keywords->count == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen t_array_init(&kw_strings, src_keywords->count + 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; i < src_keywords->count; i++) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen kwp = array_idx(status.keywords, src_keywords->idx[i]);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_append(&kw_strings, kwp, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_append_zero(&kw_strings);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return mailbox_keywords_create_valid(dest_box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_idx(&kw_strings, 0));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint virtual_save_begin(struct mail_save_context *_ctx, struct istream *input)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_mailbox *mbox =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (struct virtual_mailbox *)_ctx->transaction->box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_save_data *mdata = &_ctx->data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail *mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->backend_save_ctx == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->open_errstr != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* mailbox_open() failed */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ctx->open_error, ctx->open_errstr);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MAIL_ERROR_NOTPOSSIBLE,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "Can't save messages to this virtual mailbox");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->backend_box = ctx->backend_save_ctx->transaction->box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->backend_keywords =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen virtual_copy_keywords(_ctx->transaction->box, mdata->keywords,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->backend_box);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_save_set_flags(ctx->backend_save_ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdata->flags | mdata->pvt_flags,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->backend_keywords);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_save_set_received_date(ctx->backend_save_ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdata->received_date,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdata->received_tz_offset);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_save_set_from_envelope(ctx->backend_save_ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mdata->from_envelope);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_save_set_guid(ctx->backend_save_ctx, mdata->guid);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_save_set_min_modseq(ctx->backend_save_ctx, mdata->min_modseq);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (_ctx->dest_mail != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail = virtual_mail_set_backend_mail(_ctx->dest_mail,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mbox->save_bbox);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_save_set_dest_mail(ctx->backend_save_ctx, mail);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return mailbox_save_begin(&ctx->backend_save_ctx, input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint virtual_save_continue(struct mail_save_context *_ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return mailbox_save_continue(ctx->backend_save_ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint virtual_save_finish(struct mail_save_context *_ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mailbox_save_finish(&ctx->backend_save_ctx) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _ctx->unfinished = FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid virtual_save_cancel(struct mail_save_context *_ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->backend_save_ctx != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_save_cancel(&ctx->backend_save_ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_free_and_null(ctx->open_errstr);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _ctx->unfinished = FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid virtual_save_free(struct mail_save_context *_ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->backend_keywords != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mailbox_keywords_unref(&ctx->backend_keywords);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen virtual_save_cancel(_ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_free(ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen