make item tracking in parse_fetch_rsp() more uniform

amends 67ea5bea7 & a5a8783ea.
This commit is contained in:
Oswald Buddenhagen 2020-08-05 18:06:08 +02:00
parent ec47c90554
commit f099141e42
2 changed files with 20 additions and 18 deletions

View File

@ -59,6 +59,11 @@ typedef struct store_conf {
#define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */ #define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */
#define M_DEAD (1<<1) /* expunged */ #define M_DEAD (1<<1) /* expunged */
#define M_FLAGS (1<<2) /* flags fetched */ #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 #define TUIDL 12

View File

@ -1018,7 +1018,6 @@ parse_fetched_flags( list_t *list, uchar *flags, uchar *status )
warn( "IMAP warning: unknown system flag %s\n", list->val ); warn( "IMAP warning: unknown system flag %s\n", list->val );
flagok: ; flagok: ;
} }
*status |= M_FLAGS;
return 1; return 1;
} }
@ -1074,7 +1073,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
msg_data_t *msgdata; msg_data_t *msgdata;
imap_cmd_t *cmdp; imap_cmd_t *cmdp;
uchar mask = 0, status = 0; 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; time_t date = 0;
if (!is_list( list )) { 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" ); error( "IMAP error: unable to parse UID\n" );
return LIST_BAD; return LIST_BAD;
} }
continue; // This *is* the UID.
} else if (!strcmp( "FLAGS", name )) { } else if (!strcmp( "FLAGS", name )) {
if (!is_list( tmp )) { if (!is_list( tmp )) {
error( "IMAP error: unable to parse FLAGS\n" ); 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 )) if (!parse_fetched_flags( tmp->child, &mask, &status ))
return LIST_BAD; return LIST_BAD;
continue; // This may legitimately come without UID. status |= M_FLAGS;
} else if (!strcmp( "INTERNALDATE", name )) { } else if (!strcmp( "INTERNALDATE", name )) {
if (!is_atom( tmp )) { if (!is_atom( tmp )) {
error( "IMAP error: unable to parse INTERNALDATE\n" ); 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" ); error( "IMAP error: unable to parse INTERNALDATE format\n" );
return LIST_BAD; return LIST_BAD;
} }
status |= M_DATE;
} else if (!strcmp( "RFC822.SIZE", name )) { } else if (!strcmp( "RFC822.SIZE", name )) {
if (!is_atom( tmp ) || (size = strtoul( tmp->val, &ep, 10 ), *ep)) { if (!is_atom( tmp ) || (size = strtoul( tmp->val, &ep, 10 ), *ep)) {
error( "IMAP error: unable to parse RFC822.SIZE\n" ); error( "IMAP error: unable to parse RFC822.SIZE\n" );
return LIST_BAD; return LIST_BAD;
} }
status |= M_SIZE;
} else if (!strcmp( "BODY[]", name ) || !strcmp( "BODY[HEADER]", name )) { } else if (!strcmp( "BODY[]", name ) || !strcmp( "BODY[HEADER]", name )) {
if (!is_atom( tmp )) { if (!is_atom( tmp )) {
error( "IMAP error: unable to parse BODY[]\n" ); error( "IMAP error: unable to parse BODY[]\n" );
return LIST_BAD; return LIST_BAD;
} }
body = tmp; body = tmp;
status |= M_BODY;
} else if (!strcmp( "BODY[HEADER.FIELDS", name )) { } else if (!strcmp( "BODY[HEADER.FIELDS", name )) {
if (!is_list( tmp )) { if (!is_list( tmp )) {
bfail: bfail:
@ -1136,28 +1137,17 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
if (!is_atom( tmp )) if (!is_atom( tmp ))
goto bfail; goto bfail;
parse_fetched_header( tmp->val, uid, &tuid, &msgid, &msgid_len ); parse_fetched_header( tmp->val, uid, &tuid, &msgid, &msgid_len );
status |= M_HEADER;
} }
need_uid = 1;
} }
if (!uid) { if (!uid) {
if (need_uid) {
error( "IMAP error: received payload without UID\n" );
return LIST_BAD;
}
// Ignore async flag updates for now. // Ignore async flag updates for now.
status &= ~(M_FLAGS | M_RECENT);
} else if ((cmdp = ctx->in_progress) && cmdp->param.lastuid) { } 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. // Workaround for server not sending UIDNEXT and/or APPENDUID.
ctx->uidnext = uid + 1; ctx->uidnext = uid + 1;
} else if (body) { } else if (status & M_BODY) {
if (tuid || msgid) { // Only those that leak; ignore others.
error( "IMAP error: received extraneous data with full message\n" );
return LIST_BAD;
}
for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next) for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next)
if (cmdp->param.uid == uid) if (cmdp->param.uid == uid)
goto gotuid; goto gotuid;
@ -1171,6 +1161,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
msgdata->date = date; msgdata->date = date;
if (status & M_FLAGS) if (status & M_FLAGS)
msgdata->flags = mask; msgdata->flags = mask;
status &= ~(M_FLAGS | M_RECENT | M_BODY | M_DATE);
} else { } else {
cur = nfcalloc( sizeof(*cur) ); cur = nfcalloc( sizeof(*cur) );
*ctx->msgapp = &cur->gen; *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 ); cur->gen.msgid = nfstrndup( msgid, msgid_len );
if (tuid) if (tuid)
memcpy( cur->gen.tuid, tuid, TUIDL ); 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; return LIST_OK;