]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mailbox_save_init() API was split to multiple functions.
authorTimo Sirainen <tss@iki.fi>
Thu, 7 Aug 2008 18:05:47 +0000 (14:05 -0400)
committerTimo Sirainen <tss@iki.fi>
Thu, 7 Aug 2008 18:05:47 +0000 (14:05 -0400)
This allows adding more parameters easily in future.

--HG--
branch : HEAD

21 files changed:
src/imap/cmd-append.c
src/lib-storage/index/cydir/cydir-save.c
src/lib-storage/index/cydir/cydir-storage.c
src/lib-storage/index/cydir/cydir-storage.h
src/lib-storage/index/dbox/dbox-save.c
src/lib-storage/index/dbox/dbox-storage.c
src/lib-storage/index/dbox/dbox-storage.h
src/lib-storage/index/maildir/maildir-save.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/maildir/maildir-storage.h
src/lib-storage/index/mbox/mbox-save.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/mbox/mbox-storage.h
src/lib-storage/index/raw/raw-storage.c
src/lib-storage/mail-copy.c
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/plugins/acl/acl-mailbox.c
src/plugins/quota/quota-storage.c
src/plugins/virtual/virtual-storage.c

index cd1bd0826cfd663c4ad7621ce6053ed1a3fee7fc..84ffbf2adaa3c794b98a60598bca3d8207ebebf9 100644 (file)
@@ -327,9 +327,11 @@ static bool cmd_append_continue_parsing(struct client_command_context *cmd)
 
        /* save the mail */
        ctx->input = i_stream_create_limit(client->input, ctx->msg_size);
-       ret = mailbox_save_init(ctx->t, flags, keywords,
-                               internal_date, timezone_offset, NULL,
-                               ctx->input, FALSE, &ctx->save_ctx);
+       ctx->save_ctx = mailbox_save_alloc(ctx->t);
+       mailbox_save_set_flags(ctx->save_ctx, flags, keywords);
+       mailbox_save_set_received_date(ctx->save_ctx,
+                                      internal_date, timezone_offset);
+       ret = mailbox_save_begin(&ctx->save_ctx, ctx->input);
 
        if (keywords != NULL)
                mailbox_keywords_free(ctx->box, &keywords);
index 67873d921f7ce77cb0d23889e1d25778e4072b0f..7deec9f25dd69bc03bc0197b9f02b1d50cdfe10f 100644 (file)
@@ -28,8 +28,7 @@ struct cydir_save_context {
        uint32_t seq;
        struct istream *input;
        struct ostream *output;
-       struct mail *mail, *cur_dest_mail;
-       time_t cur_received_date;
+       struct mail *mail;
        int fd;
 
        unsigned int failed:1;
@@ -57,29 +56,33 @@ cydir_get_save_path(struct cydir_save_context *ctx, unsigned int num)
        return t_strdup_printf("%s/%s.%u", dir, ctx->tmp_basename, num);
 }
 
