]> granicus.if.org Git - curl/commitdiff
imap: Changed response tag generation to be completely unique
authorSteve Holme <steve_holme@hotmail.com>
Thu, 7 Feb 2013 00:18:23 +0000 (00:18 +0000)
committerSteve Holme <steve_holme@hotmail.com>
Thu, 7 Feb 2013 00:18:23 +0000 (00:18 +0000)
Updated the automatic response tag generation to follow the examples
given in RC3501, which list a 4 character string such as A001, A002,
etc.

As a unique identifier should be generated for each command the string
generation is based on the connection id and the incrementing command
id.

lib/imap.c
lib/imap.h
tests/data/test1321
tests/data/test801

index 5f82782aea2cb7f2e230982f8c064939b9c11d4c..72774c08947cee05180d5b0a8266aa1217e3168c 100644 (file)
@@ -211,39 +211,31 @@ static const struct Curl_handler Curl_handler_imaps_proxy = {
  *
  * Designed to never block.
  */
-static CURLcode imap_sendf(struct connectdata *conn,
-                           const char *idstr, /* command id to wait for */
-                           const char *fmt, ...)
+static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
 {
   CURLcode result;
   struct imap_conn *imapc = &conn->proto.imapc;
+  char *taggedfmt;
   va_list ap;
   va_start(ap, fmt);
 
-  imapc->resptag = idstr;
+  /* Calculate the next command ID wrapping at 3 digits */
+  imapc->cmdid = (imapc->cmdid + 1) % 1000;
 
-  result = Curl_pp_vsendf(&imapc->pp, fmt, ap);
+  /* Calculate the tag based on the connection ID and command ID */
+  snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
+           'A' + (conn->connection_id % 26), imapc->cmdid);
 
-  va_end(ap);
-
-  return result;
-}
-
-static const char *getcmdid(struct connectdata *conn)
-{
-  static const char * const ids[]= {
-    "A",
-    "B",
-    "C",
-    "D"
-  };
+  taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
+  if(!taggedfmt)
+    return CURLE_OUT_OF_MEMORY;
 
-  struct imap_conn *imapc = &conn->proto.imapc;
+  result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
 
-  /* Get the next id, but wrap at end of table */
-  imapc->cmdid = (int)((imapc->cmdid + 1) % (sizeof(ids) / sizeof(ids[0])));
+  Curl_safefree(taggedfmt);
+  va_end(ap);
 
-  return ids[imapc->cmdid];
+  return result;
 }
 
 /***********************************************************************
@@ -462,10 +454,9 @@ static void state(struct connectdata *conn, imapstate newstate)
 static CURLcode imap_state_starttls(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  const char *str = getcmdid(conn);
 
   /* Send the STARTTLS command */
-  result = imap_sendf(conn, str, "%s STARTTLS", str);
+  result = imap_sendf(conn, "STARTTLS");
 
   if(!result)
     state(conn, IMAP_STARTTLS);
@@ -477,7 +468,6 @@ static CURLcode imap_state_capability(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   struct imap_conn *imapc = &conn->proto.imapc;
-  const char *str;
 
   imapc->authmechs = 0;         /* No known authentication mechanisms yet */
   imapc->authused = 0;          /* Clear the authentication mechanism used */
@@ -490,10 +480,8 @@ static CURLcode imap_state_capability(struct connectdata *conn)
     return result;
   }
 
-  str = getcmdid(conn);
-
   /* Send the CAPABILITY command */
-  result = imap_sendf(conn, str, "%s CAPABILITY", str);
+  result = imap_sendf(conn, "CAPABILITY");
 
   if(result)
     return result;
