virtual-plugin.c \
virtual-search.c \
virtual-storage.c \
+ virtual-save.c \
virtual-sync.c \
virtual-transaction.c
noinst_HEADERS = \
virtual-plugin.h \
- virtual-storage.h
+ virtual-storage.h \
+ virtual-transaction.h
install-exec-local:
for d in imap pop3 lda; do \
name = bbox->name[0] == '-' ? bbox->name + 1 : bbox->name;
bbox->glob = imap_match_init(ctx->pool, name, TRUE, ctx->sep);
ctx->have_wildcards = TRUE;
+ } else if (bbox->name[0] == '!') {
+ /* save messages here */
+ if (ctx->mbox->save_bbox != NULL) {
+ *error_r = "Multiple save mailboxes defined";
+ return -1;
+ }
+ bbox->name++;
+ ctx->mbox->save_bbox = bbox;
}
array_append(&ctx->mbox->backend_boxes, &bbox, 1);
return 0;
#include "array.h"
#include "index-mail.h"
#include "virtual-storage.h"
+#include "virtual-transaction.h"
struct virtual_mail {
struct index_mail imail;
return NULL;
}
+struct mail *
+virtual_mail_set_backend_mail(struct mail *mail,
+ struct virtual_backend_box *bbox)
+{
+ struct virtual_mail *vmail = (struct virtual_mail *)mail;
+ struct mailbox_transaction_context *backend_trans;
+ struct mailbox_header_lookup_ctx *backend_headers;
+
+ backend_trans = virtual_transaction_get(mail->transaction, bbox->box);
+
+ backend_headers = vmail->wanted_headers == NULL ? NULL :
+ mailbox_header_lookup_init(bbox->box,
+ vmail->wanted_headers->headers);
+ vmail->backend_mail = mail_alloc(backend_trans, vmail->wanted_fields,
+ backend_headers);
+ if (backend_headers != NULL)
+ mailbox_header_lookup_unref(&backend_headers);
+ array_append(&vmail->backend_mails, &vmail->backend_mail, 1);
+ return vmail->backend_mail;
+}
+
static void virtual_mail_set_seq(struct mail *mail, uint32_t seq)
{
struct virtual_mail *vmail = (struct virtual_mail *)mail;
struct virtual_mailbox *mbox = (struct virtual_mailbox *)mail->box;
struct virtual_backend_box *bbox;
- struct mailbox_transaction_context *backend_trans;
- struct mailbox_header_lookup_ctx *backend_headers;
const struct virtual_mail_index_record *vrec;
const void *data;
bool expunged;
bbox = virtual_backend_box_lookup(mbox, vrec->mailbox_id);
vmail->backend_mail = backend_mail_find(vmail, bbox->box);
- if (vmail->backend_mail == NULL) {
- backend_trans =
- virtual_transaction_get(mail->transaction, bbox->box);
-
- backend_headers = vmail->wanted_headers == NULL ? NULL :
- mailbox_header_lookup_init(bbox->box,
- vmail->wanted_headers->headers);
- vmail->backend_mail = mail_alloc(backend_trans,
- vmail->wanted_fields,
- backend_headers);
- if (backend_headers != NULL)
- mailbox_header_lookup_unref(&backend_headers);
- array_append(&vmail->backend_mails, &vmail->backend_mail, 1);
- }
+ if (vmail->backend_mail == NULL)
+ virtual_mail_set_backend_mail(mail, bbox);
if (!mail_set_uid(vmail->backend_mail, vrec->real_uid))
i_unreached();
memset(&vmail->imail.data, 0, sizeof(vmail->imail.data));
--- /dev/null
+/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "virtual-transaction.h"
+#include "virtual-storage.h"
+
+struct virtual_save_context {
+ struct mail_save_context ctx;
+ struct mail_save_context *backend_save_ctx;
+};
+
+struct mail_save_context *
+virtual_save_alloc(struct mailbox_transaction_context *_t)
+{
+ struct virtual_transaction_context *t =
+ (struct virtual_transaction_context *)_t;
+ struct virtual_mailbox *mbox = (struct virtual_mailbox *)_t->box;
+ struct mailbox_transaction_context *backend_trans;
+ struct virtual_save_context *ctx;
+
+ if (t->save_ctx != NULL)
+ return &t->save_ctx->ctx;
+
+ ctx = t->save_ctx = i_new(struct virtual_save_context, 1);
+ ctx->ctx.transaction = &t->ictx.mailbox_ctx;
+
+ if (mbox->save_bbox != NULL) {
+ backend_trans =
+ virtual_transaction_get(_t, mbox->save_bbox->box);
+ ctx->backend_save_ctx = mailbox_save_alloc(backend_trans);
+ }
+ return &ctx->ctx;
+}
+
+int virtual_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+ struct virtual_save_context *ctx = (struct virtual_save_context *)_ctx;
+ struct virtual_mailbox *mbox =
+ (struct virtual_mailbox *)_ctx->transaction->box;
+ struct mail *mail;
+
+ if (ctx->backend_save_ctx == NULL) {
+ mail_storage_set_error(_ctx->transaction->box->storage,
+ MAIL_ERROR_NOTPOSSIBLE,
+ "Can't save messages to this virtual mailbox");
+ return -1;
+ }
+
+ mailbox_save_set_flags(ctx->backend_save_ctx, _ctx->flags,
+ _ctx->keywords);
+ mailbox_save_set_received_date(ctx->backend_save_ctx,
+ _ctx->received_date,
+ _ctx->received_tz_offset);
+ mailbox_save_set_from_envelope(ctx->backend_save_ctx,
+ _ctx->from_envelope);
+ mailbox_save_set_guid(ctx->backend_save_ctx, _ctx->guid);
+
+ if (_ctx->dest_mail != NULL) {
+ mail = virtual_mail_set_backend_mail(_ctx->dest_mail,
+ mbox->save_bbox);
+ mailbox_save_set_dest_mail(ctx->backend_save_ctx, 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;
+
+ return mailbox_save_finish(&ctx->backend_save_ctx);
+}
+
+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);
+}
+
+void virtual_save_free(struct virtual_save_context *ctx)
+{
+ if (ctx->backend_save_ctx != NULL)
+ mailbox_save_cancel(&ctx->backend_save_ctx);
+ i_free(ctx);
+}
#include "mail-copy.h"
#include "mail-search.h"
#include "virtual-plugin.h"
+#include "virtual-transaction.h"
#include "virtual-storage.h"
#include <stdio.h>
virtual_search_deinit,
virtual_search_next_nonblock,
virtual_search_next_update_seq,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ virtual_save_alloc,
+ virtual_save_begin,
+ virtual_save_continue,
+ virtual_save_finish,
+ virtual_save_cancel,
mail_storage_copy,
index_storage_is_inconsistent
}
#define VIRTUAL_CONTEXT(obj) \
MODULE_CONTEXT(obj, virtual_storage_module)
+struct virtual_save_context;
+
struct virtual_mail_index_header {
/* Increased by one each time the header is modified */
uint32_t change_counter;
/* Mailboxes this virtual mailbox consists of, sorted by mailbox_id */
ARRAY_TYPE(virtual_backend_box) backend_boxes;
+ /* backend mailbox where to save messages when saving to this mailbox */
+ struct virtual_backend_box *save_bbox;
ARRAY_TYPE(mailbox_virtual_patterns) list_include_patterns;
ARRAY_TYPE(mailbox_virtual_patterns) list_exclude_patterns;
virtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name);
struct virtual_backend_box *
virtual_backend_box_lookup(struct virtual_mailbox *mbox, uint32_t mailbox_id);
-struct mailbox_transaction_context *
-virtual_transaction_get(struct mailbox_transaction_context *trans,
- struct mailbox *backend_box);
struct mail_search_context *
virtual_search_init(struct mailbox_transaction_context *t,
virtual_mail_alloc(struct mailbox_transaction_context *t,
enum mail_fetch_field wanted_fields,
struct mailbox_header_lookup_ctx *wanted_headers);
+struct mail *
+virtual_mail_set_backend_mail(struct mail *mail,
+ struct virtual_backend_box *bbox);
struct mailbox_sync_context *
virtual_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);
+struct mail_save_context *
+virtual_save_alloc(struct mailbox_transaction_context *t);
+int virtual_save_begin(struct mail_save_context *ctx, struct istream *input);
+int virtual_save_continue(struct mail_save_context *ctx);
+int virtual_save_finish(struct mail_save_context *ctx);
+void virtual_save_cancel(struct mail_save_context *ctx);
+void virtual_save_free(struct virtual_save_context *ctx);
+
void virtual_copy_error(struct mail_storage *dest, struct mail_storage *src);
void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src);
#include "lib.h"
#include "array.h"
#include "virtual-storage.h"
-
-struct virtual_transaction_context {
- struct index_transaction_context ictx;
- union mail_index_transaction_module_context module_ctx;
-
- ARRAY_DEFINE(backend_transactions,
- struct mailbox_transaction_context *);
-};
+#include "virtual-transaction.h"
static void (*next_hook_mail_index_transaction_created)
(struct mail_index_transaction *t) = NULL;
unsigned int i, count;
int ret = 0;
+ if (dt->save_ctx != NULL)
+ virtual_save_free(dt->save_ctx);
+
bt = array_get_modifiable(&dt->backend_transactions, &count);
for (i = 0; i < count; i++) {
if (mailbox_transaction_commit(&bt[i]) < 0)
struct mailbox_transaction_context **bt;
unsigned int i, count;
+ if (dt->save_ctx != NULL)
+ virtual_save_free(dt->save_ctx);
+
bt = array_get_modifiable(&dt->backend_transactions, &count);
for (i = 0; i < count; i++)
mailbox_transaction_rollback(&bt[i]);
--- /dev/null
+#ifndef VIRTUAL_TRANSACTION_H
+#define VIRTUAL_TRANSACTION_H
+
+#include "index-storage.h"
+
+struct virtual_transaction_context {
+ struct index_transaction_context ictx;
+ union mail_index_transaction_module_context module_ctx;
+
+ struct virtual_save_context *save_ctx;
+
+ ARRAY_DEFINE(backend_transactions,
+ struct mailbox_transaction_context *);
+};
+
+struct mailbox_transaction_context *
+virtual_transaction_get(struct mailbox_transaction_context *trans,
+ struct mailbox *backend_box);
+
+void virtual_transaction_class_init(void);
+void virtual_transaction_class_deinit(void);
+
+#endif