bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "istream.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "istream-crlf.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "ostream.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "str.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "hex-binary.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "index-mail.h"
c68f28e2cf5f9621511bece0414335e551dc82c6Timo Sirainen#include "index-storage.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "dbox-attachment.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "dbox-file.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "dbox-save.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_save_add_to_index(struct dbox_save_context *ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_data *mdata = &ctx->ctx.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen enum mail_flags save_flags;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen if ((ctx->ctx.transaction->flags & MAILBOX_TRANSACTION_FLAG_FILL_IN_STUB) == 0)
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen mail_index_append(ctx->trans, mdata->uid, &ctx->seq);
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen else
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen ctx->seq = mdata->stub_seq;
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen save_flags = mdata->flags & ~MAIL_RECENT;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen save_flags);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (mdata->keywords != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_keywords(ctx->trans, ctx->seq,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen MODIFY_REPLACE, mdata->keywords);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (mdata->min_modseq != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_modseq(ctx->trans, ctx->seq,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mdata->min_modseq);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_save_begin(struct dbox_save_context *ctx, struct istream *input)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_save_context *_ctx = &ctx->ctx;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct mail_storage *_storage = _ctx->transaction->box->storage;
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_storage *storage = DBOX_STORAGE(_storage);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_message_header dbox_msg_hdr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream *crlf_input;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_save_add_to_index(ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen mail_set_seq_saving(_ctx->dest_mail, ctx->seq);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen crlf_input = i_stream_create_lf(input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_unref(&crlf_input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* write a dummy header. it'll get rewritten when we're finished */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&dbox_msg_hdr);
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen o_stream_cork(ctx->dbox_output);
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen if (o_stream_send(ctx->dbox_output, &dbox_msg_hdr,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sizeof(dbox_msg_hdr)) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mail_set_critical(_ctx->dest_mail, "write(%s) failed: %s",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi o_stream_get_name(ctx->dbox_output),
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi o_stream_get_error(ctx->dbox_output));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->failed = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen _ctx->data.output = ctx->dbox_output;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (_ctx->data.received_date == (time_t)-1)
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen _ctx->data.received_date = ioloop_time;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen index_attachment_save_begin(_ctx, storage->attachment_fs, ctx->input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_save_continue(struct mail_save_context *_ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_save_context *ctx = DBOX_SAVECTX(_ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->failed)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (_ctx->data.attach != NULL)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return index_attachment_save_continue(_ctx);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
c68f28e2cf5f9621511bece0414335e551dc82c6Timo Sirainen if (index_storage_save_continue(_ctx, ctx->input,
c68f28e2cf5f9621511bece0414335e551dc82c6Timo Sirainen _ctx->dest_mail) < 0) {
c68f28e2cf5f9621511bece0414335e551dc82c6Timo Sirainen ctx->failed = TRUE;
c68f28e2cf5f9621511bece0414335e551dc82c6Timo Sirainen return -1;
c68f28e2cf5f9621511bece0414335e551dc82c6Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainenvoid dbox_save_end(struct dbox_save_context *ctx)
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen{
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_data *mdata = &ctx->ctx.data;
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen struct ostream *dbox_output = ctx->dbox_output;
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen int ret;
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen
48325adac125d7ff275ec69b05b7a92be9637630Timo Sirainen i_assert(mdata->output != NULL);
48325adac125d7ff275ec69b05b7a92be9637630Timo Sirainen
1b6c4fdd2bb4234b5711874b3845547f49649744Timo Sirainen if (mdata->attach != NULL && !ctx->failed) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (index_attachment_save_finish(&ctx->ctx) < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ctx->failed = TRUE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen if (mdata->output != dbox_output) {
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen /* e.g. zlib plugin had changed this. make sure we
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen successfully write the trailer. */
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen ret = o_stream_finish(mdata->output);
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen } else {
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen /* no plugins - flush the output so far */
d1ba8ecbb936ace90179d2292952546708d68f71Timo Sirainen ret = o_stream_flush(mdata->output);
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen }
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen if (ret < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mail_set_critical(ctx->ctx.dest_mail,
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi "write(%s) failed: %s",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi o_stream_get_name(mdata->output),
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi o_stream_get_error(mdata->output));
efb83f10b2a557d7427c311da52d768fb91e1b47Timo Sirainen ctx->failed = TRUE;
efb83f10b2a557d7427c311da52d768fb91e1b47Timo Sirainen }
c25dfa96bc32e8841c9a8cf5ba02fffba4290160Timo Sirainen if (mdata->output != dbox_output) {
3177b410680f3915549719f84a4acbffd4f9c561Timo Sirainen o_stream_ref(dbox_output);
3177b410680f3915549719f84a4acbffd4f9c561Timo Sirainen o_stream_destroy(&mdata->output);
3177b410680f3915549719f84a4acbffd4f9c561Timo Sirainen mdata->output = dbox_output;
c3d9da3955043aef88c17b71f2081e894186aa6bTimo Sirainen }
c3d9da3955043aef88c17b71f2081e894186aa6bTimo Sirainen index_mail_cache_parse_deinit(ctx->ctx.dest_mail,
c25dfa96bc32e8841c9a8cf5ba02fffba4290160Timo Sirainen ctx->ctx.data.received_date,
c25dfa96bc32e8841c9a8cf5ba02fffba4290160Timo Sirainen !ctx->failed);
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen}
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainenvoid dbox_save_write_metadata(struct mail_save_context *_ctx,
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen struct ostream *output, uoff_t output_msg_size,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *orig_mailbox_name,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_t guid_128)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_save_context *ctx = DBOX_SAVECTX(_ctx);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_data *mdata = &ctx->ctx.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_metadata_header metadata_hdr;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *guid;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen string_t *str;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uoff_t vsize;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&metadata_hdr);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memcpy(metadata_hdr.magic_post, DBOX_MAGIC_POST,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sizeof(metadata_hdr.magic_post));
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, &metadata_hdr, sizeof(metadata_hdr));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str = t_str_new(256);
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen if (output_msg_size != ctx->input->v_offset) {
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen /* a plugin changed the data written to disk, so the
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen "message size" dbox header doesn't contain the actual
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen "physical" message size. we need to save it as a
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen separate metadata header. */
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen str_printfa(str, "%c%llx\n", DBOX_METADATA_PHYSICAL_SIZE,
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen (unsigned long long)ctx->input->v_offset);
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen }
f89eb8f2cda0bd6d40a9f96db1c92517f0593871Martti Rannanjärvi str_printfa(str, "%c%"PRIxTIME_T"\n", DBOX_METADATA_RECEIVED_TIME,
f89eb8f2cda0bd6d40a9f96db1c92517f0593871Martti Rannanjärvi mdata->received_date);
1f19649986397419d014febd1337c6eb7b530f26Timo Sirainen if (mail_get_virtual_size(_ctx->dest_mail, &vsize) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_unreached();
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, "%c%llx\n", DBOX_METADATA_VIRTUAL_SIZE,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (unsigned long long)vsize);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (mdata->pop3_uidl != NULL) {
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen i_assert(strchr(mdata->pop3_uidl, '\n') == NULL);
a8bc64d2ec8babb5109fa23aa3c90383de61cd69Timo Sirainen str_printfa(str, "%c%s\n", DBOX_METADATA_POP3_UIDL,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mdata->pop3_uidl);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen ctx->have_pop3_uidls = TRUE;
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen ctx->highest_pop3_uidl_seq =
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen I_MAX(ctx->highest_pop3_uidl_seq, ctx->seq);
a8bc64d2ec8babb5109fa23aa3c90383de61cd69Timo Sirainen }
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen if (mdata->pop3_order != 0) {
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen str_printfa(str, "%c%u\n", DBOX_METADATA_POP3_ORDER,
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen mdata->pop3_order);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen ctx->have_pop3_orders = TRUE;
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen ctx->highest_pop3_uidl_seq =
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen I_MAX(ctx->highest_pop3_uidl_seq, ctx->seq);
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen guid = mdata->guid;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (guid != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_generate_guid_128_hash(guid, guid_128);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen else {
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_generate(guid_128);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid = guid_128_to_string(guid_128);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, "%c%s\n", DBOX_METADATA_GUID, guid);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (orig_mailbox_name != NULL &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen strchr(orig_mailbox_name, '\r') == NULL &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen strchr(orig_mailbox_name, '\n') == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* save the original mailbox name so if mailbox indexes get
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen corrupted we can place at least some (hopefully most) of
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen the messages to correct mailboxes. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, "%c%s\n", DBOX_METADATA_ORIG_MAILBOX,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen orig_mailbox_name);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen dbox_attachment_save_write_metadata(_ctx, str);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_append_c(str, '\n');
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainenvoid dbox_save_update_header_flags(struct dbox_save_context *ctx,
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen struct mail_index_view *sync_view,
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen uint32_t ext_id,
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen unsigned int flags_offset)
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen{
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen const void *data;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen size_t data_size;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen uint8_t old_flags = 0, flags;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen mail_index_get_header_ext(sync_view, ext_id, &data, &data_size);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen if (flags_offset < data_size)
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen old_flags = *((const uint8_t *)data + flags_offset);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen else {
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen /* grow old dbox header */
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen mail_index_ext_resize_hdr(ctx->trans, ext_id, flags_offset+1);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen }
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen flags = old_flags;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen if (ctx->have_pop3_uidls)
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen if (ctx->have_pop3_orders)
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen if (flags != old_flags) {
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen /* flags changed, update them */
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen mail_index_update_header_ext(ctx->trans, ext_id,
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen flags_offset, &flags, 1);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen }
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen}