fix UID assignment with some non-UIDPLUS servers
the seznam.cz IMAP server seems very eager to send UIDNEXT responses despite not supporting UIDPLUS. this doesn't appear to be a particularly sensible combination, but it's valid nonetheless. however, that means that we need to save the UIDNEXT value before we start storing messages, lest imap_find_new_msgs() will simply overlook them. we do that outside the driver, in an already present field - this actually makes the main path more consistent with the journal recovery path. analysis by Tomas Tintera <trosos@seznam.cz>. REFMAIL: 20141220215032.GA10115@kyvadlo.trosos.seznam.cz
This commit is contained in:
parent
958af473a0
commit
2fa75cf159
|
@ -192,7 +192,7 @@ struct driver {
|
|||
/* Index the messages which have newly appeared in the mailbox, including their
|
||||
* temporary UID headers. This is needed if store_msg() does not guarantee returning
|
||||
* a UID; otherwise the driver needs to implement only the OPEN_FIND flag. */
|
||||
void (*find_new_msgs)( store_t *ctx,
|
||||
void (*find_new_msgs)( store_t *ctx, int newuid,
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
|
||||
/* Add/remove the named flags to/from the given message. The message may be either
|
||||
|
|
|
@ -153,6 +153,11 @@ struct imap_cmd_out_uid {
|
|||
int out_uid;
|
||||
};
|
||||
|
||||
struct imap_cmd_find_new {
|
||||
struct imap_cmd_simple gen;
|
||||
int uid;
|
||||
};
|
||||
|
||||
struct imap_cmd_refcounted_state {
|
||||
void (*callback)( int sts, void *aux );
|
||||
void *callback_aux;
|
||||
|
@ -2158,28 +2163,30 @@ imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, struct imap_cmd *cmd, int resp
|
|||
static void imap_find_new_msgs_p2( imap_store_t *, struct imap_cmd *, int );
|
||||
|
||||
static void
|
||||
imap_find_new_msgs( store_t *gctx,
|
||||
imap_find_new_msgs( store_t *gctx, int newuid,
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd_simple *cmd;
|
||||
struct imap_cmd_find_new *cmd;
|
||||
|
||||
INIT_IMAP_CMD(imap_cmd_simple, cmd, cb, aux)
|
||||
imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_find_new_msgs_p2, "CHECK" );
|
||||
INIT_IMAP_CMD_X(imap_cmd_find_new, cmd, cb, aux)
|
||||
cmd->uid = newuid;
|
||||
imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_find_new_msgs_p2, "CHECK" );
|
||||
}
|
||||
|
||||
static void
|
||||
imap_find_new_msgs_p2( imap_store_t *ctx, struct imap_cmd *gcmd, int response )
|
||||
{
|
||||
struct imap_cmd_simple *cmdp = (struct imap_cmd_simple *)gcmd, *cmd;
|
||||
struct imap_cmd_find_new *cmdp = (struct imap_cmd_find_new *)gcmd;
|
||||
struct imap_cmd_simple *cmd;
|
||||
|
||||
if (response != RESP_OK) {
|
||||
imap_done_simple_box( ctx, gcmd, response );
|
||||
return;
|
||||
}
|
||||
INIT_IMAP_CMD(imap_cmd_simple, cmd, cmdp->callback, cmdp->callback_aux)
|
||||
INIT_IMAP_CMD(imap_cmd_simple, cmd, cmdp->gen.callback, cmdp->gen.callback_aux)
|
||||
imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_done_simple_box,
|
||||
"UID FETCH %d:1000000000 (UID BODY.PEEK[HEADER.FIELDS (X-TUID)])", ctx->gen.uidnext );
|
||||
"UID FETCH %d:1000000000 (UID BODY.PEEK[HEADER.FIELDS (X-TUID)])", cmdp->uid );
|
||||
}
|
||||
|
||||
/******************* imap_list *******************/
|
||||
|
|
|
@ -1292,7 +1292,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
}
|
||||
|
||||
static void
|
||||
maildir_find_new_msgs( store_t *gctx ATTR_UNUSED,
|
||||
maildir_find_new_msgs( store_t *gctx ATTR_UNUSED, int newuid ATTR_UNUSED,
|
||||
void (*cb)( int sts, void *aux ) ATTR_UNUSED, void *aux ATTR_UNUSED )
|
||||
{
|
||||
assert( !"maildir_find_new_msgs is not supposed to be called" );
|
||||
|
|
|
@ -1506,7 +1506,8 @@ box_loaded( int sts, void *aux )
|
|||
if (UseFSync)
|
||||
fdatasync( fileno( svars->jfp ) );
|
||||
for (t = 0; t < 2; t++) {
|
||||
Fprintf( svars->jfp, "%c %d\n", "{}"[t], svars->ctx[t]->uidnext );
|
||||
svars->newuid[t] = svars->ctx[t]->uidnext;
|
||||
Fprintf( svars->jfp, "%c %d\n", "{}"[t], svars->newuid[t] );
|
||||
for (tmsg = svars->ctx[1-t]->msgs; tmsg; tmsg = tmsg->next) {
|
||||
if ((srec = tmsg->srec) && srec->tuid[0]) {
|
||||
svars->new_total[t]++;
|
||||
|
@ -1604,7 +1605,7 @@ msgs_copied( sync_vars_t *svars, int t )
|
|||
|
||||
if (svars->state[t] & ST_FIND_NEW) {
|
||||
debug( "finding just copied messages on %s\n", str_ms[t] );
|
||||
svars->drv[t]->find_new_msgs( svars->ctx[t], msgs_found_new, AUX );
|
||||
svars->drv[t]->find_new_msgs( svars->ctx[t], svars->newuid[t], msgs_found_new, AUX );
|
||||
} else {
|
||||
msgs_new_done( svars, t );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user