virtual-save.c revision 0eef579fa2714c8b6b6bc2e54c545d291e657f8f
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2009-2015 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "array.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "virtual-transaction.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "virtual-storage.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenstruct virtual_save_context {
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen struct mail_save_context ctx;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen struct mail_save_context *backend_save_ctx;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen struct mailbox *backend_box;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen struct mail_keywords *backend_keywords;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen char *open_errstr;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen enum mail_error open_error;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen};
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct mail_save_context *
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvirtual_save_alloc(struct mailbox_transaction_context *_t)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct virtual_transaction_context *t =
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen (struct virtual_transaction_context *)_t;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)_t->box;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct mailbox_transaction_context *backend_trans;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct virtual_save_context *ctx;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const char *errstr;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (_t->save_ctx == NULL) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ctx = i_new(struct virtual_save_context, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->ctx.transaction = &t->t;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen _t->save_ctx = &ctx->ctx;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen } else {
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen ctx = (struct virtual_save_context *)_t->save_ctx;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen }
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (mbox->save_bbox != NULL) {
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen i_assert(ctx->backend_save_ctx == NULL);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen i_assert(ctx->open_errstr == NULL);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (!mbox->save_bbox->box->opened &&
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen virtual_backend_box_open(mbox, mbox->save_bbox) < 0) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen errstr = mailbox_get_last_error(mbox->save_bbox->box,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen &ctx->open_error);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen ctx->open_errstr = i_strdup(errstr);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen backend_trans =
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen virtual_transaction_get(_t, mbox->save_bbox->box);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->backend_save_ctx = mailbox_save_alloc(backend_trans);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen virtual_backend_box_accessed(mbox, mbox->save_bbox);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return _t->save_ctx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic struct mail_keywords *
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvirtual_copy_keywords(struct mailbox *src_box,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const struct mail_keywords *src_keywords,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mailbox *dest_box)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mailbox_status status;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ARRAY_TYPE(keywords) kw_strings;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const char *const *kwp;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int i;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (src_keywords == NULL || src_keywords->count == 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return NULL;
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen t_array_init(&kw_strings, src_keywords->count + 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen for (i = 0; i < src_keywords->count; i++) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen kwp = array_idx(status.keywords, src_keywords->idx[i]);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen array_append(&kw_strings, kwp, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen array_append_zero(&kw_strings);
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen return mailbox_keywords_create_valid(dest_box,
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen array_idx(&kw_strings, 0));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint virtual_save_begin(struct mail_save_context *_ctx, struct istream *input)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct virtual_mailbox *mbox =
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen (struct virtual_mailbox *)_ctx->transaction->box;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_save_data *mdata = &_ctx->data;
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen struct mail *mail;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ctx->backend_save_ctx == NULL) {
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (ctx->open_errstr != NULL) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* mailbox_open() failed */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen ctx->open_error, ctx->open_errstr);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen MAIL_ERROR_NOTPOSSIBLE,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Can't save messages to this virtual mailbox");
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
35df1dd606c5ef21068ab4fe4be305859d4fad4bTimo Sirainen }
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen ctx->backend_box = ctx->backend_save_ctx->transaction->box;
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen ctx->backend_keywords =
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen virtual_copy_keywords(_ctx->transaction->box, mdata->keywords,
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen ctx->backend_box);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mailbox_save_set_flags(ctx->backend_save_ctx,
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen mdata->flags | mdata->pvt_flags,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen ctx->backend_keywords);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mailbox_save_set_received_date(ctx->backend_save_ctx,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mdata->received_date,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mdata->received_tz_offset);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mailbox_save_set_from_envelope(ctx->backend_save_ctx,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen mdata->from_envelope);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mailbox_save_set_guid(ctx->backend_save_ctx, mdata->guid);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen mailbox_save_set_min_modseq(ctx->backend_save_ctx, mdata->min_modseq);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (_ctx->dest_mail != NULL) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mail = virtual_mail_set_backend_mail(_ctx->dest_mail,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mbox->save_bbox);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mailbox_save_set_dest_mail(ctx->backend_save_ctx, mail);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return mailbox_save_begin(&ctx->backend_save_ctx, input);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenint virtual_save_continue(struct mail_save_context *_ctx)
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen{
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen return mailbox_save_continue(ctx->backend_save_ctx);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenint virtual_save_finish(struct mail_save_context *_ctx)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (mailbox_save_finish(&ctx->backend_save_ctx) < 0)
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen return -1;
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen _ctx->unfinished = FALSE;
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen return 0;
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenvoid virtual_save_cancel(struct mail_save_context *_ctx)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen if (ctx->backend_save_ctx != NULL)
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen mailbox_save_cancel(&ctx->backend_save_ctx);
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen i_free_and_null(ctx->open_errstr);
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen _ctx->unfinished = FALSE;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenvoid virtual_save_free(struct mail_save_context *_ctx)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (ctx->backend_keywords != NULL)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen mailbox_keywords_unref(&ctx->backend_keywords);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen virtual_save_cancel(_ctx);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_free(ctx);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen