mbox-sync-update.c revision ced118ac5caf6fe83d34339c2c65c63b2aa768ac
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "lib.h"
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen#include "array.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "buffer.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "str.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "message-parser.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "index-storage.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "index-sync-changes.h"
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen#include "mbox-storage.h"
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen#include "mbox-sync-private.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen/* Line length when to wrap X-IMAP, X-IMAPbase and X-Keywords headers to next
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen line. Keep this pretty long, as after we wrap we lose compatibility with
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen UW-IMAP */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define KEYWORD_WRAP_LINE_LENGTH 1024
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic void status_flags_append(struct mbox_sync_mail_context *ctx,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const struct mbox_flag_type *flags_list)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen int i;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen for (i = 0; flags_list[i].chr != 0; i++) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if ((ctx->mail.flags & flags_list[i].flag) != 0)
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen str_append_c(ctx->header, flags_list[i].chr);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenvoid mbox_sync_move_buffer(struct mbox_sync_mail_context *ctx,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen size_t pos, size_t need, size_t have)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ssize_t diff = (ssize_t)need - (ssize_t)have;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen int i;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen i_assert(have < SSIZE_T_MAX);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (diff == 0) {
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen if (ctx->header_last_change < pos + have ||
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen ctx->header_last_change == (size_t)-1)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->header_last_change = pos + have;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen } else {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* FIXME: if (diff < ctx->space && pos < ctx->offset) then
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen move the data only up to space offset and give/take the
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen space from there. update header_last_change accordingly.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen (except pos and offset can't be compared directly) */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->header_last_change = (size_t)-1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen for (i = 0; i < MBOX_HDR_COUNT; i++) {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (ctx->hdr_pos[i] > pos &&
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->hdr_pos[i] != (size_t)-1)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->hdr_pos[i] += diff;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (ctx->mail.space > 0) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen i_assert(ctx->mail.offset + ctx->mail.space <=
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen ctx->hdr_offset + pos ||
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen ctx->mail.offset > ctx->hdr_offset + pos + have);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (ctx->mail.offset > ctx->hdr_offset + pos) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* free space offset moves */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen ctx->mail.offset += diff;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (diff < 0)
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen str_delete(ctx->header, pos, -diff);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen else {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->header_last_change = (size_t)-1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen buffer_copy(ctx->header, pos + diff,
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen ctx->header, pos, (size_t)-1);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainenstatic void status_flags_replace(struct mbox_sync_mail_context *ctx, size_t pos,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const struct mbox_flag_type *flags_list)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen unsigned char *data;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen size_t size;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen int i, need, have;
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen if (ctx->header_first_change > pos)
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen ctx->header_first_change = pos;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen /* how many bytes do we need? */
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen for (i = 0, need = 0; flags_list[i].chr != 0; i++) {
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen if ((ctx->mail.flags & flags_list[i].flag) != 0)
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen need++;
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen }
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen /* how many bytes do we have now? */
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen data = buffer_get_modifiable_data(ctx->header, &size);
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen for (have = 0; pos < size; pos++) {
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen if (data[pos] == '\n' || data[pos] == '\r')
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen break;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen /* see if this is unknown flag for us */
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen for (i = 0; flags_list[i].chr != 0; i++) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (flags_list[i].chr == data[pos])
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen break;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (flags_list[i].chr != 0)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen have++;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen else {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* save this one */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen data[pos-have] = data[pos];
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen pos -= have;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen mbox_sync_move_buffer(ctx, pos, need, have);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* @UNSAFE */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen data = buffer_get_space_unsafe(ctx->header, pos, need);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen for (i = 0, need = 0; flags_list[i].chr != 0; i++) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if ((ctx->mail.flags & flags_list[i].flag) != 0)
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen *data++ = flags_list[i].chr;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic void
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenkeywords_append(struct mbox_sync_context *sync_ctx, string_t *dest,
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen const ARRAY_TYPE(keyword_indexes) *keyword_indexes_arr)
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen{
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen const char *const *keyword_names;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen const unsigned int *keyword_indexes;
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen unsigned int i, idx_count, keywords_count;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen size_t last_break;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen keyword_names = array_get(sync_ctx->mbox->ibox.keyword_names,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen &keywords_count);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen keyword_indexes = array_get(keyword_indexes_arr, &idx_count);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen for (i = 0, last_break = str_len(dest); i < idx_count; i++) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen i_assert(keyword_indexes[i] < keywords_count);
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen /* wrap the line whenever it gets too long */
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen if (str_len(dest) - last_break < KEYWORD_WRAP_LINE_LENGTH) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (i > 0)
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen str_append_c(dest, ' ');
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen } else {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_append(dest, "\n\t");
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen last_break = str_len(dest);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_append(dest, keyword_names[keyword_indexes[i]]);
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen }
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen}
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainenstatic void
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainenkeywords_append_all(struct mbox_sync_mail_context *ctx, string_t *dest,
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen size_t startpos)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
20b136f04257b0ba338e49f31a999c0d4b243647Timo Sirainen const char *const *names;
20b136f04257b0ba338e49f31a999c0d4b243647Timo Sirainen const unsigned char *p;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen unsigned int i, count;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen size_t last_break;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen p = str_data(dest);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (str_len(dest) - startpos < KEYWORD_WRAP_LINE_LENGTH)
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen last_break = startpos;
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen else {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* set last_break to beginning of line */
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen for (last_break = str_len(dest); last_break > 0; last_break--) {
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen if (p[last_break-1] == '\n')
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen break;
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen }
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen }
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen names = array_get(ctx->sync_ctx->mbox->ibox.keyword_names, &count);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen for (i = 0; i < count; i++) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* wrap the line whenever it gets too long */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (str_len(dest) - last_break < KEYWORD_WRAP_LINE_LENGTH)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append_c(dest, ' ');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen else {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append(dest, "\n\t");
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen last_break = str_len(dest);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen }
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen str_append(dest, names[i]);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen
e22b857e838fe118de3f78513aad6a3c6f4306b3Timo Sirainenstatic void mbox_sync_add_missing_headers(struct mbox_sync_mail_context *ctx)
e22b857e838fe118de3f78513aad6a3c6f4306b3Timo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen size_t old_hdr_size, new_hdr_size, startpos;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen old_hdr_size = ctx->body_offset - ctx->hdr_offset;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen new_hdr_size = str_len(ctx->header);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (new_hdr_size > 0 &&
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen str_data(ctx->header)[new_hdr_size-1] != '\n') {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* broken header - doesn't end with \n. fix it. */
48566ca412a7cf3b42512fd0ec112744778e5da0Timo Sirainen str_append_c(ctx->header, '\n');
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen }
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen if (ctx->sync_ctx->dest_first_mail &&
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] == (size_t)-1) {
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen i_assert(ctx->sync_ctx->base_uid_validity != 0);
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen str_append(ctx->header, "X-IMAPbase: ");
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] = str_len(ctx->header);
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen /* startpos must start from identical position as when
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen updating */
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen startpos = str_len(ctx->header);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen str_printfa(ctx->header, "%u ",
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen ctx->sync_ctx->base_uid_validity);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->last_uid_updated_value = ctx->sync_ctx->next_uid-1;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->last_uid_value_start_pos = str_len(ctx->header) -
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE];
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->imapbase_updated = TRUE;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen str_printfa(ctx->header, "%010u", ctx->last_uid_updated_value);
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen keywords_append_all(ctx, ctx->header, startpos);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen str_append_c(ctx->header, '\n');
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_UID] == (size_t)-1 && !ctx->mail.pseudo) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append(ctx->header, "X-UID: ");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_UID] = str_len(ctx->header);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_printfa(ctx->header, "%u\n", ctx->mail.uid);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_STATUS] == (size_t)-1 &&
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen (ctx->mail.flags & STATUS_FLAGS_MASK) != 0) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append(ctx->header, "Status: ");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->hdr_pos[MBOX_HDR_STATUS] = str_len(ctx->header);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen status_flags_append(ctx, mbox_status_flags);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append_c(ctx->header, '\n');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_STATUS] == (size_t)-1 &&
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen (ctx->mail.flags & XSTATUS_FLAGS_MASK) != 0) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append(ctx->header, "X-Status: ");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_STATUS] = str_len(ctx->header);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen status_flags_append(ctx, mbox_xstatus_flags);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append_c(ctx->header, '\n');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] == (size_t)-1 &&
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen array_is_created(&ctx->mail.keywords) &&
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen array_count(&ctx->mail.keywords) > 0) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append(ctx->header, "X-Keywords: ");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = str_len(ctx->header);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen keywords_append(ctx->sync_ctx, ctx->header,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen &ctx->mail.keywords);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append_c(ctx->header, '\n');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->content_length == (uoff_t)-1 &&
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.body_size >= MBOX_MIN_CONTENT_LENGTH_SIZE) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_printfa(ctx->header, "Content-Length: %"PRIuUOFF_T"\n",
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.body_size);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (str_len(ctx->header) != new_hdr_size) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->header_first_change == (size_t)-1)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->header_first_change = new_hdr_size;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->header_last_change = (size_t)-1;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->have_eoh)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append_c(ctx->header, '\n');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenstatic void mbox_sync_update_status(struct mbox_sync_mail_context *ctx)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen{
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_STATUS] != (size_t)-1) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen status_flags_replace(ctx, ctx->hdr_pos[MBOX_HDR_STATUS],
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_status_flags);
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainenstatic void mbox_sync_update_xstatus(struct mbox_sync_mail_context *ctx)
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen{
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_STATUS] != (size_t)-1) {
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen status_flags_replace(ctx, ctx->hdr_pos[MBOX_HDR_X_STATUS],
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen mbox_xstatus_flags);
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen }
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen}
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainenstatic void mbox_sync_update_line(struct mbox_sync_mail_context *ctx,
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen size_t pos, string_t *new_line)
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen{
af3f857bb3166ed99595e11a9d18e5b5cc670e1aTimo Sirainen const char *hdr, *p;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen uoff_t file_pos;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->header_first_change > pos)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->header_first_change = pos;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen /* set p = end of header, handle also wrapped headers */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen hdr = p = str_c(ctx->header) + pos;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen for (;;) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen p = strchr(p, '\n');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (p == NULL) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen /* shouldn't really happen, but allow anyway.. */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen p = hdr + strlen(hdr);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen break;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (p[1] != '\t' && p[1] != ' ')
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen break;
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen p += 2;
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen file_pos = pos + ctx->hdr_offset;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->mail.space > 0 && ctx->mail.offset >= file_pos &&
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.offset < file_pos + (p - hdr)) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen /* extra space points to this line. remove it. */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.offset = ctx->hdr_offset;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.space = 0;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_move_buffer(ctx, pos, str_len(new_line), p - hdr + 1);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen buffer_copy(ctx->header, pos, new_line, 0, (size_t)-1);
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenstatic void mbox_sync_update_xkeywords(struct mbox_sync_mail_context *ctx)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen{
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen string_t *str;
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] == (size_t)-1)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen return;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str = t_str_new(256);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (array_is_created(&ctx->mail.keywords))
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen keywords_append(ctx->sync_ctx, str, &ctx->mail.keywords);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append_c(str, '\n');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_KEYWORDS], str);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenstatic void mbox_sync_update_x_imap_base(struct mbox_sync_mail_context *ctx)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen{
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen struct mbox_sync_context *sync_ctx = ctx->sync_ctx;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen string_t *str;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen i_assert(sync_ctx->base_uid_validity != 0);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (!sync_ctx->dest_first_mail ||
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] == (size_t)-1)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen return;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (!ctx->imapbase_rewrite) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen /* uid-last might need updating, but we'll do it later by
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen writing it directly where needed. */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen return;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen /* a) keyword list changed, b) uid-last didn't use 10 digits */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str = t_str_new(200);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_printfa(str, "%u ", sync_ctx->base_uid_validity);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->last_uid_updated_value = sync_ctx->next_uid-1;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->last_uid_value_start_pos = str_len(str);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->imapbase_updated = TRUE;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_printfa(str, "%010u", ctx->last_uid_updated_value);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen keywords_append_all(ctx, str, 0);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append_c(str, '\n');
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_IMAPBASE], str);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenstatic void mbox_sync_update_x_uid(struct mbox_sync_mail_context *ctx)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen{
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen string_t *str;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (ctx->hdr_pos[MBOX_HDR_X_UID] == (size_t)-1 ||
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.uid == ctx->parsed_uid)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen return;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str = t_str_new(64);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_printfa(str, "%u\n", ctx->mail.uid);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_UID], str);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenstatic void mbox_sync_update_header_real(struct mbox_sync_mail_context *ctx)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen{
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen i_assert(ctx->mail.uid != 0 || ctx->mail.pseudo);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (!ctx->sync_ctx->keep_recent)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->mail.flags &= ~MAIL_RECENT;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_status(ctx);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_xstatus(ctx);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_xkeywords(ctx);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_x_imap_base(ctx);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_x_uid(ctx);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_add_missing_headers(ctx);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ctx->updated = TRUE;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenvoid mbox_sync_update_header(struct mbox_sync_mail_context *ctx)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen{
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen T_BEGIN {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mbox_sync_update_header_real(ctx);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen } T_END;
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen}
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainenstatic void
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainenmbox_sync_update_header_from_real(struct mbox_sync_mail_context *ctx,
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen const struct mbox_sync_mail *mail)
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen{
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen if ((ctx->mail.flags & STATUS_FLAGS_MASK) !=
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen (mail->flags & STATUS_FLAGS_MASK) ||
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen (ctx->mail.flags & MAIL_RECENT) != 0) {
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen ctx->mail.flags = (ctx->mail.flags & ~STATUS_FLAGS_MASK) |
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen (mail->flags & STATUS_FLAGS_MASK);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen if (!ctx->sync_ctx->keep_recent)
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen ctx->mail.flags &= ~MAIL_RECENT;
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen mbox_sync_update_status(ctx);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen }
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen if ((ctx->mail.flags & XSTATUS_FLAGS_MASK) !=
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen (mail->flags & XSTATUS_FLAGS_MASK)) {
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen ctx->mail.flags = (ctx->mail.flags & ~XSTATUS_FLAGS_MASK) |
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen (mail->flags & XSTATUS_FLAGS_MASK);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen mbox_sync_update_xstatus(ctx);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (!array_is_created(&mail->keywords) ||
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen array_count(&mail->keywords) == 0) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* no keywords for this mail */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (array_is_created(&ctx->mail.keywords)) {
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen array_clear(&ctx->mail.keywords);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen mbox_sync_update_xkeywords(ctx);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen }
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen } else if (!array_is_created(&ctx->mail.keywords)) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* adding first keywords */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen p_array_init(&ctx->mail.keywords,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->sync_ctx->mail_keyword_pool,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen array_count(&mail->keywords));
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen array_append_array(&ctx->mail.keywords,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen &mail->keywords);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen mbox_sync_update_xkeywords(ctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen } else if (!array_cmp(&ctx->mail.keywords, &mail->keywords)) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* keywords changed. */
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen array_clear(&ctx->mail.keywords);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen array_append_array(&ctx->mail.keywords,
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen &mail->keywords);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen mbox_sync_update_xkeywords(ctx);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen }
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen i_assert(ctx->mail.uid == 0 || ctx->mail.uid == mail->uid);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen ctx->mail.uid = mail->uid;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen mbox_sync_update_x_imap_base(ctx);
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen mbox_sync_update_x_uid(ctx);
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen mbox_sync_add_missing_headers(ctx);
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen}
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainenvoid mbox_sync_update_header_from(struct mbox_sync_mail_context *ctx,
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen const struct mbox_sync_mail *mail)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen T_BEGIN {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen mbox_sync_update_header_from_real(ctx, mail);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen } T_END;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen