pop3: Moved CAPA response handling to pop3_state_capa_resp()
authorSteve Holme <steve_holme@hotmail.com>
Fri, 20 Dec 2013 07:12:12 +0000 (07:12 +0000)
committerSteve Holme <steve_holme@hotmail.com>
Thu, 19 Dec 2013 23:06:42 +0000 (23:06 +0000)
Similar to the processing of untagged CAPABILITY responses in IMAP and
multi-line EHLO responses in SMTP, moved the processing of multi-line
CAPA responses to pop3_state_capa_resp().

lib/pop3.c

index b8bf784..71873a7 100644 (file)
@@ -236,7 +236,6 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
                            int *resp)
 {
   struct pop3_conn *pop3c = &conn->proto.pop3c;
-  size_t wordlen;
 
   /* Do we have an error response? */
   if(len >= 4 && !memcmp("-ERR", line, 4)) {
@@ -248,75 +247,12 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
   /* Are we processing CAPA command responses? */
   if(pop3c->state == POP3_CAPA) {
     /* Do we have the terminating line? */
-    if(len >= 1 && !memcmp(line, ".", 1)) {
+    if(len >= 1 && !memcmp(line, ".", 1))
       *resp = '+';
+    else
+      *resp = '*';
 
-      return TRUE;
-    }
-
-    /* Does the server support the STLS capability? */
-    if(len >= 4 && !memcmp(line, "STLS", 4))
-      pop3c->tls_supported = TRUE;
-
-    /* Does the server support clear text authentication? */
-    else if(len >= 4 && !memcmp(line, "USER", 4))
-      pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
-
-    /* Does the server support APOP authentication? */
-    else if(len >= 4 && !memcmp(line, "APOP", 4))
-      pop3c->authtypes |= POP3_TYPE_APOP;
-
-    /* Does the server support SASL based authentication? */
-    else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
-      pop3c->authtypes |= POP3_TYPE_SASL;
-
-      /* Advance past the SASL keyword */
-      line += 5;
-      len -= 5;
-
-      /* 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++;
-
-        /* Test the word for a matching authentication mechanism */
-        if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
-          pop3c->authmechs |= SASL_MECH_LOGIN;
-        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
-          pop3c->authmechs |= SASL_MECH_PLAIN;
-        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
-          pop3c->authmechs |= SASL_MECH_CRAM_MD5;
-        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
-          pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
-        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
-          pop3c->authmechs |= SASL_MECH_GSSAPI;
-        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
-          pop3c->authmechs |= SASL_MECH_EXTERNAL;
-        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
-          pop3c->authmechs |= SASL_MECH_NTLM;
-        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
-          pop3c->authmechs |= SASL_MECH_XOAUTH2;
-
-        line += wordlen;
-        len -= wordlen;
-      }
-    }
-
-    return FALSE;
+    return TRUE;
   }
 
   /* Do we have a command or continuation response? */
@@ -755,26 +691,95 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
   CURLcode result = CURLE_OK;
   struct SessionHandle *data = conn->data;
   struct pop3_conn *pop3c = &conn->proto.pop3c;
+  const char *line = data->state.buffer;
+  size_t len = strlen(line);
+  size_t wordlen;
 
   (void)instate; /* no use for this yet */
 
-  if(pop3code != '+')
-    result = pop3_perform_user(conn);
-  else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
-    /* We don't have a SSL/TLS connection yet, but SSL is requested */
-    if(pop3c->tls_supported)
-      /* Switch to TLS connection now */
-      result = pop3_perform_starttls(conn);
-    else if(data->set.use_ssl == CURLUSESSL_TRY)
-      /* Fallback and carry on with authentication */
-      result = pop3_perform_authentication(conn);
-    else {
-      failf(data, "STLS not supported.");
-      result = CURLE_USE_SSL_FAILED;
+  /* Do we have a untagged response? */
+  if(pop3code == '*') {
+    /* Does the server support the STLS capability? */
+    if(len >= 4 && !memcmp(line, "STLS", 4))
+      pop3c->tls_supported = TRUE;
+
+    /* Does the server support clear text authentication? */
+    else if(len >= 4 && !memcmp(line, "USER", 4))
+      pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+
+    /* Does the server support APOP authentication? */
+    else if(len >= 4 && !memcmp(line, "APOP", 4))
+      pop3c->authtypes |= POP3_TYPE_APOP;
+
+    /* Does the server support SASL based authentication? */
+    else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
+      pop3c->authtypes |= POP3_TYPE_SASL;
+
+      /* Advance past the SASL keyword */
+      line += 5;
+      len -= 5;
+
+      /* 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++;
+
+        /* Test the word for a matching authentication mechanism */
+        if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
+          pop3c->authmechs |= SASL_MECH_LOGIN;
+        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
+          pop3c->authmechs |= SASL_MECH_PLAIN;
+        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
+          pop3c->authmechs |= SASL_MECH_CRAM_MD5;
+        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
+          pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
+        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
+          pop3c->authmechs |= SASL_MECH_GSSAPI;
+        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
+          pop3c->authmechs |= SASL_MECH_EXTERNAL;
+        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
+          pop3c->authmechs |= SASL_MECH_NTLM;
+        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
+          pop3c->authmechs |= SASL_MECH_XOAUTH2;
+
+        line += wordlen;
+        len -= wordlen;
+      }
+    }
+  }
+  else if(pop3code == '+') {
+    if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+      /* We don't have a SSL/TLS connection yet, but SSL is requested */
+      if(pop3c->tls_supported)
+        /* Switch to TLS connection now */
+        result = pop3_perform_starttls(conn);
+      else if(data->set.use_ssl == CURLUSESSL_TRY)
+        /* Fallback and carry on with authentication */
+        result = pop3_perform_authentication(conn);
+      else {
+        failf(data, "STLS not supported.");
+        result = CURLE_USE_SSL_FAILED;
+      }
     }
+    else
+      result = pop3_perform_authentication(conn);
   }
   else
-    result = pop3_perform_authentication(conn);
+    result = pop3_perform_user(conn);
 
   return result;
 }