bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
08b30498acefc69e223baf7eda6429be98cc3a10Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "message-parser.h"
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen#include "index-storage.h"
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include "index-sync-changes.h"
08b30498acefc69e223baf7eda6429be98cc3a10Timo Sirainen#include "mbox-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mbox-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen/* Line length when to wrap X-IMAP, X-IMAPbase and X-Keywords headers to next
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen line. Keep this pretty long, as after we wrap we lose compatibility with
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen UW-IMAP */
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen#define KEYWORD_WRAP_LINE_LENGTH 1024
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void status_flags_append(struct mbox_sync_mail_context *ctx,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen const struct mbox_flag_type *flags_list)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; flags_list[i].chr != 0; i++) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if ((ctx->mail.flags & flags_list[i].flag) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(ctx->header, flags_list[i].chr);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainenvoid mbox_sync_move_buffer(struct mbox_sync_mail_context *ctx,
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen size_t pos, size_t need, size_t have)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen ssize_t diff = (ssize_t)need - (ssize_t)have;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen int i;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
2d3aac5be07b96f72cf0551fac35ac74a4f07770Timo Sirainen i_assert(have < SSIZE_T_MAX);
2d3aac5be07b96f72cf0551fac35ac74a4f07770Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (diff == 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ctx->header_last_change < pos + have ||
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ctx->header_last_change == (size_t)-1)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ctx->header_last_change = pos + have;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else {
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen /* FIXME: if (diff < ctx->space && pos < ctx->offset) then
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen move the data only up to space offset and give/take the
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen space from there. update header_last_change accordingly.
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen (except pos and offset can't be compared directly) */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ctx->header_last_change = (size_t)-1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen for (i = 0; i < MBOX_HDR_COUNT; i++) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ctx->hdr_pos[i] > pos &&
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ctx->hdr_pos[i] != (size_t)-1)
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen ctx->hdr_pos[i] += diff;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen if (ctx->mail.space > 0) {
a6a2b38d806f3ab3198160e39240a8200775e525Timo Sirainen i_assert(ctx->mail.offset + ctx->mail.space <=
a6a2b38d806f3ab3198160e39240a8200775e525Timo Sirainen ctx->hdr_offset + pos ||
a6a2b38d806f3ab3198160e39240a8200775e525Timo Sirainen ctx->mail.offset > ctx->hdr_offset + pos + have);
fb2e0bbb7737f3223b16aa41e4b40fb0cd5f288fTimo Sirainen if (ctx->mail.offset > ctx->hdr_offset + pos) {
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen /* free space offset moves */
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen ctx->mail.offset += diff;
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen }
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen }
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (diff < 0)
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen str_delete(ctx->header, pos, -diff);
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen else {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ctx->header_last_change = (size_t)-1;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen buffer_copy(ctx->header, pos + diff,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ctx->header, pos, (size_t)-1);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenstatic void status_flags_replace(struct mbox_sync_mail_context *ctx, size_t pos,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen const struct mbox_flag_type *flags_list)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen unsigned char *data;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size_t size;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen int i, need, have;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ctx->header_first_change > pos)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ctx->header_first_change = pos;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* how many bytes do we need? */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (i = 0, need = 0; flags_list[i].chr != 0; i++) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if ((ctx->mail.flags & flags_list[i].flag) != 0)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen need++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* how many bytes do we have now? */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen data = buffer_get_modifiable_data(ctx->header, &size);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (have = 0; pos < size; pos++) {
e5759add4dc24b96606dccc4a989838e260f2a12Timo Sirainen if (data[pos] == '\n' || data[pos] == '\r')
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen break;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* see if this is unknown flag for us */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (i = 0; flags_list[i].chr != 0; i++) {
4efba37e4f27b93832f6147c3a353d6d22c855c7Timo Sirainen if (flags_list[i].chr == (char)data[pos])
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen break;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (flags_list[i].chr != 0)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen have++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen else {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* save this one */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen data[pos-have] = data[pos];
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen pos -= have;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_sync_move_buffer(ctx, pos, need, have);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* @UNSAFE */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen data = buffer_get_space_unsafe(ctx->header, pos, need);
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen for (i = 0; flags_list[i].chr != 0; i++) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if ((ctx->mail.flags & flags_list[i].flag) != 0)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen *data++ = flags_list[i].chr;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainen
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic void
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenkeywords_append(struct mbox_sync_context *sync_ctx, string_t *dest,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const ARRAY_TYPE(keyword_indexes) *keyword_indexes_arr)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct index_mailbox_context *ibox =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen INDEX_STORAGE_CONTEXT(&sync_ctx->mbox->box);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *const *keyword_names;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const unsigned int *keyword_indexes;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen unsigned int i, idx_count, keywords_count;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen size_t last_break;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen keyword_names = array_get(ibox->keyword_names,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen &keywords_count);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen keyword_indexes = array_get(keyword_indexes_arr, &idx_count);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
197ad81605dc0f6d2ebc9ad99994db5ca6d76699Timo Sirainen for (i = 0, last_break = str_len(dest); i < idx_count; i++) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_assert(keyword_indexes[i] < keywords_count);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen /* wrap the line whenever it gets too long */
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen if (str_len(dest) - last_break < KEYWORD_WRAP_LINE_LENGTH) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (i > 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append_c(dest, ' ');
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append(dest, "\n\t");
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen last_break = str_len(dest);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append(dest, keyword_names[keyword_indexes[i]]);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic void
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainenkeywords_append_all(struct mbox_sync_mail_context *ctx, string_t *dest,
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen size_t startpos)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct index_mailbox_context *ibox =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen INDEX_STORAGE_CONTEXT(&ctx->sync_ctx->mbox->box);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *const *names;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const unsigned char *p;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen unsigned int i, count;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen size_t last_break;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen p = str_data(dest);
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen if (str_len(dest) - startpos < KEYWORD_WRAP_LINE_LENGTH)
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen last_break = startpos;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen else {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* set last_break to beginning of line */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for (last_break = str_len(dest); last_break > 0; last_break--) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (p[last_break-1] == '\n')
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen break;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen names = array_get(ibox->keyword_names, &count);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for (i = 0; i < count; i++) {
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen /* wrap the line whenever it gets too long */
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen if (str_len(dest) - last_break < KEYWORD_WRAP_LINE_LENGTH)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append_c(dest, ' ');
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen else {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append(dest, "\n\t");
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen last_break = str_len(dest);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append(dest, names[i]);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mbox_sync_add_missing_headers(struct mbox_sync_mail_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen size_t new_hdr_size, startpos;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen new_hdr_size = str_len(ctx->header);
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen if (new_hdr_size > 0 &&
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen str_data(ctx->header)[new_hdr_size-1] != '\n') {
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen /* broken header - doesn't end with \n. fix it. */
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen str_append_c(ctx->header, '\n');
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen }
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (ctx->sync_ctx->dest_first_mail &&
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] == (size_t)-1) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen i_assert(ctx->sync_ctx->base_uid_validity != 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen str_append(ctx->header, "X-IMAPbase: ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] = str_len(ctx->header);
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen /* startpos must start from identical position as when
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen updating */
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen startpos = str_len(ctx->header);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen str_printfa(ctx->header, "%u ",
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->sync_ctx->base_uid_validity);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
bf301a34ffbfd049be583094019b2644884b6d0bTimo Sirainen ctx->last_uid_updated_value = ctx->sync_ctx->next_uid-1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->last_uid_value_start_pos = str_len(ctx->header) -
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE];
58eb2cb24dbeadd94500670acad7ceb1c8b0d9b4Timo Sirainen ctx->imapbase_updated = TRUE;
bf301a34ffbfd049be583094019b2644884b6d0bTimo Sirainen str_printfa(ctx->header, "%010u", ctx->last_uid_updated_value);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen keywords_append_all(ctx, ctx->header, startpos);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(ctx->header, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_UID] == (size_t)-1 && !ctx->mail.pseudo) {
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen str_append(ctx->header, "X-UID: ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_UID] = str_len(ctx->header);
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen str_printfa(ctx->header, "%u\n", ctx->mail.uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->hdr_pos[MBOX_HDR_STATUS] == (size_t)-1 &&
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen (ctx->mail.flags & STATUS_FLAGS_MASK) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(ctx->header, "Status: ");
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen ctx->hdr_pos[MBOX_HDR_STATUS] = str_len(ctx->header);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen status_flags_append(ctx, mbox_status_flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(ctx->header, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_STATUS] == (size_t)-1 &&
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen (ctx->mail.flags & XSTATUS_FLAGS_MASK) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(ctx->header, "X-Status: ");
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_STATUS] = str_len(ctx->header);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen status_flags_append(ctx, mbox_xstatus_flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(ctx->header, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] == (size_t)-1 &&
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_is_created(&ctx->mail.keywords) &&
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_count(&ctx->mail.keywords) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(ctx->header, "X-Keywords: ");
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = str_len(ctx->header);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen keywords_append(ctx->sync_ctx, ctx->header,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen &ctx->mail.keywords);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(ctx->header, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
08b30498acefc69e223baf7eda6429be98cc3a10Timo Sirainen if (ctx->content_length == (uoff_t)-1 &&
08b30498acefc69e223baf7eda6429be98cc3a10Timo Sirainen ctx->mail.body_size >= MBOX_MIN_CONTENT_LENGTH_SIZE) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(ctx->header, "Content-Length: %"PRIuUOFF_T"\n",
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ctx->mail.body_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (str_len(ctx->header) != new_hdr_size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->header_first_change == (size_t)-1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->header_first_change = new_hdr_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->header_last_change = (size_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->have_eoh)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(ctx->header, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mbox_sync_update_status(struct mbox_sync_mail_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_STATUS] != (size_t)-1) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen status_flags_replace(ctx, ctx->hdr_pos[MBOX_HDR_STATUS],
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mbox_status_flags);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mbox_sync_update_xstatus(struct mbox_sync_mail_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_STATUS] != (size_t)-1) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen status_flags_replace(ctx, ctx->hdr_pos[MBOX_HDR_X_STATUS],
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mbox_xstatus_flags);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainenstatic void mbox_sync_update_line(struct mbox_sync_mail_context *ctx,
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen size_t pos, string_t *new_line)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen{
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen const char *hdr, *p;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen uoff_t file_pos;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (ctx->header_first_change > pos)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen ctx->header_first_change = pos;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen /* set p = end of header, handle also wrapped headers */
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen hdr = p = str_c(ctx->header) + pos;
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen for (;;) {
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen p = strchr(p, '\n');
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen if (p == NULL) {
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen /* shouldn't really happen, but allow anyway.. */
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen p = hdr + strlen(hdr);
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen break;
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen }
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen if (p[1] != '\t' && p[1] != ' ')
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen break;
92139717fd109c34692670df54d157d8c4df9b71Timo Sirainen p += 2;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen file_pos = pos + ctx->hdr_offset;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ctx->mail.space > 0 && ctx->mail.offset >= file_pos &&
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->mail.offset < file_pos + (p - hdr)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* extra space points to this line. remove it. */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->mail.offset = ctx->hdr_offset;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->mail.space = 0;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mbox_sync_move_buffer(ctx, pos, str_len(new_line), p - hdr + 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen buffer_copy(ctx->header, pos, new_line, 0, (size_t)-1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic void mbox_sync_update_xkeywords(struct mbox_sync_mail_context *ctx)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen string_t *str;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] == (size_t)-1)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str = t_str_new(256);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (array_is_created(&ctx->mail.keywords))
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen keywords_append(ctx->sync_ctx, str, &ctx->mail.keywords);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append_c(str, '\n');
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_KEYWORDS], str);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen}
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic void mbox_sync_update_x_imap_base(struct mbox_sync_mail_context *ctx)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct mbox_sync_context *sync_ctx = ctx->sync_ctx;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen string_t *str;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen i_assert(sync_ctx->base_uid_validity != 0);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (!sync_ctx->dest_first_mail ||
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] == (size_t)-1)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (!ctx->imapbase_rewrite) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* uid-last might need updating, but we'll do it later by
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen writing it directly where needed. */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* a) keyword list changed, b) uid-last didn't use 10 digits */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen str = t_str_new(200);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen str_printfa(str, "%u ", sync_ctx->base_uid_validity);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
bf301a34ffbfd049be583094019b2644884b6d0bTimo Sirainen ctx->last_uid_updated_value = sync_ctx->next_uid-1;
51ff0538ab38def8045b3f7feb43e1e069cbe037Timo Sirainen ctx->last_uid_value_start_pos = str_len(str);
58eb2cb24dbeadd94500670acad7ceb1c8b0d9b4Timo Sirainen ctx->imapbase_updated = TRUE;
bf301a34ffbfd049be583094019b2644884b6d0bTimo Sirainen str_printfa(str, "%010u", ctx->last_uid_updated_value);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
2054222e84cb972842cc4de88e16516bef41b542Timo Sirainen keywords_append_all(ctx, str, 0);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen str_append_c(str, '\n');
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_IMAPBASE], str);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainenstatic void mbox_sync_update_x_uid(struct mbox_sync_mail_context *ctx)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen{
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen string_t *str;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_UID] == (size_t)-1 ||
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen ctx->mail.uid == ctx->parsed_uid)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen return;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen str = t_str_new(64);
a60c1c1fca85402e6fccbf3ae0784b7179ae186cTimo Sirainen str_printfa(str, "%u\n", ctx->mail.uid);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_UID], str);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void mbox_sync_update_header_real(struct mbox_sync_mail_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen i_assert(ctx->mail.uid != 0 || ctx->mail.pseudo);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen if (!ctx->sync_ctx->keep_recent)
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen ctx->mail.flags &= ~MAIL_RECENT;
08fa343b3aace9343da3195686c65c5326eda207Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_sync_update_status(ctx);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_sync_update_xstatus(ctx);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_sync_update_xkeywords(ctx);
dc049c5e83d947aaf1b97c26ae819cc9577e0475Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_sync_update_x_imap_base(ctx);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mbox_sync_update_x_uid(ctx);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen mbox_sync_add_missing_headers(ctx);
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen ctx->updated = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenvoid mbox_sync_update_header(struct mbox_sync_mail_context *ctx)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mbox_sync_update_header_real(ctx);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenmbox_sync_update_header_from_real(struct mbox_sync_mail_context *ctx,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen const struct mbox_sync_mail *mail)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
511a7ccd55cea57c9d953920b7d651720128ada9Timo Sirainen if (mail->status_broken ||
511a7ccd55cea57c9d953920b7d651720128ada9Timo Sirainen (ctx->mail.flags & STATUS_FLAGS_MASK) !=
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (mail->flags & STATUS_FLAGS_MASK) ||
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen (ctx->mail.flags & MAIL_RECENT) != 0) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ctx->mail.flags = (ctx->mail.flags & ~STATUS_FLAGS_MASK) |
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen (mail->flags & STATUS_FLAGS_MASK);
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen if (!ctx->sync_ctx->keep_recent)
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen ctx->mail.flags &= ~MAIL_RECENT;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mbox_sync_update_status(ctx);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
511a7ccd55cea57c9d953920b7d651720128ada9Timo Sirainen if (mail->xstatus_broken ||
511a7ccd55cea57c9d953920b7d651720128ada9Timo Sirainen (ctx->mail.flags & XSTATUS_FLAGS_MASK) !=
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen (mail->flags & XSTATUS_FLAGS_MASK)) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ctx->mail.flags = (ctx->mail.flags & ~XSTATUS_FLAGS_MASK) |
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen (mail->flags & XSTATUS_FLAGS_MASK);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mbox_sync_update_xstatus(ctx);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (!array_is_created(&mail->keywords) ||
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_count(&mail->keywords) == 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* no keywords for this mail */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (array_is_created(&ctx->mail.keywords)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_clear(&ctx->mail.keywords);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mbox_sync_update_xkeywords(ctx);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else if (!array_is_created(&ctx->mail.keywords)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* adding first keywords */
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen p_array_init(&ctx->mail.keywords,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->sync_ctx->mail_keyword_pool,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_count(&mail->keywords));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append_array(&ctx->mail.keywords,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen &mail->keywords);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mbox_sync_update_xkeywords(ctx);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen } else if (!array_cmp(&ctx->mail.keywords, &mail->keywords)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* keywords changed. */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_clear(&ctx->mail.keywords);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append_array(&ctx->mail.keywords,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen &mail->keywords);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mbox_sync_update_xkeywords(ctx);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dc52b16795b56589923ff586e5cdd0c0f1fd5931Timo Sirainen i_assert(ctx->mail.uid == 0 || ctx->mail.uid == mail->uid);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ctx->mail.uid = mail->uid;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_sync_update_x_imap_base(ctx);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mbox_sync_update_x_uid(ctx);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mbox_sync_add_missing_headers(ctx);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenvoid mbox_sync_update_header_from(struct mbox_sync_mail_context *ctx,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const struct mbox_sync_mail *mail)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mbox_sync_update_header_from_real(ctx, mail);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}