-int cydir_save_init(struct mailbox_transaction_context *_t,
-                   enum mail_flags flags, struct mail_keywords *keywords,
-                   time_t received_date, int timezone_offset ATTR_UNUSED,
-                   const char *from_envelope ATTR_UNUSED,
-                   struct istream *input, struct mail **dest_mail,
-                   struct mail_save_context **ctx_r)
+struct mail_save_context *
+cydir_save_alloc(struct mailbox_transaction_context *_t)
 {
        struct cydir_transaction_context *t =
                (struct cydir_transaction_context *)_t;
        struct cydir_mailbox *mbox = (struct cydir_mailbox *)t->ictx.ibox;
        struct cydir_save_context *ctx = t->save_ctx;
-       enum mail_flags save_flags;
-       struct istream *crlf_input;
 
        i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
 
-       if (ctx == NULL) {
-               ctx = t->save_ctx = i_new(struct cydir_save_context, 1);
-               ctx->ctx.transaction = &t->ictx.mailbox_ctx;
-               ctx->mbox = mbox;
-               ctx->trans = t->ictx.trans;
-               ctx->tmp_basename = cydir_generate_tmp_filename();
-       }
+       if (t->save_ctx != NULL)
+               return &t->save_ctx->ctx;
+
+       ctx = t->save_ctx = i_new(struct cydir_save_context, 1);
+       ctx->ctx.transaction = &t->ictx.mailbox_ctx;
+       ctx->mbox = mbox;
+       ctx->trans = t->ictx.trans;
+       ctx->tmp_basename = cydir_generate_tmp_filename();
+       return &ctx->ctx;
+}
+
+int cydir_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+       struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
+       struct mailbox_transaction_context *trans = _ctx->transaction;
+       enum mail_flags save_flags;
+       struct istream *crlf_input;
 
        T_BEGIN {
                const char *path;
@@ -91,7 +94,7 @@ int cydir_save_init(struct mailbox_transaction_context *_t,
                                o_stream_create_fd_file(ctx->fd, 0, FALSE);
                        o_stream_cork(ctx->output);
                } else {
-                       mail_storage_set_critical(_t->box->storage,
+                       mail_storage_set_critical(trans->box->storage,
                                                  "open(%s) failed: %m", path);
                        ctx->failed = TRUE;
                }
@@ -100,30 +103,25 @@ int cydir_save_init(struct mailbox_transaction_context *_t,
                return -1;
 
        /* add to index */
-       save_flags = flags & ~MAIL_RECENT;
+       save_flags = _ctx->flags & ~MAIL_RECENT;
        mail_index_append(ctx->trans, 0, &ctx->seq);
        mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
                                save_flags);
-       if (keywords != NULL) {
+       if (_ctx->keywords != NULL) {
                mail_index_update_keywords(ctx->trans, ctx->seq,
-                                          MODIFY_REPLACE, keywords);
+                                          MODIFY_REPLACE, _ctx->keywords);
        }
 
-       if (*dest_mail == NULL) {
+       if (_ctx->dest_mail == NULL) {
                if (ctx->mail == NULL)
-                       ctx->mail = mail_alloc(_t, 0, NULL);
-               *dest_mail = ctx->mail;
+                       ctx->mail = mail_alloc(trans, 0, NULL);
+               _ctx->dest_mail = ctx->mail;
        }
-       mail_set_seq(*dest_mail, ctx->seq);
+       mail_set_seq(_ctx->dest_mail, ctx->seq);
 
        crlf_input = i_stream_create_crlf(input);
-       ctx->input = index_mail_cache_parse_init(*dest_mail, crlf_input);
+       ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
        i_stream_unref(&crlf_input);
-
-       ctx->cur_dest_mail = *dest_mail;
-       ctx->cur_received_date = received_date;
-
-       *ctx_r = &ctx->ctx;
        return ctx->failed ? -1 : 0;
 }
 
@@ -145,7 +143,7 @@ int cydir_save_continue(struct mail_save_context *_ctx)
                        ctx->failed = TRUE;
                        return -1;
                }
-               index_mail_cache_parse_continue(ctx->cur_dest_mail);
+               index_mail_cache_parse_continue(_ctx->dest_mail);
 
                /* both tee input readers may consume data from our primary
                   input stream. we'll have to make sure we don't return with
@@ -177,9 +175,9 @@ int cydir_save_finish(struct mail_save_context *_ctx)
                }
        }
 
-       if (ctx->cur_received_date == (time_t)-1) {
+       if (_ctx->received_date == (time_t)-1) {
                if (fstat(ctx->fd, &st) == 0)
-                       ctx->cur_received_date = st.st_mtime;
+                       _ctx->received_date = st.st_mtime;
                else {
                        mail_storage_set_critical(storage,
                                                  "fstat(%s) failed: %m", path);
@@ -189,7 +187,7 @@ int cydir_save_finish(struct mail_save_context *_ctx)
                struct utimbuf ut;
 
                ut.actime = ioloop_time;
-               ut.modtime = ctx->cur_received_date;
+               ut.modtime = _ctx->received_date;
                if (utime(path, &ut) < 0) {
                        mail_storage_set_critical(storage,
                                                  "utime(%s) failed: %m", path);
@@ -214,8 +212,8 @@ int cydir_save_finish(struct mail_save_context *_ctx)
                }
        }
 
-       index_mail_cache_parse_deinit(ctx->cur_dest_mail,
-                                     ctx->cur_received_date, !ctx->failed);
+       index_mail_cache_parse_deinit(_ctx->dest_mail,
+                                     _ctx->received_date, !ctx->failed);
        i_stream_unref(&ctx->input);
 
        return ctx->failed ? -1 : 0;
index c4ce9a4cfb42f9a947d9fd0887dfe3c419a33d74..15c36cec081d922156122db621c0556e8ac734b7 100644 (file)
@@ -453,7 +453,8 @@ struct mailbox cydir_mailbox = {
                index_storage_search_deinit,
                index_storage_search_next_nonblock,
                index_storage_search_next_update_seq,
-               cydir_save_init,
+               cydir_save_alloc,
+               cydir_save_begin,
                cydir_save_continue,
                cydir_save_finish,
                cydir_save_cancel,
index dad1039ae3d333964cec7096b30905c2f4d54e72..296f5cca0da439fafbb2568d7f6e084afbc1e182 100644 (file)
@@ -33,11 +33,9 @@ extern struct mail_vfuncs cydir_mail_vfuncs;
 void cydir_transaction_class_init(void);
 void cydir_transaction_class_deinit(void);
 
-int cydir_save_init(struct mailbox_transaction_context *_t,
-                   enum mail_flags flags, struct mail_keywords *keywords,
-                   time_t received_date, int timezone_offset,
-                   const char *from_envelope, struct istream *input,
-                   struct mail **dest_mail, struct mail_save_context **ctx_r);
+struct mail_save_context *
+cydir_save_alloc(struct mailbox_transaction_context *_t);
+int cydir_save_begin(struct mail_save_context *ctx, struct istream *input);
 int cydir_save_continue(struct mail_save_context *ctx);
 int cydir_save_finish(struct mail_save_context *ctx);
 void cydir_save_cancel(struct mail_save_context *ctx);
index 69dd41e8905fe86e4d1ba595e474755c61e837c9..b3e8c13b3ddbf9d8fe8ed09c2dcbb7d7a5ddd93e 100644 (file)
@@ -36,9 +36,7 @@ struct dbox_save_context {
        /* updated for each appended mail: */
        uint32_t seq;
        struct istream *input;
-       struct mail *mail, *cur_dest_mail;
-       time_t cur_received_date;
-       enum mail_flags cur_flags;
+       struct mail *mail;
        string_t *cur_keywords;
 
        struct dbox_file *cur_file;
@@ -61,17 +59,31 @@ static void dbox_save_keywords(struct dbox_save_context *ctx,
                                           keywords);
 }
 
-int dbox_save_init(struct mailbox_transaction_context *_t,
-                  enum mail_flags flags, struct mail_keywords *keywords,
-                  time_t received_date, int timezone_offset ATTR_UNUSED,
-                  const char *from_envelope ATTR_UNUSED,
-                  struct istream *input, struct mail **dest_mail,
-                  struct mail_save_context **ctx_r)
+struct mail_save_context *
+dbox_save_alloc(struct mailbox_transaction_context *_t)
 {
        struct dbox_transaction_context *t =
                (struct dbox_transaction_context *)_t;
        struct dbox_mailbox *mbox = (struct dbox_mailbox *)t->ictx.ibox;
-       struct dbox_save_context *ctx = t->save_ctx;
+       struct dbox_save_context *ctx;
+
+       i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
+
+       if (t->save_ctx != NULL)
+               return &t->save_ctx->ctx;
+
+       ctx = t->save_ctx = i_new(struct dbox_save_context, 1);
+       ctx->ctx.transaction = &t->ictx.mailbox_ctx;
+       ctx->mbox = mbox;
+       ctx->trans = t->ictx.trans;
+       ctx->append_ctx = dbox_index_append_begin(mbox->dbox_index);
+       i_array_init(&ctx->mails, 32);
+       return &ctx->ctx;
+}
+
+int dbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+       struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
        struct dbox_message_header dbox_msg_hdr;
        struct dbox_save_mail *save_mail;
        struct istream *crlf_input;
