virtual-save.c revision 18a41cbd38f83429b790414c1159c097af4a59b8
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2009-2014 Dovecot authors, see the included COPYING file */
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen#include "lib.h"
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen#include "array.h"
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen#include "virtual-transaction.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "virtual-storage.h"
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstruct virtual_save_context {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_save_context ctx;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_save_context *backend_save_ctx;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mailbox *backend_box;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_keywords *backend_keywords;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen char *open_errstr;
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainen enum mail_error open_error;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen};
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainenstruct mail_save_context *
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenvirtual_save_alloc(struct mailbox_transaction_context *_t)
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen{
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct virtual_transaction_context *t =
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen (struct virtual_transaction_context *)_t;
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)_t->box;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mailbox_transaction_context *backend_trans;
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainen struct virtual_save_context *ctx;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen const char *errstr;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (_t->save_ctx == NULL) {
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen ctx = i_new(struct virtual_save_context, 1);
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen ctx->ctx.transaction = &t->t;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen _t->save_ctx = &ctx->ctx;
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen } else {
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen ctx = (struct virtual_save_context *)_t->save_ctx;
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen }
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen if (mbox->save_bbox != NULL) {
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen i_assert(ctx->backend_save_ctx == NULL);
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen i_assert(ctx->open_errstr == NULL);
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen if (mailbox_open(mbox->save_bbox->box) < 0) {
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen errstr = mailbox_get_last_error(mbox->save_bbox->box,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen &ctx->open_error);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen ctx->open_errstr = i_strdup(errstr);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen } else {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen backend_trans =
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainen virtual_transaction_get(_t, mbox->save_bbox->box);
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen ctx->backend_save_ctx = mailbox_save_alloc(backend_trans);
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen }
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen }
4b8459c6c24b79d4ed5974ab6e3289a3f2b701c0Timo Sirainen return _t->save_ctx;
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen}
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstatic struct mail_keywords *
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainenvirtual_copy_keywords(struct mailbox *src_box,
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen const struct mail_keywords *src_keywords,
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen struct mailbox *dest_box)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen{
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct mailbox_status status;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen ARRAY_TYPE(keywords) kw_strings;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen const char *const *kwp;
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen unsigned int i;
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen if (src_keywords == NULL || src_keywords->count == 0)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen return NULL;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen t_array_init(&kw_strings, src_keywords->count + 1);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen for (i = 0; i < src_keywords->count; i++) {
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen kwp = array_idx(status.keywords, src_keywords->idx[i]);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen array_append(&kw_strings, kwp, 1);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen }
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen array_append_zero(&kw_strings);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen return mailbox_keywords_create_valid(dest_box,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen array_idx(&kw_strings, 0));
49b6e2d72cfaa5c244c798ddbae5b61489b0f728Timo Sirainen}
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
49b6e2d72cfaa5c244c798ddbae5b61489b0f728Timo Sirainenint virtual_save_begin(struct mail_save_context *_ctx, struct istream *input)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen{
49b6e2d72cfaa5c244c798ddbae5b61489b0f728Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen struct virtual_mailbox *mbox =
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen (struct virtual_mailbox *)_ctx->transaction->box;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_save_data *mdata = &_ctx->data;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail *mail;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (ctx->backend_save_ctx == NULL) {
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen if (ctx->open_errstr != NULL) {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* mailbox_open() failed */
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen ctx->open_error, ctx->open_errstr);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen } else {
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen mail_storage_set_error(_ctx->transaction->box->storage,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen MAIL_ERROR_NOTPOSSIBLE,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen "Can't save messages to this virtual mailbox");
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen }
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen return -1;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen ctx->backend_box = ctx->backend_save_ctx->transaction->box;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen ctx->backend_keywords =
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch virtual_copy_keywords(_ctx->transaction->box, mdata->keywords,
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen ctx->backend_box);
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mailbox_save_set_flags(ctx->backend_save_ctx,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mdata->flags | mdata->pvt_flags,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen ctx->backend_keywords);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen mailbox_save_set_received_date(ctx->backend_save_ctx,
debb28d107fa06d26fd194fdac523cfb32809199Timo Sirainen mdata->received_date,
7420207c4eae66bd7edc2bdebaee7d2cb0b6c341Timo Sirainen mdata->received_tz_offset);
4d4cd9cde9e01d4ad9354e6e30ac2f90d13042b2Timo Sirainen mailbox_save_set_from_envelope(ctx->backend_save_ctx,
4d4cd9cde9e01d4ad9354e6e30ac2f90d13042b2Timo Sirainen mdata->from_envelope);
4d4cd9cde9e01d4ad9354e6e30ac2f90d13042b2Timo Sirainen mailbox_save_set_guid(ctx->backend_save_ctx, mdata->guid);
debb28d107fa06d26fd194fdac523cfb32809199Timo Sirainen mailbox_save_set_min_modseq(ctx->backend_save_ctx, mdata->min_modseq);
debb28d107fa06d26fd194fdac523cfb32809199Timo Sirainen
debb28d107fa06d26fd194fdac523cfb32809199Timo Sirainen if (_ctx->dest_mail != NULL) {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mail = virtual_mail_set_backend_mail(_ctx->dest_mail,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mbox->save_bbox);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen mailbox_save_set_dest_mail(ctx->backend_save_ctx, mail);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen }
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen return mailbox_save_begin(&ctx->backend_save_ctx, input);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen}
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainenint virtual_save_continue(struct mail_save_context *_ctx)
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen{
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen return mailbox_save_continue(ctx->backend_save_ctx);
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen}
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainenint virtual_save_finish(struct mail_save_context *_ctx)
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen{
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (mailbox_save_finish(&ctx->backend_save_ctx) < 0)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen return -1;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen _ctx->unfinished = FALSE;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen return 0;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen}
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Boschvoid virtual_save_cancel(struct mail_save_context *_ctx)
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen{
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen if (ctx->backend_save_ctx != NULL)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mailbox_save_cancel(&ctx->backend_save_ctx);
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen i_free_and_null(ctx->open_errstr);
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainen _ctx->unfinished = FALSE;
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainen}
debb28d107fa06d26fd194fdac523cfb32809199Timo Sirainen
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainenvoid virtual_save_free(struct mail_save_context *_ctx)
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainen{
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainen struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainen
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen if (ctx->backend_keywords != NULL)
f05b9dd37f830576ca7d32ec7071bf87906df3d2Timo Sirainen mailbox_keywords_unref(&ctx->backend_keywords);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen virtual_save_cancel(_ctx);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_free(ctx);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen}
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen