mbox-sync-parse.c revision 9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "lib.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "buffer.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "istream.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "str.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "write-full.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "message-parser.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "mail-index.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "mbox-sync-private.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include <stdlib.h>
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#define IS_LWSP_LF(c) (IS_LWSP(c) || (c) == '\n')
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstruct mbox_flag_type mbox_status_flags[] = {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { 'R', MAIL_SEEN },
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch { 'O', MBOX_NONRECENT },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { 0, 0 }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen};
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstruct mbox_flag_type mbox_xstatus_flags[] = {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { 'A', MAIL_ANSWERED },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { 'F', MAIL_FLAGGED },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { 'T', MAIL_DRAFT },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { 'D', MAIL_DELETED },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { 0, 0 }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen};
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
fe779565bda49a0ed0476724819c6e3c1340c94bTimo Sirainenstruct header_func {
fe779565bda49a0ed0476724819c6e3c1340c94bTimo Sirainen const char *header;
fe779565bda49a0ed0476724819c6e3c1340c94bTimo Sirainen int (*func)(struct mbox_sync_mail_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_line *hdr);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen};
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstatic enum mail_flags mbox_flag_find(struct mbox_flag_type *flags, char chr)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen int i;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = 0; flags[i].chr != 0; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (flags[i].chr == chr)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return flags[i].flag;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return 0;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic void parse_status_flags(struct mbox_sync_mail_context *ctx,
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch struct message_header_line *hdr,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct mbox_flag_type *flags_list)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen size_t i;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = 0; i < hdr->full_value_len; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->mail.flags |=
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mbox_flag_find(flags_list, hdr->full_value[i]);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic int parse_status(struct mbox_sync_mail_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_line *hdr)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen parse_status_flags(ctx, hdr, mbox_status_flags);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->hdr_pos[MBOX_HDR_STATUS] = str_len(ctx->header);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic int parse_x_status(struct mbox_sync_mail_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_line *hdr)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen parse_status_flags(ctx, hdr, mbox_xstatus_flags);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_STATUS] = str_len(ctx->header);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Boschstatic int parse_x_imap_base(struct mbox_sync_mail_context *ctx,
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch struct message_header_line *hdr)
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch{
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch const char *str;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen char *end;
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch size_t pos;
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch uint32_t uid_validity, uid_last;
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch if (ctx->seq != 1 || ctx->seen_imapbase) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* Valid only in first message */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return FALSE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen /* <uid validity> <last uid> */
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen t_push();
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen str = t_strndup(hdr->full_value, hdr->full_value_len);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen uid_validity = strtoul(str, &end, 10);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen uid_last = strtoul(end, &end, 10);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen pos = end - str;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen t_pop();
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch while (pos < hdr->full_value_len && IS_LWSP_LF(hdr->full_value[pos]))
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch pos++;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (uid_validity == 0) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* broken */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return FALSE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (pos == hdr->full_value_len)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen // FIXME: save keywords
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (ctx->sync_ctx->base_uid_validity == 0) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->sync_ctx->base_uid_validity = uid_validity;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->sync_ctx->base_uid_last = uid_last;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->sync_ctx->next_uid = uid_last+1;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] = str_len(ctx->header);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->seen_imapbase = TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic int parse_x_keywords(struct mbox_sync_mail_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_line *hdr)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen size_t i, space = 0;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = hdr->full_value_len; i > 0; i--) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (!IS_LWSP_LF(hdr->full_value[i-1]))
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen break;
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody space++;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (space > ctx->mail.space) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->mail.offset = ctx->hdr_offset +
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen hdr->full_value_offset + i;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->mail.space = space;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen // FIXME: parse them
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = str_len(ctx->header);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic int parse_x_uid(struct mbox_sync_mail_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_line *hdr)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen uint32_t value = 0;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen size_t i, space_pos, extra_space = 0;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (ctx->mail.uid != 0) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* duplicate */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return FALSE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = 0; i < hdr->full_value_len; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (hdr->full_value[i] < '0' || hdr->full_value[i] > '9')
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen break;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen value = value*10 + (hdr->full_value[i] - '0');
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen space_pos = i;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (; i < hdr->full_value_len; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (!IS_LWSP_LF(hdr->full_value[i])) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* broken value */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return FALSE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen extra_space++;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (value <= ctx->sync_ctx->prev_msg_uid) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* broken - UIDs must be growing */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return FALSE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->sync_ctx->prev_msg_uid = value;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_UID] = str_len(ctx->header);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->mail.uid = value;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (extra_space != 0 && ctx->mail.space == 0) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* set it only if X-Keywords hasn't been seen. spaces in X-UID
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen should be removed when writing X-Keywords. */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->mail.offset = ctx->hdr_offset +
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen hdr->full_value_offset + space_pos;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->mail.space = extra_space;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic int parse_content_length(struct mbox_sync_mail_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_line *hdr)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen uoff_t value = 0;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen size_t i;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (ctx->content_length != (uoff_t)-1) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* duplicate */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return FALSE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = 0; i < hdr->full_value_len; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (hdr->full_value[i] < '0' || hdr->full_value[i] > '9')
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen break;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen value = value*10 + (hdr->full_value[i] - '0');
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (; i < hdr->full_value_len; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (!IS_LWSP_LF(hdr->full_value[i])) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* broken value */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return FALSE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->content_length = value;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic struct header_func header_funcs[] = {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch { "Content-Length", parse_content_length },
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch { "Status", parse_status },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { "X-IMAPbase", parse_x_imap_base },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { "X-Keywords", parse_x_keywords },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { "X-Status", parse_x_status },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { "X-UID", parse_x_uid },
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen { NULL, NULL }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen};
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic struct header_func *header_func_find(const char *header)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen int i;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = 0; header_funcs[i].header != NULL; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (strcasecmp(header_funcs[i].header, header) == 0)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return &header_funcs[i];
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return NULL;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenvoid mbox_sync_parse_next_mail(struct istream *input,
8855b8b57050fe3b6dc3f19283488512fae98648Timo Sirainen struct mbox_sync_mail_context *ctx)
8855b8b57050fe3b6dc3f19283488512fae98648Timo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_parser_ctx *hdr_ctx;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct message_header_line *hdr;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct header_func *func;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen size_t line_start_pos;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen int i;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->hdr_offset = ctx->mail.offset;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->header_first_change = (size_t)-1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->header_last_change = 0;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch for (i = 0; i < MBOX_HDR_COUNT; i++)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->hdr_pos[i] = (size_t)-1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->content_length = (uoff_t)-1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch str_truncate(ctx->header, 0);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch line_start_pos = 0;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch hdr_ctx = message_parse_header_init(input, NULL);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch while ((hdr = message_parse_header_next(hdr_ctx)) != NULL) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (hdr->eoh) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->have_eoh = TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch break;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (!hdr->continued) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen line_start_pos = str_len(ctx->header);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen str_append(ctx->header, hdr->name);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen str_append(ctx->header, ": ");
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch func = header_func_find(hdr->name);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (func != NULL) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (hdr->continues)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch hdr->use_full_value = TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch else if (!func->func(ctx, hdr)) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* this header is broken, remove it */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->need_rewrite = TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch str_truncate(ctx->header, line_start_pos);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (ctx->header_first_change == (size_t)-1) {
d8aa10df6d1dae56d3aa485708a34d74e9e31e79Stephan Bosch ctx->header_first_change =
d8aa10df6d1dae56d3aa485708a34d74e9e31e79Stephan Bosch line_start_pos;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch continue;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch buffer_append(ctx->header, hdr->full_value,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch hdr->full_value_len);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (!hdr->no_newline)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch str_append_c(ctx->header, '\n');
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch message_parse_header_deinit(hdr_ctx);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (ctx->seq == 1 && ctx->sync_ctx->base_uid_validity == 0) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* missing X-IMAPbase */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->need_rewrite = TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (ctx->mail.uid == 0) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* missing X-UID */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->need_rewrite = TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->body_offset = input->v_offset;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch