1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

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.
This commit is contained in:
Steve Holme 2013-02-07 00:18:23 +00:00
parent 542507f316
commit 7704621f4c
4 changed files with 36 additions and 54 deletions

View File

@ -211,41 +211,33 @@ 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);
taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
if(!taggedfmt)
return CURLE_OUT_OF_MEMORY;
result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
Curl_safefree(taggedfmt);
va_end(ap);
return result;
}
static const char *getcmdid(struct connectdata *conn)
{
static const char * const ids[]= {
"A",
"B",
"C",
"D"
};
struct imap_conn *imapc = &conn->proto.imapc;
/* Get the next id, but wrap at end of table */
imapc->cmdid = (int)((imapc->cmdid + 1) % (sizeof(ids) / sizeof(ids[0])));
return ids[imapc->cmdid];
}
/***********************************************************************
*
* imap_atom()
@ -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;

View 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 */
};

View File

@ -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

View File

@ -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>