From f099141e4285173f79725635f31c8b0e0ce710b6 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 5 Aug 2020 18:06:08 +0200 Subject: [PATCH] make item tracking in parse_fetch_rsp() more uniform amends 67ea5bea7 & a5a8783ea. --- src/driver.h | 5 +++++ src/drv_imap.c | 33 +++++++++++++++------------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/driver.h b/src/driver.h index 575ec86..8aeba48 100644 --- a/src/driver.h +++ b/src/driver.h @@ -59,6 +59,11 @@ typedef struct store_conf { #define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */ #define M_DEAD (1<<1) /* expunged */ #define M_FLAGS (1<<2) /* flags fetched */ +// The following are only for IMAP FETCH response parsing +#define M_DATE (1<<3) +#define M_SIZE (1<<4) +#define M_BODY (1<<5) +#define M_HEADER (1<<6) #define TUIDL 12 diff --git a/src/drv_imap.c b/src/drv_imap.c index ec4c716..27d43ec 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1018,7 +1018,6 @@ parse_fetched_flags( list_t *list, uchar *flags, uchar *status ) warn( "IMAP warning: unknown system flag %s\n", list->val ); flagok: ; } - *status |= M_FLAGS; return 1; } @@ -1074,7 +1073,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) msg_data_t *msgdata; imap_cmd_t *cmdp; uchar mask = 0, status = 0; - uint uid = 0, need_uid = 0, size = 0, msgid_len = 0; + uint uid = 0, size = 0, msgid_len = 0; time_t date = 0; if (!is_list( list )) { @@ -1094,7 +1093,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) error( "IMAP error: unable to parse UID\n" ); return LIST_BAD; } - continue; // This *is* the UID. } else if (!strcmp( "FLAGS", name )) { if (!is_list( tmp )) { error( "IMAP error: unable to parse FLAGS\n" ); @@ -1102,7 +1100,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) } if (!parse_fetched_flags( tmp->child, &mask, &status )) return LIST_BAD; - continue; // This may legitimately come without UID. + status |= M_FLAGS; } else if (!strcmp( "INTERNALDATE", name )) { if (!is_atom( tmp )) { error( "IMAP error: unable to parse INTERNALDATE\n" ); @@ -1112,17 +1110,20 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) error( "IMAP error: unable to parse INTERNALDATE format\n" ); return LIST_BAD; } + status |= M_DATE; } else if (!strcmp( "RFC822.SIZE", name )) { if (!is_atom( tmp ) || (size = strtoul( tmp->val, &ep, 10 ), *ep)) { error( "IMAP error: unable to parse RFC822.SIZE\n" ); return LIST_BAD; } + status |= M_SIZE; } else if (!strcmp( "BODY[]", name ) || !strcmp( "BODY[HEADER]", name )) { if (!is_atom( tmp )) { error( "IMAP error: unable to parse BODY[]\n" ); return LIST_BAD; } body = tmp; + status |= M_BODY; } else if (!strcmp( "BODY[HEADER.FIELDS", name )) { if (!is_list( tmp )) { bfail: @@ -1136,28 +1137,17 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) if (!is_atom( tmp )) goto bfail; parse_fetched_header( tmp->val, uid, &tuid, &msgid, &msgid_len ); + status |= M_HEADER; } - need_uid = 1; } if (!uid) { - if (need_uid) { - error( "IMAP error: received payload without UID\n" ); - return LIST_BAD; - } // Ignore async flag updates for now. + status &= ~(M_FLAGS | M_RECENT); } else if ((cmdp = ctx->in_progress) && cmdp->param.lastuid) { - if (need_uid || (status & M_FLAGS)) { - error( "IMAP error: received extraneous data in response to UID query\n" ); - return LIST_BAD; - } // Workaround for server not sending UIDNEXT and/or APPENDUID. ctx->uidnext = uid + 1; - } else if (body) { - if (tuid || msgid) { // Only those that leak; ignore others. - error( "IMAP error: received extraneous data with full message\n" ); - return LIST_BAD; - } + } else if (status & M_BODY) { for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next) if (cmdp->param.uid == uid) goto gotuid; @@ -1171,6 +1161,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) msgdata->date = date; if (status & M_FLAGS) msgdata->flags = mask; + status &= ~(M_FLAGS | M_RECENT | M_BODY | M_DATE); } else { cur = nfcalloc( sizeof(*cur) ); *ctx->msgapp = &cur->gen; @@ -1183,6 +1174,12 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) cur->gen.msgid = nfstrndup( msgid, msgid_len ); if (tuid) memcpy( cur->gen.tuid, tuid, TUIDL ); + status &= ~(M_FLAGS | M_RECENT | M_SIZE | M_HEADER); + } + + if (status) { + error( "IMAP error: received extraneous data in FETCH response\n" ); + return LIST_BAD; } return LIST_OK;