aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Holme <steve_holme@hotmail.com>2013-02-07 00:18:23 +0000
committerSteve Holme <steve_holme@hotmail.com>2013-02-07 00:18:23 +0000
commit7704621f4cd1d6d8728c1d7a8c3fd2cef1bec1ab (patch)
treeff845f88b5f9c49f31173bebd2a8c67d7f2cd288
parent542507f316d8ee4aeb3978ddcb48215c56d80d2f (diff)
imap: Changed response tag generation to be completely unique
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.
-rw-r--r--lib/imap.c68
-rw-r--r--lib/imap.h2
-rw-r--r--tests/data/test132110
-rw-r--r--tests/data/test80110
4 files changed, 36 insertions, 54 deletions
diff --git a/lib/imap.c b/lib/imap.c
index 5f82782ae..72774c089 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -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;
diff --git a/lib/imap.h b/lib/imap.h
index 4a276c151..5cbae751a 100644
--- a/lib/imap.h
+++ b/lib/imap.h
@@ -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 */
};
diff --git a/tests/data/test1321 b/tests/data/test1321
index 4a04575b1..7589534f7 100644
--- a/tests/data/test1321
+++ b/tests/data/test1321
@@ -56,11 +56,11 @@ imap://%HOSTIP:%IMAPPORT/1321 -u user:secret -p -x %HOSTIP:%PROXYPORT
^User-Agent: curl/.*
</strip>
<protocol>
-B CAPABILITY
-C LOGIN user secret
-D SELECT 1321
-A FETCH 1 BODY[TEXT]
-B LOGOUT
+A001 CAPABILITY
+A002 LOGIN user secret
+A003 SELECT 1321
+A004 FETCH 1 BODY[TEXT]
+A005 LOGOUT
</protocol>
<proxy>
CONNECT %HOSTIP:%IMAPPORT HTTP/1.1
diff --git a/tests/data/test801 b/tests/data/test801
index d5f1cfeb9..67e10997f 100644
--- a/tests/data/test801
+++ b/tests/data/test801
@@ -38,11 +38,11 @@ imap://%HOSTIP:%IMAPPORT/801 -u user:secret
# Verify data after the test has been "shot"
<verify>
<protocol>
-B CAPABILITY
-C LOGIN user secret
-D SELECT 801
-A FETCH 1 BODY[TEXT]
-B LOGOUT
+A001 CAPABILITY
+A002 LOGIN user secret
+A003 SELECT 801
+A004 FETCH 1 BODY[TEXT]
+A005 LOGOUT
</protocol>
</verify>
</testcase>