commit 72be55b0e3b3ccaca8c2e5ee1c0706bf41388900
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Sat Jan 28 19:19:41 2017 +0100

    add fallbacks for determining UIDNEXT
    
    if the server sends no UIDNEXT, do an initial FETCH to query the UID of
    the last message.
    
    same if the server sends no APPENDUID.
    
    this allows us to remove the arbitrary limitation of the UID range to
    INT_MAX, at the cost of additional round-trips.

 src/drv_imap.c | 74 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 66 insertions(+), 8 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index adffc38..336bea1 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -151,6 +151,7 @@ struct imap_cmd {
                char to_trash; /* we are storing to trash, not current. */
                char create; /* create the mailbox if we get an error which 
suggests so. */
                char failok; /* Don't complain about NO response. */
+               char lastuid; /* querying the last UID in the mailbox. */
        } 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)
                        if (cmdp->param.uid == uid)
                                goto gotuid;
@@ -1065,7 +1074,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;
-       } else if (uid) { /* ignore async flag updates for now */
+       } else {
                /* XXX this will need sorting for out-of-order (multiple 
queries) */
                cur = nfcalloc( sizeof(*cur) );
                *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 );
                else
                        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 );
@@ -2287,6 +2294,9 @@ imap_select_box( store_t *gctx, const char *name )
        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
 imap_open_box( store_t *gctx,
                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)
        cmd->gen.param.failok = 1;
-       imap_exec( ctx, &cmd->gen, imap_done_simple_box,
+       imap_exec( ctx, &cmd->gen, imap_open_box_p2,
                   "SELECT \"%\\s\"", 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 *******************/
 
 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 );
                }
                if (maxuid == INT_MAX)
-                       maxuid = ctx->gen.uidnext ? ctx->gen.uidnext - 1 : 
0x7fffffff;
+                       maxuid = ctx->gen.uidnext - 1;
                if (maxuid >= minuid) {
                        imap_range_t ranges[3];
                        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 *******************/
 
 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
 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_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) {
                imap_done_simple_box( ctx, gcmd, response );
                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)
        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 *******************/

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to