@@ -79,17 +91,6 @@ int dbox_save_init(struct mailbox_transaction_context *_t,
        const struct stat *st;
        uoff_t mail_size;
 
-       i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
-
-       if (ctx == NULL) {
-               ctx = t->save_ctx = i_new(struct dbox_save_context, 1);
-               ctx->ctx.transaction = &t->ictx.mailbox_ctx;
-               ctx->mbox = mbox;
-               ctx->trans = t->ictx.trans;
-               ctx->append_ctx = dbox_index_append_begin(mbox->dbox_index);
-               i_array_init(&ctx->mails, 32);
-       }
-
        /* get the size of the mail to be saved, if possible */
        st = i_stream_stat(input, TRUE);
        mail_size = st == NULL || st->st_size == -1 ? 0 : st->st_size;
@@ -101,26 +102,24 @@ int dbox_save_init(struct mailbox_transaction_context *_t,
        }
 
        /* add to index */
-       save_flags = flags & ~MAIL_RECENT;
+       save_flags = _ctx->flags & ~MAIL_RECENT;
        mail_index_append(ctx->trans, 0, &ctx->seq);
        mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
                                save_flags);
-       if (keywords != NULL) {
+       if (_ctx->keywords != NULL) {
                mail_index_update_keywords(ctx->trans, ctx->seq,
-                                          MODIFY_REPLACE, keywords);
+                                          MODIFY_REPLACE, _ctx->keywords);
        }
 
-       if (*dest_mail == NULL) {
+       if (_ctx->dest_mail == NULL) {
                if (ctx->mail == NULL)
-                       ctx->mail = mail_alloc(_t, 0, NULL);
-               *dest_mail = ctx->mail;
+                       ctx->mail = mail_alloc(_ctx->transaction, 0, NULL);
+               _ctx->dest_mail = ctx->mail;
        }
-       mail_set_seq(*dest_mail, ctx->seq);
-
-       ctx->cur_dest_mail = *dest_mail;
+       mail_set_seq(_ctx->dest_mail, ctx->seq);
 
        crlf_input = i_stream_create_lf(input);
-       ctx->input = index_mail_cache_parse_init(*dest_mail, crlf_input);
+       ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
        i_stream_unref(&crlf_input);
 
        save_mail = array_append_space(&ctx->mails);
@@ -134,18 +133,15 @@ int dbox_save_init(struct mailbox_transaction_context *_t,
        o_stream_cork(ctx->cur_output);
        if (o_stream_send(ctx->cur_output, &dbox_msg_hdr,
                          sizeof(dbox_msg_hdr)) < 0) {
-               mail_storage_set_critical(_t->box->storage,
+               mail_storage_set_critical(_ctx->transaction->box->storage,
                        "o_stream_send(%s) failed: %m", 
                        dbox_file_get_path(ctx->cur_file));
                ctx->failed = TRUE;
        }
 
-       ctx->cur_received_date = received_date != (time_t)-1 ?
-               received_date : ioloop_time;
-       ctx->cur_flags = flags;
-       dbox_save_keywords(ctx, keywords);
-
-       *ctx_r = &ctx->ctx;
+       if (_ctx->received_date == (time_t)-1)
+               _ctx->received_date = ioloop_time;
+       dbox_save_keywords(ctx, _ctx->keywords);
        return ctx->failed ? -1 : 0;
 }
 
@@ -169,7 +165,7 @@ int dbox_save_continue(struct mail_save_context *_ctx)
                        ctx->failed = TRUE;
                        return -1;
                }
-               index_mail_cache_parse_continue(ctx->cur_dest_mail);
+               index_mail_cache_parse_continue(_ctx->dest_mail);
 
                /* both tee input readers may consume data from our primary
                   input stream. we'll have to make sure we don't return with
@@ -193,17 +189,17 @@ static void dbox_save_write_metadata(struct dbox_save_context *ctx)
        str = t_str_new(256);
        /* write first fields that don't change */
        str_printfa(str, "%c%lx\n", DBOX_METADATA_RECEIVED_TIME,
-                   (unsigned long)ctx->cur_received_date);
+                   (unsigned long)ctx->ctx.received_date);
        str_printfa(str, "%c%lx\n", DBOX_METADATA_SAVE_TIME,
                    (unsigned long)ioloop_time);
-       if (mail_get_virtual_size(ctx->cur_dest_mail, &vsize) < 0)
+       if (mail_get_virtual_size(ctx->ctx.dest_mail, &vsize) < 0)
                i_unreached();
        str_printfa(str, "%c%llx\n", DBOX_METADATA_VIRTUAL_SIZE,
                    (unsigned long long)vsize);
 
        /* flags */
        str_append_c(str, DBOX_METADATA_FLAGS);
-       dbox_mail_metadata_flags_append(str, ctx->cur_flags);
+       dbox_mail_metadata_flags_append(str, ctx->ctx.flags);
        str_append_c(str, '\n');
 
        /* keywords */
@@ -254,8 +250,8 @@ int dbox_save_finish(struct mail_save_context *_ctx)
        if (ctx->cur_output == NULL)
                return -1;
 
-       index_mail_cache_parse_deinit(ctx->cur_dest_mail,
-                                     ctx->cur_received_date, !ctx->failed);
+       index_mail_cache_parse_deinit(_ctx->dest_mail,
+                                     _ctx->received_date, !ctx->failed);
 
        if (!ctx->failed) T_BEGIN {
                const char *cur_path;
index caff4772eae767a157c33fdae98c60b6657c0250..25dd5a4099f7d0195d13dad9b4dbabc4a903f1cf 100644 (file)
@@ -713,7 +713,8 @@ struct mailbox dbox_mailbox = {
                index_storage_search_deinit,
                index_storage_search_next_nonblock,
                index_storage_search_next_update_seq,
-               dbox_save_init,
+               dbox_save_alloc,
+               dbox_save_begin,
                dbox_save_continue,
                dbox_save_finish,
                dbox_save_cancel,
index 96889b1d913c7746bf68a91e6a10a6132c5eea35..838ff54e0dbecb2984e001370fbeb03e7d3c9247 100644 (file)
@@ -82,11 +82,9 @@ dbox_mail_alloc(struct mailbox_transaction_context *t,
                enum mail_fetch_field wanted_fields,
                struct mailbox_header_lookup_ctx *wanted_headers);
 
-int dbox_save_init(struct mailbox_transaction_context *_t,
-                  enum mail_flags flags, struct mail_keywords *keywords,
-                  time_t received_date, int timezone_offset,
-                  const char *from_envelope, struct istream *input,
-                  struct mail **dest_mail, struct mail_save_context **ctx_r);
+struct mail_save_context *
+dbox_save_alloc(struct mailbox_transaction_context *_t);
+int dbox_save_begin(struct mail_save_context *ctx, struct istream *input);
 int dbox_save_continue(struct mail_save_context *ctx);
 int dbox_save_finish(struct mail_save_context *ctx);
 void dbox_save_cancel(struct mail_save_context *ctx);
index 95a3c1bb611c387cc0993ea4726fa6774a16bcd2..8f18a0971cd83af947360f7ca049e2a5dfb17b2d 100644 (file)
@@ -54,7 +54,6 @@ struct maildir_save_context {
        struct istream *input;
        struct ostream *output;
        int fd;
-       time_t received_date;
        uint32_t first_seq, seq;
 
        unsigned int want_mails:1;
@@ -346,52 +345,51 @@ static int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
        return fd;
 }
 
-int maildir_save_init(struct mailbox_transaction_context *_t,
-                     enum mail_flags flags, struct mail_keywords *keywords,
-                     time_t received_date, int timezone_offset ATTR_UNUSED,
-                     const char *from_envelope ATTR_UNUSED,
-                     struct istream *input, struct mail **dest_mail,
-                     struct mail_save_context **ctx_r)
+struct mail_save_context *
+maildir_save_alloc(struct mailbox_transaction_context *_t)
 {
        struct maildir_transaction_context *t =
                (struct maildir_transaction_context *)_t;
-       struct maildir_save_context *ctx;
-       struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->ictx.ibox;
 
        i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
 
        if (t->save_ctx == NULL)
                t->save_ctx = maildir_save_transaction_init(t);
-       ctx = t->save_ctx;
+       return &t->save_ctx->ctx;
+}
+
+int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+       struct maildir_transaction_context *t =
+               (struct maildir_transaction_context *)_ctx->transaction;
+       struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
 
-       flags &= ~MAIL_RECENT;
-       if (mbox->ibox.keep_recent)
-               flags |= MAIL_RECENT;
+       _ctx->flags &= ~MAIL_RECENT;
+       if (ctx->mbox->ibox.keep_recent)
+               _ctx->flags |= MAIL_RECENT;
 
        T_BEGIN {
                /* create a new file in tmp/ directory */
                const char *fname;
 
-               ctx->fd = maildir_create_tmp(mbox, ctx->tmpdir, &fname);
+               ctx->fd = maildir_create_tmp(ctx->mbox, ctx->tmpdir, &fname);
                if (ctx->fd == -1)
                        ctx->failed = TRUE;
                else {
-                       ctx->received_date = received_date;
                        ctx->input = (ctx->mbox->storage->storage.flags &
                                      MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ?
                                i_stream_create_crlf(input) :
                                i_stream_create_lf(input);
 
-                       maildir_save_add(t, fname, flags, keywords, *dest_mail);
+                       maildir_save_add(t, fname, _ctx->flags, _ctx->keywords,
+                                        _ctx->dest_mail);
                }
        } T_END;
-       if (ctx->failed)
-               return -1;
 
-       ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE);
-       o_stream_cork(ctx->output);
-
-       *ctx_r = &ctx->ctx;
+       if (!ctx->failed) {
+               ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE);
+               o_stream_cork(ctx->output);
+       }
        return ctx->failed ? -1 : 0;
 }
 
@@ -446,10 +444,10 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx)
                ctx->failed = TRUE;
        }
 
