virtual-save.c revision c9c4494be2e6e8664ed2a37f74c2989c9b0ffe65
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen#include "lib.h"
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen#include "array.h"
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen#include "virtual-transaction.h"
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen#include "virtual-storage.h"
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainenstruct virtual_save_context {
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen struct mail_save_context ctx;
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen struct mail_save_context *backend_save_ctx;
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen struct mailbox *backend_box;
86bdb644d147a73df85abce4325254d694217a5fTimo Sirainen char *open_errstr;
86bdb644d147a73df85abce4325254d694217a5fTimo Sirainen enum mail_error open_error;
86bdb644d147a73df85abce4325254d694217a5fTimo Sirainen};
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainenstruct mail_save_context *
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainenvirtual_save_alloc(struct mailbox_transaction_context *_t)
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen{
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen struct virtual_transaction_context *t =
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen (struct virtual_transaction_context *)_t;
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)_t->box;
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen struct mailbox_transaction_context *backend_trans;
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen struct virtual_save_context *ctx;
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen const char *errstr;
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen if (_t->save_ctx == NULL) {
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen ctx = i_new(struct virtual_save_context, 1);
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen ctx->ctx.transaction = &t->t;
86bdb644d147a73df85abce4325254d694217a5fTimo Sirainen _t->save_ctx = &ctx->ctx;
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen } else {
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen ctx = (struct virtual_save_context *)_t->save_ctx;
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen }
f6ae9ae80a1fcf6c8f45ab759f0074caaa66c9c8Timo Sirainen
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen if (mbox->save_bbox != NULL) {
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainen i_assert(ctx->backend_save_ctx == NULL);
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen i_assert(ctx->open_errstr == NULL);
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen if (!mbox->save_bbox->box->opened &&
ae9691f7ef36d5272d72c90fa51393dfea5dd126Timo Sirainen virtual_backend_box_open(mbox, mbox->save_bbox) < 0) {
2eccb2637d0153bb7f9ad39a70f254cece74342cTimo Sirainen errstr = mailbox_get_last_error(mbox->save_bbox->box,
2eccb2637d0153bb7f9ad39a70f254cece74342cTimo Sirainen &ctx->open_error);
2eccb2637d0153bb7f9ad39a70f254cece74342cTimo Sirainen ctx->open_errstr = i_strdup(errstr);
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen } else {
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen backend_trans =
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen virtual_transaction_get(_t, mbox->save_bbox->box);
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen ctx->backend_save_ctx = mailbox_save_alloc(backend_trans);
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen }
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen virtual_backend_box_accessed(mbox, mbox->save_bbox);
10972f2a15f5538860fcc1d4adda227d59d2d757Timo Sirainen }
4ca2ccd50ad25260865f561e4ebf36899d7fe966Timo Sirainen return _t->save_ctx;
bb869cc24b24a8df84a43154c628785d6aee784cTimo Sirainen}
bb869cc24b24a8df84a43154c628785d6aee784cTimo Sirainen
4ca2ccd50ad25260865f561e4ebf36899d7fe966Timo Sirainenstatic struct mail_keywords *
e0ba54c7f985fc403b41c6e36d6a7f44908b23f0Timo Sirainenvirtual_copy_keywords(struct mailbox *src_box,
const struct mail_keywords *src_keywords,
struct mailbox *dest_box)
{
struct mailbox_status status;
ARRAY_TYPE(keywords) kw_strings;
const char *const *kwp;
unsigned int i;
if (src_keywords == NULL || src_keywords->count == 0)
return NULL;
t_array_init(&kw_strings, src_keywords->count + 1);
mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
for (i = 0; i < src_keywords->count; i++) {
kwp = array_idx(status.keywords, src_keywords->idx[i]);
array_append(&kw_strings, kwp, 1);
}
array_append_zero(&kw_strings);
return mailbox_keywords_create_valid(dest_box,
array_idx(&kw_strings, 0));
}
int virtual_save_begin(struct mail_save_context *_ctx, struct istream *input)
{
struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
struct mail_save_data *mdata = &_ctx->data;
struct mail_keywords *keywords;
if (ctx->backend_save_ctx == NULL) {
if (ctx->open_errstr != NULL) {
/* mailbox_open() failed */
mail_storage_set_error(_ctx->transaction->box->storage,
ctx->open_error, ctx->open_errstr);
} else {
mail_storage_set_error(_ctx->transaction->box->storage,
MAIL_ERROR_NOTPOSSIBLE,
"Can't save messages to this virtual mailbox");
}
return -1;
}
ctx->backend_box = ctx->backend_save_ctx->transaction->box;
keywords = virtual_copy_keywords(_ctx->transaction->box, mdata->keywords,
ctx->backend_box);
mailbox_save_set_flags(ctx->backend_save_ctx,
mdata->flags | mdata->pvt_flags,
keywords);
if (keywords != NULL)
mail_index_keywords_unref(&keywords);
mailbox_save_set_received_date(ctx->backend_save_ctx,
mdata->received_date,
mdata->received_tz_offset);
mailbox_save_set_from_envelope(ctx->backend_save_ctx,
mdata->from_envelope);
mailbox_save_set_guid(ctx->backend_save_ctx, mdata->guid);
mailbox_save_set_min_modseq(ctx->backend_save_ctx, mdata->min_modseq);
virtual_mail_set_unattached_backend_mail(_ctx->dest_mail,
ctx->backend_save_ctx->dest_mail);
return mailbox_save_begin(&ctx->backend_save_ctx, input);
}
int virtual_save_continue(struct mail_save_context *_ctx)
{
struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
return mailbox_save_continue(ctx->backend_save_ctx);
}
int virtual_save_finish(struct mail_save_context *_ctx)
{
struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
int ret;
ret = mailbox_save_finish(&ctx->backend_save_ctx);
index_save_context_free(_ctx);
return ret;
}
void virtual_save_cancel(struct mail_save_context *_ctx)
{
struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
if (ctx->backend_save_ctx != NULL)
mailbox_save_cancel(&ctx->backend_save_ctx);
i_free_and_null(ctx->open_errstr);
_ctx->unfinished = FALSE;
}
void virtual_save_free(struct mail_save_context *_ctx)
{
struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
virtual_save_cancel(_ctx);
mailbox_save_context_deinit(_ctx);
i_free(ctx);
}