]> Pileus Git - ~andy/fetchmail/blobdiff - imap.c
Merge 'next' branch up to tag 'before-cpp'
[~andy/fetchmail] / imap.c
diff --git a/imap.c b/imap.c
index 867ce0084458ad4ba4ec0a403f0fb14b610da185..5e76801cf02b5acb39efe60c43e39d6d835d430c 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -176,7 +176,7 @@ static int imap_untagged_response(int sock, const char *buf)
     return(PS_SUCCESS);
 }
 
-static int imap_response(int sock, char *argbuf)
+static int imap_response(int sock, char *argbuf, struct RecvSplit *rs)
 /* parse command response */
 {
     char buf[MSGBUFSIZE+1];
@@ -185,7 +185,11 @@ static int imap_response(int sock, char *argbuf)
        int     ok;
        char    *cp;
 
-       if ((ok = gen_recv(sock, buf, sizeof(buf))))
+       if (rs)
+           ok = gen_recv_split(sock, buf, sizeof(buf), rs);
+       else
+           ok = gen_recv(sock, buf, sizeof(buf));
+       if (ok != PS_SUCCESS)
            return(ok);
 
        /* all tokens in responses are caseblind */
@@ -266,7 +270,7 @@ static int imap_ok(int sock, char *argbuf)
 {
     int ok;
 
-    while ((ok = imap_response(sock, argbuf)) == PS_UNTAGGED)
+    while ((ok = imap_response(sock, argbuf, NULL)) == PS_UNTAGGED)
        ; /* wait for the tagged response */
     return(ok);
 }
@@ -711,20 +715,16 @@ static int imap_idle(int sock)
     }
 
     /* restore normal timeout value */
-    set_timeout(0);
     mytimeout = saved_timeout;
     stage = STAGE_GETRANGE;
 
     return(ok);
 }
 
-/* maximum number of numbers we can process in "SEARCH" response */
-# define IMAP_SEARCH_MAX 1000
-
 static int imap_search(int sock, struct query *ctl, int count)
 /* search for unseen messages */
 {
-    int ok, first, last;
+    int ok;
     char buf[MSGBUFSIZE+1], *cp;
 
     /* Don't count deleted messages. Enabled only for IMAP4 servers or
@@ -734,29 +734,20 @@ static int imap_search(int sock, struct query *ctl, int count)
     flag skipdeleted = ctl->keep;
     const char *undeleted;
 
-    /* Skip range search if there are less than or equal to
-     * IMAP_SEARCH_MAX mails. */
-    flag skiprangesearch = (count <= IMAP_SEARCH_MAX);
+    /* structure to keep the end portion of the incomplete response */
+    struct RecvSplit rs;
 
     /* startcount is higher than count so that if there are no
      * unseen messages, imap_getsizes() will not need to do
      * anything! */
     startcount = count + 1;
 
-    for (first = 1, last = IMAP_SEARCH_MAX; first <= count; first += IMAP_SEARCH_MAX, last += IMAP_SEARCH_MAX)
+    for (;;)
     {
-       if (last > count)
-           last = count;
-
-restartsearch:
        undeleted = (skipdeleted ? " UNDELETED" : "");
-       if (skiprangesearch)
-           gen_send(sock, "SEARCH UNSEEN%s", undeleted);
-       else if (last == first)
-           gen_send(sock, "SEARCH %d UNSEEN%s", last, undeleted);
-       else
-           gen_send(sock, "SEARCH %d:%d UNSEEN%s", first, last, undeleted);
-       while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+       gen_send(sock, "SEARCH UNSEEN%s", undeleted);
+       gen_recv_split_init("* SEARCH", &rs);
+       while ((ok = imap_response(sock, buf, &rs)) == PS_UNTAGGED)
        {
            if ((cp = strstr(buf, "* SEARCH")))
            {
@@ -788,39 +779,25 @@ restartsearch:
                }
            }
        }
-       /* if there is a protocol error on the first loop, try a
-        * different search command */
-       if (ok == PS_ERROR && first == 1)
+       if (ok != PS_ERROR) /* success or non-protocol error */
+           return(ok);
+
+       /* there is a protocol error. try a different search command. */
+       if (skipdeleted)
        {
-           if (skipdeleted)
-           {
-               /* retry with "SEARCH 1:1000 UNSEEN" */
-               skipdeleted = FALSE;
-               goto restartsearch;
-           }
-           if (!skiprangesearch)
-           {
-               /* retry with "SEARCH UNSEEN" */
-               skiprangesearch = TRUE;
-               goto restartsearch;
-           }
-           /* try with "FETCH 1:n FLAGS" */
-           goto fetchflags;
+           /* retry with "SEARCH UNSEEN" */
+           skipdeleted = FALSE;
+           continue;
        }
-       if (ok != PS_SUCCESS)
-           return(ok);
-       /* loop back only when searching in range */
-       if (skiprangesearch)
-           break;
+       /* try with "FETCH 1:n FLAGS" */
+       break;
     }
-    return(PS_SUCCESS);
 
-fetchflags:
     if (count == 1)
        gen_send(sock, "FETCH %d FLAGS", count);
     else
        gen_send(sock, "FETCH %d:%d FLAGS", 1, count);
-    while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+    while ((ok = imap_response(sock, buf, NULL)) == PS_UNTAGGED)
     {
        unsigned int num;
        int consumed;
@@ -1031,7 +1008,7 @@ static int imap_getpartialsizes(int sock, int first, int last, int *sizes)
        gen_send(sock, "FETCH %d:%d RFC822.SIZE", first, last);
     else /* no unseen messages! */
        return(PS_SUCCESS);
-    while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+    while ((ok = imap_response(sock, buf, NULL)) == PS_UNTAGGED)
     {
        unsigned int size;
        int num;
@@ -1119,7 +1096,7 @@ static int imap_fetch_headers(int sock, struct query *ctl,int number,int *lenp)
     gen_send(sock, "FETCH %d RFC822.HEADER", number);
 
     /* looking for FETCH response */
-    if ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+    if ((ok = imap_response(sock, buf, NULL)) == PS_UNTAGGED)
     {
                int consumed;
        /* expected response formats:
@@ -1270,6 +1247,22 @@ static int imap_delete(int sock, struct query *ctl, int number)
 /* set delete flag for given message */
 {
     int        ok;
+    /* Select which flags to set on message deletion: */
+    const char delflags_seen[] = "\\Seen \\Deleted";
+    const char delflags_unseen[] = "\\Deleted";
+    static const char *delflags;
+    /* Which environment variable to look for: */
+    const char dis_env[] = "FETCHMAIL_IMAP_DELETED_REMAINS_UNSEEN";
+
+    if (!delflags) {
+       char *tmp;
+       if ((tmp = getenv(dis_env)) != NULL && *tmp) {
+           delflags = delflags_unseen;
+       } else {
+           /* DEFAULT since many fetchmail versions <= 6.3.X */
+           delflags = delflags_seen;
+       }
+    }
 
     (void)ctl;
     /* expunges change the fetch numbers */