-       if (ctx->received_date != (time_t)-1) {
+       if (ctx->ctx.received_date != (time_t)-1) {
                /* set the received_date by modifying mtime */
                buf.actime = ioloop_time;
-               buf.modtime = ctx->received_date;
+               buf.modtime = ctx->ctx.received_date;
 
                if (utime(path, &buf) < 0) {
                        ctx->failed = TRUE;
@@ -458,7 +456,7 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx)
                }
        } else if (ctx->fd != -1) {
                if (fstat(ctx->fd, &st) == 0)
-                       ctx->received_date = st.st_mtime;
+                       ctx->ctx.received_date = st.st_mtime;
                else {
                        ctx->failed = TRUE;
                        mail_storage_set_critical(storage,
@@ -467,7 +465,7 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx)
        } else {
                /* hardlinked */
                if (stat(path, &st) == 0)
-                       ctx->received_date = st.st_mtime;
+                       ctx->ctx.received_date = st.st_mtime;
                else {
                        ctx->failed = TRUE;
                        mail_storage_set_critical(storage,
@@ -477,7 +475,8 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx)
 
        if (ctx->cur_dest_mail != NULL) {
                index_mail_cache_parse_deinit(ctx->cur_dest_mail,
-                                             ctx->received_date, !ctx->failed);
+                                             ctx->ctx.received_date,
+                                             !ctx->failed);
        }
        i_stream_unref(&ctx->input);
 
index 74abe787987391090d992d59041520f6b9ecf3d7..8ce23f7148be385d15be9ce52c462df116911712 100644 (file)
@@ -1058,7 +1058,8 @@ struct mailbox maildir_mailbox = {
                index_storage_search_deinit,
                index_storage_search_next_nonblock,
                index_storage_search_next_update_seq,
-               maildir_save_init,
+               maildir_save_alloc,
+               maildir_save_begin,
                maildir_save_continue,
                maildir_save_finish,
                maildir_save_cancel,
index c66dd38926cd57f91be231bd69a2aa1e0ad61007..8be7ec5811101e97edf950c63293b0a569297434 100644 (file)
@@ -126,12 +126,9 @@ bool maildir_set_deleted(struct maildir_mailbox *mbox);
 void maildir_transaction_class_init(void);
 void maildir_transaction_class_deinit(void);
 
-int maildir_save_init(struct mailbox_transaction_context *_t,
-                     enum mail_flags flags, struct mail_keywords *keywords,
-                     time_t received_date, int timezone_offset,
-                     const char *from_envelope, struct istream *input,
-                     struct mail **dest_mail,
-                     struct mail_save_context **ctx_r);
+struct mail_save_context *
+maildir_save_alloc(struct mailbox_transaction_context *_t);
+int maildir_save_begin(struct mail_save_context *ctx, struct istream *input);
 int maildir_save_continue(struct mail_save_context *ctx);
 int maildir_save_finish(struct mail_save_context *ctx);
 void maildir_save_cancel(struct mail_save_context *ctx);
index a119e52dafe8d14792463938483bb7657a6963ed..758883defa855fb8306b6ff557da2aece67d4563 100644 (file)
@@ -40,7 +40,6 @@ struct mbox_save_context {
        struct mail *mail;
        uoff_t append_offset, mail_offset;
        time_t orig_atime;
-       time_t received_date;
 
        string_t *headers;
        size_t space_end_idx;
@@ -424,44 +423,50 @@ mbox_save_get_input_stream(struct mbox_save_context *ctx, struct istream *input)
        return ret;
 }
 
-int mbox_save_init(struct mailbox_transaction_context *_t,
-                  enum mail_flags flags, struct mail_keywords *keywords,
-                  time_t received_date, int timezone_offset ATTR_UNUSED,
-                  const char *from_envelope, struct istream *input,
-                  struct mail **dest_mail, struct mail_save_context **ctx_r)
+struct mail_save_context *
+mbox_save_alloc(struct mailbox_transaction_context *_t)
 {
        struct mbox_transaction_context *t =
                (struct mbox_transaction_context *)_t;
        struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->ictx.ibox;
-       struct mbox_save_context *ctx = t->save_ctx;
-       enum mail_flags save_flags;
-       uint64_t offset;
+       struct mbox_save_context *ctx;
 
        i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
 
+       if (t->save_ctx != NULL)
+               return &t->save_ctx->ctx;
+
+       ctx = t->save_ctx = i_new(struct mbox_save_context, 1);
+       ctx->ctx.transaction = &t->ictx.mailbox_ctx;
+       ctx->mbox = mbox;
+       ctx->trans = t->ictx.trans;
+       ctx->append_offset = (uoff_t)-1;
+       ctx->headers = str_new(default_pool, 512);
+       ctx->mail_offset = (uoff_t)-1;
+       return &ctx->ctx;
+}
+
+int mbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+       struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx;
+       struct mbox_transaction_context *t =
+               (struct mbox_transaction_context *)_ctx->transaction;
+       enum mail_flags save_flags;
+       uint64_t offset;
+
        /* FIXME: we could write timezone_offset to From-line.. */
-       if (received_date == (time_t)-1)
-               received_date = ioloop_time;
-
-       if (ctx == NULL) {
-               ctx = t->save_ctx = i_new(struct mbox_save_context, 1);
-               ctx->ctx.transaction = &t->ictx.mailbox_ctx;
-               ctx->mbox = mbox;
-               ctx->trans = t->ictx.trans;
-               ctx->append_offset = (uoff_t)-1;
-               ctx->headers = str_new(default_pool, 512);
-               ctx->mail_offset = (uoff_t)-1;
-       }
+       if (_ctx->received_date == (time_t)-1)
+               _ctx->received_date = ioloop_time;
 
        ctx->failed = FALSE;
        ctx->seq = 0;
 
-       if (mbox_save_init_file(ctx, t, *dest_mail != NULL) < 0) {
+       if (mbox_save_init_file(ctx, t, _ctx->dest_mail != NULL) < 0) {
                ctx->failed = TRUE;
                return -1;
        }
 
-       save_flags = (flags & ~MAIL_RECENT) | MAIL_RECENT;
+       save_flags = (_ctx->flags & ~MAIL_RECENT) | MAIL_RECENT;
        str_truncate(ctx->headers, 0);
        if (ctx->synced) {
                if (ctx->mbox->mbox_save_md5)
@@ -476,42 +481,42 @@ int mbox_save_init(struct mailbox_transaction_context *_t,
                mail_index_append(ctx->trans, ctx->next_uid, &ctx->seq);
                mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
                                        save_flags & ~MAIL_RECENT);
-               if (keywords != NULL) {
+               if (_ctx->keywords != NULL) {
                        mail_index_update_keywords(ctx->trans, ctx->seq,
-                                                  MODIFY_REPLACE, keywords);
+                                                  MODIFY_REPLACE,
+                                                  _ctx->keywords);
                }
 
                offset = ctx->output->offset == 0 ? 0 :
                        ctx->output->offset - 1;
                mail_index_update_ext(ctx->trans, ctx->seq,
-                                     mbox->mbox_ext_idx, &offset, NULL);
+                                     ctx->mbox->mbox_ext_idx, &offset, NULL);
                ctx->next_uid++;
 
                /* parse and cache the mail headers as we read it */
-               if (*dest_mail == NULL) {
-                       if (ctx->mail == NULL)
-                               ctx->mail = mail_alloc(_t, 0, NULL);
-                       *dest_mail = ctx->mail;
+               if (_ctx->dest_mail == NULL) {
+                       if (ctx->mail == NULL) {
+                               ctx->mail = mail_alloc(_ctx->transaction,
+                                                      0, NULL);
+                       }
+                       _ctx->dest_mail = ctx->mail;
                }
-               mail_set_seq(*dest_mail, ctx->seq);
+               mail_set_seq(_ctx->dest_mail, ctx->seq);
        }
        mbox_save_append_flag_headers(ctx->headers, save_flags);
-       mbox_save_append_keyword_headers(ctx, keywords);
+       mbox_save_append_keyword_headers(ctx, _ctx->keywords);
        str_append_c(ctx->headers, '\n');
 
-       i_assert(mbox->mbox_lock_type == F_WRLCK);
+       i_assert(ctx->mbox->mbox_lock_type == F_WRLCK);
 
        ctx->mail_offset = ctx->output->offset;
        ctx->eoh_offset = (uoff_t)-1;
        ctx->last_char = '\n';
-       ctx->received_date = received_date;
 
-       if (write_from_line(ctx, received_date, from_envelope) < 0)
+       if (write_from_line(ctx, _ctx->received_date, _ctx->from_envelope) < 0)
                ctx->failed = TRUE;
        else
                ctx->input = mbox_save_get_input_stream(ctx, input);
-
-       *ctx_r = &ctx->ctx;
        return ctx->failed ? -1 : 0;
 }
 
@@ -670,7 +675,7 @@ int mbox_save_finish(struct mail_save_context *_ctx)
        }
 
        if (ctx->mail != NULL) {
-               index_mail_cache_parse_deinit(ctx->mail, ctx->received_date,
+               index_mail_cache_parse_deinit(ctx->mail, ctx->ctx.received_date,
                                              !ctx->failed);
        }
        if (ctx->input != NULL)
index 9f7553557dd065ef09725dd68f531bdbfeb995a7..15deb252dfbbac30c464c596a29590b50790cbe3 100644 (file)
@@ -1012,7 +1012,8 @@ struct mailbox mbox_mailbox = {
                index_storage_search_deinit,
                index_storage_search_next_nonblock,
                index_storage_search_next_update_seq,
-               mbox_save_init,
+               mbox_save_alloc,
+               mbox_save_begin,
                mbox_save_continue,
                mbox_save_finish,
                mbox_save_cancel,
index 7749a5b2a2005d23182a38a32c33acc3a020348c..c154de0a63fbf1ec455e4a21d34c442af70ed2f9 100644 (file)
@@ -73,11 +73,9 @@ void mbox_transaction_class_deinit(void);
 struct mailbox_sync_context *
 mbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);
 
-int mbox_save_init(struct mailbox_transaction_context *_t,
-                  enum mail_flags flags, struct mail_keywords *keywords,
-                  time_t received_date, int timezone_offset,
-                  const char *from_envelope, struct istream *input,
-                  struct mail **dest_mail, struct mail_save_context **ctx_r);
+struct mail_save_context *
+mbox_save_alloc(struct mailbox_transaction_context *_t);
+int mbox_save_begin(struct mail_save_context *ctx, struct istream *input);
 int mbox_save_continue(struct mail_save_context *ctx);
 int mbox_save_finish(struct mail_save_context *ctx);
 void mbox_save_cancel(struct mail_save_context *ctx);
index f9e617f870641e4ae6095a3cf51c8bb27c75992c..df6e660d88348cac450af412c0d23fff7b48d56d 100644 (file)
@@ -308,6 +308,7 @@ struct mailbox raw_mailbox = {
                NULL,
                NULL,
                NULL,
+               NULL,
                mail_storage_copy,
                index_storage_is_inconsistent
        }
index 5bbe4d7baa58903ec4d35b21bef50e361b56f4b9..ceb524ca7c3e6d508947b2032fbd09b15c3a2f42 100644 (file)
@@ -25,8 +25,13 @@ int mail_storage_copy(struct mailbox_transaction_context *t, struct mail *mail,
        if (*from_envelope == '\0')
                from_envelope = NULL;
 
-       if (mailbox_save_init(t, flags, keywords, received_date,
-                             0, from_envelope, input, dest_mail, &ctx) < 0)
+       ctx = mailbox_save_alloc(t);
+       mailbox_save_set_flags(ctx, flags, keywords);
+       mailbox_save_set_received_date(ctx, received_date, 0);
+       mailbox_save_set_from_envelope(ctx, from_envelope);
+       mailbox_save_set_dest_mail(ctx, dest_mail);
+
+       if (mailbox_save_begin(&ctx, input) < 0)
                return -1;
 
        do {
index 5a38a1d82f2ab794a982066e4aabd342308f04fb..22f8b858d901490bcdb2769d43b06c60ccb2c958 100644 (file)
@@ -160,13 +160,9 @@ struct mailbox_vfuncs {
        /* Internal search function which updates ctx->seq */
        int (*search_next_update_seq)(struct mail_search_context *ctx);
 
-       int (*save_init)(struct mailbox_transaction_context *t,
-                        enum mail_flags flags,
-                        struct mail_keywords *keywords,
-                        time_t received_date, int timezone_offset,
-                        const char *from_envelope, struct istream *input,
-                        struct mail **dest_mail,
-                        struct mail_save_context **ctx_r);
+       struct mail_save_context *
+               (*save_alloc)(struct mailbox_transaction_context *t);
+       int (*save_begin)(struct mail_save_context *ctx, struct istream *input);
        int (*save_continue)(struct mail_save_context *ctx);
        int (*save_finish)(struct mail_save_context *ctx);
        void (*save_cancel)(struct mail_save_context *ctx);
@@ -320,6 +316,14 @@ struct mail_search_context {
 struct mail_save_context {
        struct mailbox_transaction_context *transaction;
        struct mail *dest_mail;
+
+       enum mail_flags flags;
+       struct mail_keywords *keywords;
+
+       time_t received_date;
+       int received_tz_offset;
+
+       char *from_envelope;
 };
 
 struct mailbox_sync_context {
index 30f14593ffbb43ff7c690daef95c99d8e0a8cd2a..747d773756dd11a5748c756661920ed56944ea59 100644 (file)
@@ -784,23 +784,61 @@ mailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
        return t->box;
 }
 
-int mailbox_save_init(struct mailbox_transaction_context *t,
-                     enum mail_flags flags, struct mail_keywords *keywords,
-                     time_t received_date, int timezone_offset,
-                     const char *from_envelope, struct istream *input,
-                     struct mail *dest_mail, struct mail_save_context **ctx_r)
-{
-       if (t->box->v.save_init == NULL) {
-               mail_storage_set_error(t->box->storage, MAIL_ERROR_NOTPOSSIBLE,
+struct mail_save_context *
+mailbox_save_alloc(struct mailbox_transaction_context *t)
+{
+       struct mail_save_context *ctx;
+
+       ctx = t->box->v.save_alloc(t);
+       ctx->received_date = (time_t)-1;
+       return ctx;
+}
+
+void mailbox_save_set_flags(struct mail_save_context *ctx,
+                           enum mail_flags flags,
+                           struct mail_keywords *keywords)
+{
+       ctx->flags = flags;
+       ctx->keywords = keywords;
+}
+
+void mailbox_save_set_received_date(struct mail_save_context *ctx,
+                                   time_t received_date, int timezone_offset)
+{
+       ctx->received_date = received_date;
+       ctx->received_tz_offset = timezone_offset;
+}
+
+void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
+                                   const char *envelope)
+{
+       i_free(ctx->from_envelope);
+       ctx->from_envelope = i_strdup(envelope);
+}
+
+void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
+                               struct mail *mail)
+{
+       ctx->dest_mail = mail;
+}
+
+int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
+{
+       struct mailbox *box = (*ctx)->transaction->box;
+       int ret;
+
+       if (box->v.save_begin == NULL) {
+               mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
                                       "Saving messages not supported");
-               return -1;
+               ret = -1;
+       } else {
+               ret = box->v.save_begin(*ctx, input);
        }
-       if (t->box->v.save_init(t, flags, keywords,
-                               received_date, timezone_offset,
-                               from_envelope, input, &dest_mail, ctx_r) < 0)
-               return -1;
 
-       (*ctx_r)->dest_mail = dest_mail;
+       if (ret < 0) {
+               mailbox_save_cancel(ctx);
+               return -1;
+       }
        return 0;
 }
 
@@ -814,6 +852,7 @@ int mailbox_save_finish(struct mail_save_context **_ctx)
        struct mail_save_context *ctx = *_ctx;
 
        *_ctx = NULL;
+       i_free(ctx->from_envelope);
        return ctx->transaction->box->v.save_finish(ctx);
 }
 
@@ -822,6 +861,7 @@ void mailbox_save_cancel(struct mail_save_context **_ctx)
        struct mail_save_context *ctx = *_ctx;
 
        *_ctx = NULL;
+       i_free(ctx->from_envelope);
        ctx->transaction->box->v.save_cancel(ctx);
 }
 
index d603678067f06a25a76aacff779b13f9d855a158..9e9933a419f9a98e77d7b9f54ee0fa19d1564e28 100644 (file)
@@ -449,24 +449,35 @@ void mailbox_search_result_sync(struct mail_search_result *result,
                                ARRAY_TYPE(seq_range) *removed_uids,
                                ARRAY_TYPE(seq_range) *added_uids);
 
-/* Save a mail into mailbox. timezone_offset specifies the timezone in
-   minutes in which received_date was originally given with. To use
-   current time, set received_date to (time_t)-1.
-
-   If dest_mail is set, the saved message can be accessed using it. Note that
+/* Initialize saving a new mail. You must not try to save more than one mail
+   at a time. */
+struct mail_save_context *
+mailbox_save_alloc(struct mailbox_transaction_context *t);
+/* Set the flags and keywords. Nothing is set by default. */
+void mailbox_save_set_flags(struct mail_save_context *ctx,
+                           enum mail_flags flags,
+                           struct mail_keywords *keywords);
+/* If received date isn't specified the current time is used. timezone_offset
+   specifies the preferred timezone in minutes, but it may be ignored if
+   backend doesn't support storing it. */
+void mailbox_save_set_received_date(struct mail_save_context *ctx,
+                                   time_t received_date, int timezone_offset);
+/* Set the envelope sender. This is currently used only with mbox files to
+   specify the address in From_-line. */
+void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
+                                   const char *envelope);
+/* If dest_mail is set, the saved message can be accessed using it. Note that
    setting it may require mailbox syncing, so don't set it unless you need
    it. Also you shouldn't try to access it before mailbox_save_finish() is
-   called.
-
-   The given input stream is never read in these functions, only the data
-   inside it is used. So you should call i_stream_read() yourself and then
-   call mailbox_save_continue() whenever more data is read.
-*/
-int mailbox_save_init(struct mailbox_transaction_context *t,
-                     enum mail_flags flags, struct mail_keywords *keywords,
-                     time_t received_date, int timezone_offset,
-                     const char *from_envelope, struct istream *input,
-                     struct mail *dest_mail, struct mail_save_context **ctx_r);
+   called. */
+void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
+                               struct mail *mail);
+/* Begin saving the message. All mail_save_set_*() calls must have been called
+   before this function. If the save initialization fails, the context is freed
+   and -1 is returned. After beginning the save you should keep calling
+   i_stream_read() and calling mailbox_save_continue() as long as there's
+   more input. */
+int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input);
 int mailbox_save_continue(struct mail_save_context *ctx);
 int mailbox_save_finish(struct mail_save_context **ctx);
 void mailbox_save_cancel(struct mail_save_context **ctx);
index bde7f42da5d120052867b013d3061296f3e5cd78..a0729257927dbea674f847993debd46150cb63f2 100644 (file)
@@ -246,23 +246,17 @@ static int acl_save_get_flags(struct mailbox *box, enum mail_flags *flags,
 }
 
 static int
-acl_save_init(struct mailbox_transaction_context *t,
-             enum mail_flags flags, struct mail_keywords *keywords,
-             time_t received_date, int timezone_offset,
-             const char *from_envelope, struct istream *input,
-             struct mail **dest_mail, struct mail_save_context **ctx_r)
+acl_save_begin(struct mail_save_context *ctx, struct istream *input)
 {
-       struct acl_mailbox *abox = ACL_CONTEXT(t->box);
+       struct mailbox *box = ctx->transaction->box;
+       struct acl_mailbox *abox = ACL_CONTEXT(box);
 
-       if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
+       if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_INSERT) <= 0)
                return -1;
-       if (acl_save_get_flags(t->box, &flags, &keywords) < 0)
+       if (acl_save_get_flags(box, &ctx->flags, &ctx->keywords) < 0)
                return -1;
 
-       return abox->module_ctx.super.
-               save_init(t, flags, keywords, received_date,
-                         timezone_offset, from_envelope,
-                         input, dest_mail, ctx_r);
+       return abox->module_ctx.super.save_begin(ctx, input);
 }
 
 static int
