]> granicus.if.org Git - mutt/commitdiff
Restore IMAP postponed check in the wake of the buffy pipelining patch.
authorBrendan Cully <brendan@kublai.com>
Tue, 13 Dec 2005 06:52:23 +0000 (06:52 +0000)
committerBrendan Cully <brendan@kublai.com>
Tue, 13 Dec 2005 06:52:23 +0000 (06:52 +0000)
Fall back to NOOP if IDLE poll fails.
Allow for untagged messages when starting IDLE.
Free idata->cmdbuf in imap_free_idata.

imap/command.c
imap/imap.c
imap/imap.h
imap/imap_private.h
imap/util.c
postpone.c

index 8ba51fbc8752ee5c7ecc6a84bdaf8ab1fd74ced2..1562a769781ed92e96ae6c57a1c31bd75418677b 100644 (file)
@@ -719,9 +719,11 @@ static void cmd_parse_search (IMAP_DATA* idata, const char* s)
 static void cmd_parse_status (IMAP_DATA* idata, char* s)
 {
   char* mailbox;
+  char* value;
   BUFFY* inc;
   IMAP_MBOX mx;
   int count;
+  IMAP_STATUS status;
 
   dprint (2, (debugfile, "Handling STATUS\n"));
   
@@ -730,7 +732,55 @@ static void cmd_parse_status (IMAP_DATA* idata, char* s)
   *(s - 1) = '\0';
   
   imap_unmunge_mbox_name (mailbox);
-  
+  status.name = mailbox;
+
+  if (*s++ != '(')
+  {
+    dprint (1, (debugfile, "Error parsing STATUS\n"));
+    return;
+  }
+  while (*s && *s != ')')
+  {
+    value = imap_next_word (s);
+    count = strtol (value, &value, 10);
+
+    if (!ascii_strncmp ("MESSAGES", s, 8))
+    {
+      dprint (2, (debugfile, "%d messages in %s\n", count, mailbox));
+      status.messages = count;
+    }
+    else if (!ascii_strncmp ("RECENT", s, 6))
+    {
+      dprint (2, (debugfile, "%d recent in %s\n", count, mailbox));
+      status.recent = count;
+    }
+    else if (!ascii_strncmp ("UIDNEXT", s, 7))
+    {
+      dprint (2, (debugfile, "UIDNEXT for %s is %d\n", mailbox, count));
+      status.uidnext = count;
+    }
+    else if (!ascii_strncmp ("UIDVALIDITY", s, 11))
+    {
+      dprint (2, (debugfile, "UIDVALIDITY for %s is %d\n", mailbox, count));
+      status.uidvalidity = count;
+    }
+    else if (!ascii_strncmp ("UNSEEN", s, 6))
+    {
+      dprint (2, (debugfile, "%d unseen in %s\n", count, mailbox));
+      status.unseen = count;
+    }
+    
+    s = value;
+  }
+
+  /* caller is prepared to handle the result herself */
+  if (idata->cmddata)
+  {
+    memcpy (idata->cmddata, &status, sizeof (status));
+    return;
+  }
+
+  /* should perhaps move this code back to imap_buffy_check */
   for (inc = Incoming; inc; inc = inc->next)
   {
     if (inc->magic != M_IMAP)
@@ -743,38 +793,10 @@ static void cmd_parse_status (IMAP_DATA* idata, char* s)
     }
     
     if (mutt_account_match (&idata->conn->account, &mx.account) && mx.mbox
-        && strncmp (mailbox, mx.mbox, strlen (mailbox)) == 0)
+        && mutt_strncmp (mailbox, mx.mbox, strlen (mailbox)) == 0)
     {
-      if (*s++ != '(')
-      {
-        dprint (1, (debugfile, "Error parsing STATUS\n"));
-        FREE (&mx.mbox);
-        return;
-      }
-      
-      while (*s && *s != ')')
-      {
-        if (!ascii_strncmp ("RECENT", s, 6))
-        {
-          s = imap_next_word (s);
-          count = strtol (s, &s, 10);
-          dprint (2, (debugfile, "%d recent in %s\n", count, mx.mbox));
-          inc->new = count;
-        }
-        else if (!ascii_strncmp ("UNSEEN", s, 6))
-        {
-          s = imap_next_word (s);
-          count = strtol (s, &s, 10);
-          dprint (2, (debugfile, "%d unseen in %s\n", count, mx.mbox));
-        }
-        else if (!ascii_strncmp ("MESSAGES", s, 8))
-        {
-          s = imap_next_word (s);
-          count = strtol (s, &s, 10);
-          dprint (2, (debugfile, "%d messages in %s\n", count, mx.mbox));
-        }
-      }
-      
+      inc->new = status.recent;
+      FREE (&mx.mbox);
       return;
     }
 
