]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
virtual: Added support for saving/copying messages to virtual mailboxes.
authorTimo Sirainen <tss@iki.fi>
Thu, 26 Feb 2009 23:30:02 +0000 (18:30 -0500)
committerTimo Sirainen <tss@iki.fi>
Thu, 26 Feb 2009 23:30:02 +0000 (18:30 -0500)
--HG--
branch : HEAD

src/plugins/virtual/Makefile.am
src/plugins/virtual/virtual-config.c
src/plugins/virtual/virtual-mail.c
src/plugins/virtual/virtual-save.c [new file with mode: 0644]
src/plugins/virtual/virtual-storage.c
src/plugins/virtual/virtual-storage.h
src/plugins/virtual/virtual-transaction.c
src/plugins/virtual/virtual-transaction.h [new file with mode: 0644]

index 6f248c5a466ac29ef1178e67d6c60fb8a32cf185..94d58b3b219f4ce319523e82f1e0190e82e9977b 100644 (file)
@@ -17,12 +17,14 @@ lib20_virtual_plugin_la_SOURCES = \
        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 \
index 396a94cb9cc7e93751551c322549451b1c1daaf1..050a1da360d3d7c7eaf5c06c81a33920b48b3ddd 100644 (file)
@@ -125,6 +125,14 @@ virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
                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;
index 3e27eb4e5c69533651cebc64812984fa3174dbb1..191191903ead9b698ad25ec3d3dec9c42ed6cbb4 100644 (file)
@@ -4,6 +4,7 @@
 #include "array.h"
 #include "index-mail.h"
 #include "virtual-storage.h"
+#include "virtual-transaction.h"
 
 struct virtual_mail {
        struct index_mail imail;
@@ -75,13 +76,32 @@ backend_mail_find(struct virtual_mail *vmail, struct mailbox *box)
        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;
@@ -92,20 +112,8 @@ static void virtual_mail_set_seq(struct mail *mail, uint32_t seq)
 
        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));
diff --git a/src/plugins/virtual/virtual-save.c b/src/plugins/virtual/virtual-save.c
new file mode 100644 (file)
index 0000000..07c7878
--- /dev/null
@@ -0,0 +1,93 @@
+/* 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);
+}
index c0f75df7c0fcd2d09d07632244f6868525b47d7c..bb0aa65a4222326e591b7b7ec761e21e0e68df59 100644 (file)
@@ -10,6 +10,7 @@
 #include "mail-copy.h"
 #include "mail-search.h"
 #include "virtual-plugin.h"
+#include "virtual-transaction.h"
 #include "virtual-storage.h"
 
 #include <stdio.h>
@@ -668,11 +669,11 @@ struct mailbox virtual_mailbox = {
                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
        }
index 3f12460a89f58e6076b2f8ffa0f67311cb2aa157..09a13a551c175ffe2b1b354721c4369f906dab1d 100644 (file)
@@ -13,6 +13,8 @@
 #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;
@@ -108,6 +110,8 @@ struct virtual_mailbox {
 
        /* 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;
@@ -129,9 +133,6 @@ struct virtual_backend_box *
 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,
@@ -146,10 +147,21 @@ struct mail *
 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);
 
index 2f59b64d5b1e6a53c24f160f46993aa487f65e0f..68519e2ba5986803d92b3b862be45e02b9cc2f3d 100644 (file)
@@ -3,14 +3,7 @@
 #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;
@@ -44,6 +37,9 @@ static int virtual_transaction_commit(struct mail_index_transaction *t,
        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)
@@ -63,6 +59,9 @@ static void virtual_transaction_rollback(struct mail_index_transaction *t)
        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]);
diff --git a/src/plugins/virtual/virtual-transaction.h b/src/plugins/virtual/virtual-transaction.h
new file mode 100644 (file)
index 0000000..d2ca72c
--- /dev/null
@@ -0,0 +1,23 @@
+#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