mbox-sync-parse.c revision 1430ad83da079f60c8ad86abf398eaff9f34e97a
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen/* MD5 header summing logic was pretty much copy&pasted from popa3d by
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen Solar Designer */
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen#define IS_LWSP_LF(c) (IS_LWSP(c) || (c) == '\n')
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen int (*func)(struct mbox_sync_mail_context *ctx,
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainenstatic void parse_trailing_whitespace(struct mbox_sync_mail_context *ctx,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* the value may contain newlines. we can't count whitespace before
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen and after it as a single contiguous whitespace block, as that may
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen get us into situation where removing whitespace goes eg.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen " \n \n" -> " \n\n" which would then be treated as end of headers.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen that could probably be avoided by being careful, but as newlines
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen should never be there (we don't generate them), it's not worth the
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ctx->mail.offset = hdr->full_value_offset + i;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic enum mail_flags mbox_flag_find(struct mbox_flag_type *flags, char chr)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic void parse_status_flags(struct mbox_sync_mail_context *ctx,
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen mbox_flag_find(flags_list, hdr->full_value[i]);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic int parse_status(struct mbox_sync_mail_context *ctx,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen parse_status_flags(ctx, hdr, mbox_status_flags);
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen ctx->hdr_pos[MBOX_HDR_STATUS] = str_len(ctx->header);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic int parse_x_status(struct mbox_sync_mail_context *ctx,
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen parse_status_flags(ctx, hdr, mbox_xstatus_flags);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_STATUS] = str_len(ctx->header);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic int parse_x_imap_base(struct mbox_sync_mail_context *ctx,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen const char *str;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* Valid only in first message */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* <uid validity> <last uid> */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen str = t_strndup(hdr->full_value, hdr->full_value_len);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen while (pos < hdr->full_value_len && IS_LWSP_LF(hdr->full_value[pos]))
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->sync_ctx->base_uid_validity = uid_validity;
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen if (ctx->sync_ctx->next_uid <= ctx->sync_ctx->prev_msg_uid) {
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen /* broken, update */
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen ctx->sync_ctx->next_uid = ctx->sync_ctx->prev_msg_uid+1;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] = str_len(ctx->header);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen // FIXME: save keywords
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenstatic int parse_x_imap(struct mbox_sync_mail_context *ctx,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* this is the c-client style "FOLDER INTERNAL DATA" message.
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenstatic int parse_x_keywords(struct mbox_sync_mail_context *ctx,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen // FIXME: parse them
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = str_len(ctx->header);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenstatic int parse_x_uid(struct mbox_sync_mail_context *ctx,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* duplicate */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (hdr->full_value[i] < '0' || hdr->full_value[i] > '9')
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen value = value*10 + (hdr->full_value[i] - '0');
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* broken value */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* next_uid broken - fix it */
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen /* broken - UIDs must be growing */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* we're in mbox_sync_parse_match_mail() */
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen if (ctx->sync_ctx->dest_first_mail && !ctx->seen_imapbase) {
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen /* everything was good, except we can't have X-UID before
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen X-IMAPbase header (to keep c-client compatibility). keep
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen the UID, but when we're rewriting this makes sure the
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen X-UID is appended after X-IMAPbase. */
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen ctx->hdr_pos[MBOX_HDR_X_UID] = str_len(ctx->header);
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainenstatic int parse_content_length(struct mbox_sync_mail_context *ctx,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* duplicate */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (hdr->full_value[i] < '0' || hdr->full_value[i] > '9')
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen value = value*10 + (hdr->full_value[i] - '0');
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* broken value */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenstatic struct mbox_sync_header_func header_funcs[] = {
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen#define HEADER_FUNCS_COUNT (sizeof(header_funcs) / sizeof(*header_funcs))
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainenstatic int mbox_sync_bsearch_header_func_cmp(const void *p1, const void *p2)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen const struct mbox_sync_header_func *func = p2;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainenvoid mbox_sync_parse_next_mail(struct istream *input,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen struct mbox_sync_context *sync_ctx = ctx->sync_ctx;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen for (i = 0; i < MBOX_HDR_COUNT; i++)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen hdr_ctx = message_parse_header_init(input, NULL, FALSE);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_append_n(ctx->header, hdr->middle, hdr->middle_len);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* this header is broken, remove it */
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen mbox_md5_finish(mbox_md5_ctx, ctx->hdr_md5_sum);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if ((ctx->seq == 1 && sync_ctx->base_uid_validity == 0) ||
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen (ctx->seq > 1 && sync_ctx->dest_first_mail)) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* missing X-IMAPbase */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (ctx->seq == 1 && sync_ctx->update_base_uid_last != 0 &&
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen sync_ctx->update_base_uid_last > sync_ctx->base_uid_last) {
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen /* update uid-last field in X-IMAPbase */
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainenint mbox_sync_parse_match_mail(struct index_mailbox *ibox,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* we only wish to be sure that this mail actually is what we expect
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen it to be. If there's X-UID header, it's used. Otherwise use
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen the MD5 sum. */
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen hdr_ctx = message_parse_header_init(ibox->mbox_stream, NULL, FALSE);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0) {
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen mbox_md5_finish(mbox_md5_ctx, ctx.hdr_md5_sum);
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen /* match by X-UID header */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (mail_index_lookup_uid(view, seq, &uid) < 0) {
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen /* match by MD5 sum */