virtual-save.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
dfa2201c6ac8ddb2d2798dee15662cfe774e644eMartti Rannanjärvi#include "virtual-transaction.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "virtual-storage.h"
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainenstruct virtual_save_context {
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen struct mail_save_context ctx;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen struct mail_save_context *backend_save_ctx;
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen struct mailbox *backend_box;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen char *open_errstr;
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen enum mail_error open_error;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen};
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainenstruct mail_save_context *
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenvirtual_save_alloc(struct mailbox_transaction_context *_t)
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen{
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen struct virtual_transaction_context *t =
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen (struct virtual_transaction_context *)_t;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)_t->box;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen struct mailbox_transaction_context *backend_trans;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct virtual_save_context *ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *errstr;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (_t->save_ctx == NULL) {
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen ctx = i_new(struct virtual_save_context, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ctx->ctx.transaction = &t->t;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen _t->save_ctx = &ctx->ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen ctx = (struct virtual_save_context *)_t->save_ctx;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen }
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen if (mbox->save_bbox != NULL) {
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen i_assert(ctx->backend_save_ctx == NULL);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen i_assert(ctx->open_errstr == NULL);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen if (!mbox->save_bbox->box->opened &&
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen virtual_backend_box_open(mbox, mbox->save_bbox) < 0) {
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen errstr = mailbox_get_last_error(mbox->save_bbox->box,
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen &ctx->open_error);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen ctx->open_errstr = i_strdup(errstr);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen backend_trans =
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen virtual_transaction_get(_t, mbox->save_bbox->box);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen ctx->backend_save_ctx = mailbox_save_alloc(backend_trans);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen virtual_backend_box_accessed(mbox, mbox->save_bbox);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return _t->save_ctx;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic struct mail_keywords *
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvirtual_copy_keywords(struct mailbox *src_box,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mail_keywords *src_keywords,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox *dest_box)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_status status;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ARRAY_TYPE(keywords) kw_strings;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *const *kwp;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (src_keywords == NULL || src_keywords->count == 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen t_array_init(&kw_strings, src_keywords->count + 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < src_keywords->count; i++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen kwp = array_idx(status.keywords, src_keywords->idx[i]);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_append(&kw_strings, kwp, 1);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen array_append_zero(&kw_strings);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return mailbox_keywords_create_valid(dest_box,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen array_idx(&kw_strings, 0));
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint virtual_save_begin(struct mail_save_context *_ctx, struct istream *input)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_save_data *mdata = &_ctx->data;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_keywords *keywords;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ctx->backend_save_ctx == NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ctx->open_errstr != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* mailbox_open() failed */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ctx->open_error, ctx->open_errstr);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MAIL_ERROR_NOTPOSSIBLE,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "Can't save messages to this virtual mailbox");
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return -1;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ctx->backend_box = ctx->backend_save_ctx->transaction->box;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen keywords = virtual_copy_keywords(_ctx->transaction->box, mdata->keywords,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ctx->backend_box);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mailbox_save_set_flags(ctx->backend_save_ctx,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mdata->flags | mdata->pvt_flags,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen keywords);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (keywords != NULL)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mail_index_keywords_unref(&keywords);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_save_set_received_date(ctx->backend_save_ctx,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mdata->received_date,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen mdata->received_tz_offset);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen mailbox_save_set_from_envelope(ctx->backend_save_ctx,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mdata->from_envelope);
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek mailbox_save_set_guid(ctx->backend_save_ctx, mdata->guid);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_save_set_min_modseq(ctx->backend_save_ctx, mdata->min_modseq);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen virtual_mail_set_unattached_backend_mail(_ctx->dest_mail,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen ctx->backend_save_ctx->dest_mail);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return mailbox_save_begin(&ctx->backend_save_ctx, input);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint virtual_save_continue(struct mail_save_context *_ctx)
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return mailbox_save_continue(ctx->backend_save_ctx);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainenint virtual_save_finish(struct mail_save_context *_ctx)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen int ret;
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek ret = mailbox_save_finish(&ctx->backend_save_ctx);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen index_save_context_free(_ctx);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return ret;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen}
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenvoid virtual_save_cancel(struct mail_save_context *_ctx)
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen if (ctx->backend_save_ctx != NULL)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_save_cancel(&ctx->backend_save_ctx);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_free_and_null(ctx->open_errstr);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen _ctx->unfinished = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainenvoid virtual_save_free(struct mail_save_context *_ctx)
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen{
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen virtual_save_cancel(_ctx);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_save_context_deinit(_ctx);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_free(ctx);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen}
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen