From 7704621f4cd1d6d8728c1d7a8c3fd2cef1bec1ab Mon Sep 17 00:00:00 2001 From: Steve Holme Date: Thu, 7 Feb 2013 00:18:23 +0000 Subject: 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. --- lib/imap.c | 68 ++++++++++++++++++++--------------------------------- lib/imap.h | 2 +- tests/data/test1321 | 10 ++++---- tests/data/test801 | 10 ++++---- 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/.* -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 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" -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 -- cgit v1.2.3