@ -151,6 +151,7 @@ struct imap_cmd {
char to_trash ; /* we are storing to trash, not current. */
char to_trash ; /* we are storing to trash, not current. */
char create ; /* create the mailbox if we get an error which suggests so. */
char create ; /* create the mailbox if we get an error which suggests so. */
char failok ; /* Don't complain about NO response. */
char failok ; /* Don't complain about NO response. */
char lastuid ; /* querying the last UID in the mailbox. */
} param ;
} param ;
} ;
} ;
@ -1051,7 +1052,15 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
}
}
}
}
if ( body ) {
if ( ! uid ) {
assert ( ! body & & ! tuid & & ! msgid ) ;
// Ignore async flag updates for now.
} else if ( ( cmdp = ctx - > in_progress ) & & cmdp - > param . lastuid ) {
assert ( ! body & & ! tuid & & ! msgid ) ;
// Workaround for server not sending UIDNEXT and/or APPENDUID.
ctx - > gen . uidnext = uid + 1 ;
} else if ( body ) {
assert ( ! tuid & & ! msgid ) ;
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 ;
@ -1065,7 +1074,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 ;
} else if ( uid ) { /* ignore async flag updates for now */
} else {
/* XXX this will need sorting for out-of-order (multiple queries) */
/* XXX this will need sorting for out-of-order (multiple queries) */
cur = nfcalloc ( sizeof ( * cur ) ) ;
cur = nfcalloc ( sizeof ( * cur ) ) ;
* ctx - > msgapp = & cur - > gen ;
* ctx - > msgapp = & cur - > gen ;
@ -1081,8 +1090,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
memcpy ( cur - > gen . tuid , tuid , TUIDL ) ;
memcpy ( cur - > gen . tuid , tuid , TUIDL ) ;
else
else
cur - > gen . tuid [ 0 ] = 0 ;
cur - > gen . tuid [ 0 ] = 0 ;
if ( ctx - > gen . uidnext < = uid ) /* in case the server sends no UIDNEXT */
ctx - > gen . uidnext = uid + 1 ;
}
}
free_list ( list ) ;
free_list ( list ) ;
@ -2287,6 +2294,9 @@ imap_select_box( store_t *gctx, const char *name )
return DRV_OK ;
return DRV_OK ;
}
}
static void imap_open_box_p2 ( imap_store_t * , imap_cmd_t * , int ) ;
static void imap_open_box_p3 ( imap_store_t * , imap_cmd_t * , int ) ;
static void
static void
imap_open_box ( store_t * gctx ,
imap_open_box ( store_t * gctx ,
void ( * cb ) ( int sts , void * aux ) , void * aux )
void ( * cb ) ( int sts , void * aux ) , void * aux )
@ -2304,11 +2314,38 @@ imap_open_box( store_t *gctx,
INIT_IMAP_CMD ( imap_cmd_simple_t , cmd , cb , aux )
INIT_IMAP_CMD ( imap_cmd_simple_t , cmd , cb , aux )
cmd - > gen . param . failok = 1 ;
cmd - > gen . param . failok = 1 ;
imap_exec ( ctx , & cmd - > gen , imap_d one_sim pl e_box ,
imap_exec ( ctx , & cmd - > gen , imap_open _box_p2 ,
" SELECT \" % \\ s \" " , buf ) ;
" SELECT \" % \\ s \" " , buf ) ;
free ( buf ) ;
free ( buf ) ;
}
}
static void
imap_open_box_p2 ( imap_store_t * ctx , imap_cmd_t * gcmd , int response )
{
imap_cmd_simple_t * cmdp = ( imap_cmd_simple_t * ) gcmd ;
imap_cmd_simple_t * cmd ;
if ( response ! = RESP_OK | | ctx - > gen . uidnext ) {
imap_done_simple_box ( ctx , & cmdp - > gen , response ) ;
return ;
}
INIT_IMAP_CMD ( imap_cmd_simple_t , cmd , cmdp - > callback , cmdp - > callback_aux )
cmd - > gen . param . lastuid = 1 ;
imap_exec ( ctx , & cmd - > gen , imap_open_box_p3 ,
" UID FETCH *:* (UID) " ) ;
}
static void
imap_open_box_p3 ( imap_store_t * ctx , imap_cmd_t * gcmd , int response )
{
// This will happen if the box is empty.
if ( ! ctx - > gen . uidnext )
ctx - > gen . uidnext = 1 ;
imap_done_simple_box ( ctx , gcmd , response ) ;
}
/******************* imap_create_box *******************/
/******************* imap_create_box *******************/
static void
static void
@ -2443,7 +2480,7 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int seenuid, i
imap_submit_load ( ctx , buf , shifted_bit ( ctx - > gen . opts , OPEN_OLD_IDS , WantMsgids ) , sts ) ;
imap_submit_load ( ctx , buf , shifted_bit ( ctx - > gen . opts , OPEN_OLD_IDS , WantMsgids ) , sts ) ;
}
}
if ( maxuid = = INT_MAX )
if ( maxuid = = INT_MAX )
maxuid = ctx - > gen . uidnext ? ctx - > gen . uidnext - 1 : 0x7fffffff ;
maxuid = ctx - > gen . uidnext - 1 ;
if ( maxuid > = minuid ) {
if ( maxuid > = minuid ) {
imap_range_t ranges [ 3 ] ;
imap_range_t ranges [ 3 ] ;
ranges [ 0 ] . first = minuid ;
ranges [ 0 ] . first = minuid ;
@ -2720,6 +2757,7 @@ imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response
/******************* imap_find_new_msgs *******************/
/******************* imap_find_new_msgs *******************/
static void imap_find_new_msgs_p2 ( imap_store_t * , imap_cmd_t * , int ) ;
static void imap_find_new_msgs_p2 ( imap_store_t * , imap_cmd_t * , int ) ;
static void imap_find_new_msgs_p3 ( imap_store_t * , imap_cmd_t * , int ) ;
static void
static void
imap_find_new_msgs ( store_t * gctx , int newuid ,
imap_find_new_msgs ( store_t * gctx , int newuid ,
@ -2738,15 +2776,35 @@ static void
imap_find_new_msgs_p2 ( imap_store_t * ctx , imap_cmd_t * gcmd , int response )
imap_find_new_msgs_p2 ( imap_store_t * ctx , imap_cmd_t * gcmd , int response )
{
{
imap_cmd_find_new_t * cmdp = ( imap_cmd_find_new_t * ) gcmd ;
imap_cmd_find_new_t * cmdp = ( imap_cmd_find_new_t * ) gcmd ;
imap_cmd_simple _t * cmd ;
imap_cmd_find_new _t * cmd ;
if ( response ! = RESP_OK ) {
if ( response ! = RESP_OK ) {
imap_done_simple_box ( ctx , gcmd , response ) ;
imap_done_simple_box ( ctx , gcmd , response ) ;
return ;
return ;
}
}
ctx - > gen . uidnext = 0 ;
INIT_IMAP_CMD_X ( imap_cmd_find_new_t , cmd , cmdp - > gen . callback , cmdp - > gen . callback_aux )
cmd - > uid = cmdp - > uid ;
cmd - > gen . gen . param . lastuid = 1 ;
imap_exec ( ctx , & cmd - > gen . gen , imap_find_new_msgs_p3 ,
" UID FETCH *:* (UID) " ) ;
}
static void
imap_find_new_msgs_p3 ( imap_store_t * ctx , imap_cmd_t * gcmd , int response )
{
imap_cmd_find_new_t * cmdp = ( imap_cmd_find_new_t * ) gcmd ;
imap_cmd_simple_t * cmd ;
if ( response ! = RESP_OK | | ctx - > gen . uidnext < = cmdp - > uid ) {
imap_done_simple_box ( ctx , gcmd , response ) ;
return ;
}
INIT_IMAP_CMD ( imap_cmd_simple_t , cmd , cmdp - > gen . callback , cmdp - > gen . callback_aux )
INIT_IMAP_CMD ( imap_cmd_simple_t , cmd , cmdp - > gen . callback , cmdp - > gen . callback_aux )
imap_exec ( ( imap_store_t * ) ctx , & cmd - > gen , imap_done_simple_box ,
imap_exec ( ( imap_store_t * ) ctx , & cmd - > gen , imap_done_simple_box ,
" UID FETCH %d: " stringify ( INT_MAX ) " (UID BODY.PEEK[HEADER.FIELDS (X-TUID)]) " , cmdp - > uid ) ;
" UID FETCH %d:%d (UID BODY.PEEK[HEADER.FIELDS (X-TUID)]) " , cmdp - > uid , ctx - > gen . uidnext - 1 ) ;
}
}
/******************* imap_list_store *******************/
/******************* imap_list_store *******************/