@@ -342,7 +336,7 @@ struct mailbox *acl_mailbox_open_box(struct mailbox *box)
        box->v.allow_new_keywords = acl_allow_new_keywords;
        box->v.close = acl_mailbox_close;
        box->v.mail_alloc = acl_mail_alloc;
-       box->v.save_init = acl_save_init;
+       box->v.save_begin = acl_save_begin;
        box->v.keywords_create = acl_keywords_create;
        box->v.copy = acl_copy;
        box->v.transaction_commit = acl_transaction_commit;
index 2b561d8811adf5a7713e24a2d8e5feca86676096..7ef5781bc64de12f20403a44efe4e89e167ceb1a 100644 (file)
@@ -187,12 +187,9 @@ quota_copy(struct mailbox_transaction_context *t, struct mail *mail,
 }
 
 static int
-quota_save_init(struct mailbox_transaction_context *t,
-               enum mail_flags flags, struct mail_keywords *keywords,
-               time_t received_date, int timezone_offset,
-               const char *from_envelope, struct istream *input,
-               struct mail **dest_mail, struct mail_save_context **ctx_r)
+quota_save_begin(struct mail_save_context *ctx, struct istream *input)
 {
+       struct mailbox_transaction_context *t = ctx->transaction;
        struct quota_transaction_context *qt = QUOTA_CONTEXT(t);
        struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box);
        const struct stat *st;