@@ -507,13 +495,12 @@ static CURLcode imap_state_login(struct connectdata *conn)
 {
   CURLcode result;
   struct FTP *imap = conn->data->state.proto.imap;
-  const char *str = getcmdid(conn);
   char *user = imap_atom(imap->user);
   char *passwd = imap_atom(imap->passwd);
 
   /* Send USER and password */
-  result = imap_sendf(conn, str, "%s LOGIN %s %s", str,
-                      user ? user : "", passwd ? passwd : "");
+  result = imap_sendf(conn, "LOGIN %s %s", user ? user : "",
+                      passwd ? passwd : "");
 
   Curl_safefree(user);
   Curl_safefree(passwd);
@@ -569,9 +556,7 @@ static CURLcode imap_authenticate(struct connectdata *conn)
 
   if(mech) {
     /* Perform SASL based authentication */
-    const char *str = getcmdid(conn);
-
-    result = imap_sendf(conn, str, "%s AUTHENTICATE %s", str, mech);
+    result = imap_sendf(conn, "AUTHENTICATE %s", mech);
 
     if(!result)
       state(conn, authstate);
@@ -1051,10 +1036,9 @@ static CURLcode imap_select(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   struct imap_conn *imapc = &conn->proto.imapc;
-  const char *str = getcmdid(conn);
 
-  result = imap_sendf(conn, str, "%s SELECT %s", str,
-                      imapc->mailbox?imapc->mailbox:"");
+  result = imap_sendf(conn, "SELECT %s",
+                      imapc->mailbox ? imapc->mailbox : "");
   if(result)
     return result;
 
@@ -1066,12 +1050,11 @@ static CURLcode imap_select(struct connectdata *conn)
 static CURLcode imap_fetch(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  const char *str = getcmdid(conn);
 
   /* TODO: make this select the correct mail
    * Use "1 body[text]" to get the full mail body of mail 1
    */
-  result = imap_sendf(conn, str, "%s FETCH 1 BODY[TEXT]", str);
+  result = imap_sendf(conn, "FETCH 1 BODY[TEXT]");
   if(result)
     return result;
 
@@ -1389,8 +1372,8 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
   /* Start off waiting for the server greeting response */
   state(conn, IMAP_SERVERGREET);
 
-  /* Start off with an id of '*' */
-  imapc->resptag = "*";
+  /* Start off with an response id of '*' */
+  strcpy(imapc->resptag, "*");
 
   result = imap_multi_statemach(conn, done);
 
@@ -1521,9 +1504,8 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
 static CURLcode imap_logout(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  const char *str = getcmdid(conn);
 
-  result = imap_sendf(conn, str, "%s LOGOUT", str, NULL);
+  result = imap_sendf(conn, "LOGOUT", NULL);
   if(result)
     return result;
 
index 4a276c1510c777ab6a11523e2a2ed27617ffbc5a..5cbae751a5c7ac62780155db9b1e926f100786a1 100644 (file)
@@ -60,7 +60,7 @@ struct imap_conn {
   unsigned int authused;  /* Auth mechanism used for the connection */
   imapstate state;        /* Always use imap.c:state() to change state! */
   int cmdid;              /* Last used command ID */
-  const char *resptag;    /* Response tag to wait for */
+  char resptag[5];        /* Response tag to wait for */
   bool ssldone;           /* Is connect() over SSL done? */
   bool login_disabled;    /* LOGIN command explicitly disabled by server */
 };
index 4a04575b184300f207bb2dd9e63bf99e53ac2279..7589534f7e23e38448b180d3427e8f2303008edc 100644 (file)
@@ -56,11 +56,11 @@ imap://%HOSTIP:%IMAPPORT/1321 -u user:secret -p -x %HOSTIP:%PROXYPORT
 ^User-Agent: curl/.*
 </strip>
 <protocol>
-B CAPABILITY\r
-C LOGIN user secret\r
-D SELECT 1321\r
-A FETCH 1 BODY[TEXT]\r
-B LOGOUT\r
+A001 CAPABILITY\r
+A002 LOGIN user secret\r
+A003 SELECT 1321\r
+A004 FETCH 1 BODY[TEXT]\r
+A005 LOGOUT\r
 </protocol>
 <proxy>
 CONNECT %HOSTIP:%IMAPPORT HTTP/1.1\r
index d5f1cfeb9a84563d2d2049a0bfbba7e1455673bb..67e10997f5cb9de3456e85b070a61912eb0f8b77 100644 (file)
@@ -38,11 +38,11 @@ imap://%HOSTIP:%IMAPPORT/801 -u user:secret
 # Verify data after the test has been "shot"
 <verify>
 <protocol>
-B CAPABILITY\r
-C LOGIN user secret\r
-D SELECT 801\r
-A FETCH 1 BODY[TEXT]\r
-B LOGOUT\r
+A001 CAPABILITY\r
+A002 LOGIN user secret\r
+A003 SELECT 801\r
+A004 FETCH 1 BODY[TEXT]\r
+A005 LOGOUT\r
 </protocol>
 </verify>
 </testcase>