index ba01c67429b526976c1a326425bba85966832e78..0732cd139c4358b155a21d232537cf0d485aceeb 100644 (file)
@@ -1190,7 +1190,10 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint, int force)
           || time(NULL) >= idata->lastread + ImapKeepalive))
   {
     imap_cmd_start (idata, "IDLE");
-    if (imap_cmd_step (idata) != IMAP_CMD_RESPOND)
+    do
+      result = imap_cmd_step (idata);
+    while (result == IMAP_CMD_CONTINUE);
+    if (result != IMAP_CMD_RESPOND)
     {
       dprint (1, (debugfile, "Error starting IDLE\n"));
       return -1;
@@ -1199,7 +1202,7 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint, int force)
   }
   if (idata->state == IMAP_IDLE)
   {
-    while (mutt_socket_poll (idata->conn) > 0)
+    while ((result = mutt_socket_poll (idata->conn)) > 0)
     {
       if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)
       {
@@ -1207,6 +1210,11 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint, int force)
         return -1;
       }
     }
+    if (result < 0)
+    {
+      dprint (1, (debugfile, "Poll failed, disabling IDLE\n"));
+      mutt_bit_unset (idata->capabilities, IDLE);
+    }
   }
   else if ((force || time(NULL) >= idata->lastread + Timeout)
       && imap_exec (idata, "NOOP", 0) != 0)
@@ -1229,13 +1237,13 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint, int force)
 }
 
 /* split path into (idata,mailbox name) */
-static int imap_buffy_split (const char* path, IMAP_DATA** hidata, char* buf, size_t blen)
+static int imap_get_mailbox (const char* path, IMAP_DATA** hidata, char* buf, size_t blen)
 {
   IMAP_MBOX mx;
 
   if (imap_parse_path (path, &mx))
   {
-    dprint (1, (debugfile, "imap_split_path: Error parsing %s\n", path));
+    dprint (1, (debugfile, "imap_get_mailbox: Error parsing %s\n", path));
     return -1;
   }
   if (!(*hidata = imap_conn_find (&(mx.account), option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0))
@@ -1278,7 +1286,7 @@ int imap_buffy_check (int force)
 
     mailbox->new = 0;
 
-    if (imap_buffy_split (mailbox->path, &idata, name, sizeof (name)) < 0)
+    if (imap_get_mailbox (mailbox->path, &idata, name, sizeof (name)) < 0)
       continue;
 
     /* Don't issue STATUS on the selected mailbox, it will be NOOPed or
@@ -1344,78 +1352,51 @@ int imap_buffy_check (int force)
   return buffies;
 }
 
-/* returns count of recent messages if new = 1, else count of total messages.
- * (useful for at least postponed function)
- * Question of taste: use RECENT or UNSEEN for new?
- *   0+   number of messages in mailbox
- *  -1    error while polling mailboxes
- */
-int imap_mailbox_check (char* path, int new)
+/* imap_status: returns count of messages in mailbox, or -1 on error */
+int imap_status (char* path)
 {
-  CONNECTION *conn;
   IMAP_DATA *idata;
   char buf[LONG_STRING];
   char mbox[LONG_STRING];
-  char mbox_unquoted[LONG_STRING];
-  int connflags = 0;
-  IMAP_MBOX mx;
+  IMAP_STATUS status;
   int rc;
-  BUFFY* buffy;
-  
-  if (imap_parse_path (path, &mx))
-    return -1;
+  int messages = 0;
 
-  /* If imap_passive is set, don't open a connection to check for new mail */
-  if (option (OPTIMAPPASSIVE))
-    connflags = M_IMAP_CONN_NONEW;
-
-  if (!(idata = imap_conn_find (&(mx.account), connflags)))
-  {
-    FREE (&mx.mbox);
+  if (imap_get_mailbox (path, &idata, buf, sizeof (buf)) < 0)
     return -1;
-  }
-  conn = idata->conn;
 
-  imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
-  FREE (&mx.mbox);
-
-  imap_munge_mbox_name (mbox, sizeof(mbox), buf);
-  strfcpy (mbox_unquoted, buf, sizeof (mbox_unquoted));
-
-  /* The draft IMAP implementor's guide warns againts using the STATUS
-   * command on a mailbox that you have selected 
-   */
-
-  if (mutt_strcmp (mbox_unquoted, idata->mailbox) == 0
-      || (ascii_strcasecmp (mbox_unquoted, "INBOX") == 0
-         && mutt_strcasecmp (mbox_unquoted, idata->mailbox) == 0))
-  {
-    strfcpy (buf, "NOOP", sizeof (buf));
-  }
+  if (mutt_strcmp (buf, idata->mailbox) == 0
+      || (ascii_strcasecmp (buf, "INBOX") == 0
+         && mutt_strcasecmp (buf, idata->mailbox) == 0))
+    /* We are in the folder we're polling - just return the mailbox count */
+    return idata->ctx->msgcount;
   else if (mutt_bit_isset(idata->capabilities,IMAP4REV1) ||
           mutt_bit_isset(idata->capabilities,STATUS))
-  {                            
-    snprintf (buf, sizeof (buf), "STATUS %s (%s)", mbox,
-      new ? "RECENT" : "MESSAGES");
+  {
+    imap_munge_mbox_name (mbox, sizeof(mbox), buf);
+    snprintf (buf, sizeof (buf), "STATUS %s (%s)", mbox, "MESSAGES");
+    imap_unmunge_mbox_name (mbox);
   }
   else
     /* Server does not support STATUS, and this is not the current mailbox.
      * There is no lightweight way to check recent arrivals */
     return -1;
 
+  idata->cmddata = &status;
   imap_cmd_start (idata, buf);
-
   do
-    rc = imap_cmd_step (idata);
-  while (rc == IMAP_CMD_CONTINUE);
-
-  for (buffy = Incoming; buffy; buffy = buffy->next)
   {
-    if (!strncmp (buffy->path, path, strlen (path)))
-      return buffy->new;
+    status.name = NULL;
+    if ((rc = imap_cmd_step (idata)) == IMAP_CMD_CONTINUE)
+    {
+      if (status.name && !mutt_strcmp (mbox, status.name))
+        messages = status.messages;
+    }
   }
+  while (rc == IMAP_CMD_CONTINUE);
+  idata->cmddata = NULL;
 
-  return 0;
+  return messages;
 }
 
 /* returns number of patterns in the search that should be done server-side
index b09d07b34184cc7427ab214157952439e179b5bb..145fdfa18f8ba416842c3047451dacedeb2cf7be 100644 (file)
@@ -40,7 +40,7 @@ int imap_open_mailbox_append (CONTEXT *ctx);
 int imap_sync_mailbox (CONTEXT *ctx, int expunge, int *index_hint);
 void imap_close_mailbox (CONTEXT *ctx);
 int imap_buffy_check (int force);
-int imap_mailbox_check (char *path, int new);
+int imap_status (char *path);
 int imap_search (CONTEXT* ctx, const pattern_t* pat);
 int imap_subscribe (char *path, int subscribe);
 int imap_complete (char* dest, size_t dlen, char* path);
index cd66c51742c7855e49494acebeeaa04087f76687..2a04d699d15fb23d31e737bac0900328ba4c2ab7 100644 (file)
@@ -150,6 +150,17 @@ typedef struct
   int noinferiors;
 } IMAP_NAMESPACE_INFO;
 
+typedef struct
+{
+  char* name;
+
+  unsigned int messages;
+  unsigned int recent;
+  unsigned int uidnext;
+  unsigned int uidvalidity;
+  unsigned int unseen;
+} IMAP_STATUS;
+
 /* IMAP command structure */
 typedef struct
 {
@@ -177,6 +188,8 @@ typedef struct
   time_t lastread; /* last time we read a command for the server */
   char* buf;
   unsigned int blen;
+  void* cmddata; /* if set, the response parser will store results for
+                  * complicated commands here. */
 
   /* command queue */
   IMAP_COMMAND cmds[IMAP_PIPELINE_DEPTH];
index ceea64e7abb08e0d19e237c3440fec31c1fbfd53..cfd65d3df0b9c77f83a90d935cf7d7ef9368f5b6 100644 (file)
@@ -261,6 +261,7 @@ void imap_free_idata (IMAP_DATA** idata)
   FREE (&(*idata)->capstr);
   mutt_free_list (&(*idata)->flags);
   FREE (&((*idata)->buf));
+  FREE (&((*idata)->cmdbuf));
   FREE (idata);
 }
 
index 25f4800b709a01183a594d78ed5afd6c625c4389..2795af328be483bb9ab837c2a2716f1c3b9b51f9 100644 (file)
@@ -89,7 +89,7 @@ int mutt_num_postponed (int force)
     {
       short newpc;
 
-      newpc = imap_mailbox_check (Postponed, 0);
+      newpc = imap_status (Postponed);
       if (newpc >= 0)
       {
        PostCount = newpc;