imap: Moved CAPABILITY response handling to imap_state_capability_resp()
authorJiri Hruska <jirka@fud.cz>
Tue, 26 Feb 2013 17:10:54 +0000 (18:10 +0100)
committerSteve Holme <steve_holme@hotmail.com>
Tue, 26 Feb 2013 19:51:16 +0000 (19:51 +0000)
Introduced similar handling to the FETCH responses, where even the
untagged data responses are handled by the response handler of the
individual state.

lib/imap.c

index 845d7dd..7738e63 100644 (file)
@@ -323,16 +323,14 @@ static char* imap_atom(const char* str)
   return newstr;
 }
 
-/* Function that checks for an ending IMAP status code at the start of the
-   given string but also detects various capabilities from the CAPABILITY
-   response including the supported authentication mechanisms. */
+/* Function that checks whether the given string is a valid tagged, untagged
+   or continuation response which can be processed by the response handler. */
 static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
                            int *resp)
 {
   struct imap_conn *imapc = &conn->proto.imapc;
   const char *id = imapc->resptag;
   size_t id_len = strlen(id);
-  size_t wordlen;
 
   /* Do we have a tagged command response? */
   if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') {
@@ -355,77 +353,19 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
 
   /* Do we have an untagged command response */
   if(len >= 2 && !memcmp("* ", line, 2)) {
-    /* Are we processing CAPABILITY command data? */
-    if(imapc->state == IMAP_CAPABILITY) {
-      line += 2;
-      len -= 2;
-
-      /* Loop through the data line */
-      for(;;) {
-        while(len &&
-              (*line == ' ' || *line == '\t' ||
-               *line == '\r' || *line == '\n')) {
-
-          line++;
-          len--;
-        }
-
-        if(!len)
-          break;
-
-        /* Extract the word */
-        for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
-              line[wordlen] != '\t' && line[wordlen] != '\r' &&
-              line[wordlen] != '\n';)
-          wordlen++;
-
-        /* Does the server support the STARTTLS capability? */
-        if(wordlen == 8 && !memcmp(line, "STARTTLS", 8))
-          imapc->tls_supported = TRUE;
-
-        /* Has the server explicitly disabled clear text authentication? */
-        else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13))
-          imapc->login_disabled = TRUE;
-
-        /* Does the server support the SASL-IR capability? */
-        else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7))
-          imapc->ir_supported = TRUE;
-
-        /* Do we have a SASL based authentication mechanism? */
-        else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) {
-          line += 5;
-          len -= 5;
-          wordlen -= 5;
-
-          /* Test the word for a matching authentication mechanism */
-          if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
-            imapc->authmechs |= SASL_MECH_LOGIN;
-          if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
-            imapc->authmechs |= SASL_MECH_PLAIN;
-          else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
-            imapc->authmechs |= SASL_MECH_CRAM_MD5;
-          else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
-            imapc->authmechs |= SASL_MECH_DIGEST_MD5;
-          else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
-            imapc->authmechs |= SASL_MECH_GSSAPI;
-          else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
-            imapc->authmechs |= SASL_MECH_EXTERNAL;
-          else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
-            imapc->authmechs |= SASL_MECH_NTLM;
-        }
-
-        line += wordlen;
-        len -= wordlen;
-      }
-
-      return FALSE;
+    switch(imapc->state) {
+      /* States which are interested in untagged responses */
+      case IMAP_CAPABILITY:
+      case IMAP_FETCH:
+        *resp = '*';
+        break;
+      /* Ignore other untagged responses */
+      default:
+        return FALSE;
     }
-    /* Are we processing FETCH command responses? */
-    else if(imapc->state == IMAP_FETCH) {
-      *resp = '*';
 
-      return TRUE;
-    }
+    return TRUE;
   }
 
   /* Do we have a continuation response? */
@@ -755,10 +695,71 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
   CURLcode result = CURLE_OK;
   struct SessionHandle *data = conn->data;
   struct imap_conn *imapc = &conn->proto.imapc;
+  const char *line = data->state.buffer;
+  size_t wordlen;
 
   (void)instate; /* no use for this yet */
 
-  if(imapcode != 'O')
+  /* Do we have a untagged response? */
+  if(imapcode == '*') {
+    line += 2;
+
+    /* Loop through the data line */
+    for(;;) {
+      while(*line &&
+            (*line == ' ' || *line == '\t' ||
+              *line == '\r' || *line == '\n')) {
+
+        line++;
+      }
+
+      if(!*line)
+        break;
+
+      /* Extract the word */
+      for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' &&
+            line[wordlen] != '\t' && line[wordlen] != '\r' &&
+            line[wordlen] != '\n';)
+        wordlen++;
+
+      /* Does the server support the STARTTLS capability? */
+      if(wordlen == 8 && !memcmp(line, "STARTTLS", 8))
+        imapc->tls_supported = TRUE;
+
+      /* Has the server explicitly disabled clear text authentication? */
+      else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13))
+        imapc->login_disabled = TRUE;
+
+      /* Does the server support the SASL-IR capability? */
+      else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7))
+        imapc->ir_supported = TRUE;
+
+      /* Do we have a SASL based authentication mechanism? */
+      else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) {
+        line += 5;
+        wordlen -= 5;
+
+        /* Test the word for a matching authentication mechanism */
+        if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
+          imapc->authmechs |= SASL_MECH_LOGIN;
+        if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
+          imapc->authmechs |= SASL_MECH_PLAIN;
+        else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
+          imapc->authmechs |= SASL_MECH_CRAM_MD5;
+        else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
+          imapc->authmechs |= SASL_MECH_DIGEST_MD5;
+        else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
+          imapc->authmechs |= SASL_MECH_GSSAPI;
+        else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
+          imapc->authmechs |= SASL_MECH_EXTERNAL;
+        else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
+          imapc->authmechs |= SASL_MECH_NTLM;
+      }
+
+      line += wordlen;
+    }
+  }
+  else if(imapcode != 'O')
     result = imap_state_login(conn);
   else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
     /* We don't have a SSL/TLS connection yet, but SSL is requested */