@@ -224,19 +221,16 @@ quota_save_init(struct mailbox_transaction_context *t,
                }
        }
 
-       if (*dest_mail == NULL) {
+       if (ctx->dest_mail == NULL) {
                /* we always want to know the mail size */
                if (qt->tmp_mail == NULL) {
                        qt->tmp_mail = mail_alloc(t, MAIL_FETCH_PHYSICAL_SIZE,
                                                  NULL);
                }
-               *dest_mail = qt->tmp_mail;
+               ctx->dest_mail = qt->tmp_mail;
        }
 
-       return qbox->module_ctx.super.
-               save_init(t, flags, keywords, received_date,
-                         timezone_offset, from_envelope,
-                         input, dest_mail, ctx_r);
+       return qbox->module_ctx.super.save_begin(ctx, input);
 }
 
 static int quota_save_finish(struct mail_save_context *ctx)
@@ -371,7 +365,7 @@ quota_mailbox_open(struct mail_storage *storage, const char *name,
        box->v.transaction_commit = quota_mailbox_transaction_commit;
        box->v.transaction_rollback = quota_mailbox_transaction_rollback;
        box->v.mail_alloc = quota_mail_alloc;
-       box->v.save_init = quota_save_init;
+       box->v.save_begin = quota_save_begin;
        box->v.save_finish = quota_save_finish;
        box->v.copy = quota_copy;
        box->v.sync_notify = quota_mailbox_sync_notify;
index d6cb1dad87bcbeda1bc1652b5f5468d025729f85..9cfca23f0b8562fb51d2adeacd2ae41b859898aa 100644 (file)
@@ -459,23 +459,6 @@ virtual_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
        return ret;
 }
 
-static int
-virtual_save_init(struct mailbox_transaction_context *_t,
-                 enum mail_flags flags ATTR_UNUSED,
-                 struct mail_keywords *keywords ATTR_UNUSED,
-                 time_t received_date ATTR_UNUSED,
-                 int timezone_offset ATTR_UNUSED,
-                 const char *from_envelope ATTR_UNUSED,
-                 struct istream *input ATTR_UNUSED,
-                 struct mail **dest_mail ATTR_UNUSED,
-                 struct mail_save_context **ctx_r)
-{
-       mail_storage_set_error(_t->box->storage, MAIL_ERROR_NOTPOSSIBLE,
-                              "Can't save to virtual mailboxes");
-       *ctx_r = NULL;
-       return -1;
-}
-
 static void virtual_class_init(void)
 {
        virtual_transaction_class_init();
@@ -537,7 +520,8 @@ struct mailbox virtual_mailbox = {
                index_storage_search_deinit,
                index_storage_search_next_nonblock,
                index_storage_search_next_update_seq,
-               virtual_save_init,
+               NULL,
+               NULL,
                NULL,
                NULL,
                NULL,