Applied some of the comment and layout changes that had already been
applied to the pop3 and smtp code over the last 6 to 9 months.

This is in preparation of adding SASL based authentication.
This commit is contained in:
Steve Holme 2012-12-28 21:24:36 +00:00
Родитель b3204e6d60
Коммит 2255ac52f7
1 изменённых файлов: 101 добавлений и 93 удалений

Просмотреть файл

@ -82,17 +82,16 @@
static CURLcode imap_parse_url_path(struct connectdata *conn); static CURLcode imap_parse_url_path(struct connectdata *conn);
static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done); static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
static CURLcode imap_do(struct connectdata *conn, bool *done); static CURLcode imap_do(struct connectdata *conn, bool *done);
static CURLcode imap_done(struct connectdata *conn, static CURLcode imap_done(struct connectdata *conn, CURLcode status,
CURLcode, bool premature); bool premature);
static CURLcode imap_connect(struct connectdata *conn, bool *done); static CURLcode imap_connect(struct connectdata *conn, bool *done);
static CURLcode imap_disconnect(struct connectdata *conn, bool dead); static CURLcode imap_disconnect(struct connectdata *conn, bool dead);
static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done); static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done);
static int imap_getsock(struct connectdata *conn, static int imap_getsock(struct connectdata *conn,
curl_socket_t *socks, curl_socket_t *socks,
int numsocks); int numsocks);
static CURLcode imap_doing(struct connectdata *conn, static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
bool *dophase_done); static CURLcode imap_setup_connection(struct connectdata *conn);
static CURLcode imap_setup_connection(struct connectdata * conn);
static CURLcode imap_state_upgrade_tls(struct connectdata *conn); static CURLcode imap_state_upgrade_tls(struct connectdata *conn);
/* /*
@ -238,8 +237,8 @@ static const char *getcmdid(struct connectdata *conn)
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
/* get the next id, but wrap at end of table */ /* Get the next id, but wrap at end of table */
imapc->cmdid = (int)((imapc->cmdid+1) % (sizeof(ids)/sizeof(ids[0]))); imapc->cmdid = (int)((imapc->cmdid + 1) % (sizeof(ids) / sizeof(ids[0])));
return ids[imapc->cmdid]; return ids[imapc->cmdid];
} }
@ -328,8 +327,8 @@ static int imap_getsock(struct connectdata *conn,
return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks); return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks);
} }
/* function that checks for an imap status code at the start of the /* Function that checks for an ending imap status code at the start of the
given string */ given string. */
static int imap_endofresp(struct pingpong *pp, int *resp) static int imap_endofresp(struct pingpong *pp, int *resp)
{ {
char *line = pp->linestart_resp; char *line = pp->linestart_resp;
@ -351,6 +350,7 @@ static int imap_endofresp(struct pingpong *pp, int *resp)
return TRUE; return TRUE;
} }
} }
return FALSE; /* nothing for us */ return FALSE; /* nothing for us */
} }
@ -358,6 +358,7 @@ static int imap_endofresp(struct pingpong *pp, int *resp)
static void state(struct connectdata *conn, static void state(struct connectdata *conn,
imapstate newstate) imapstate newstate)
{ {
struct imap_conn *imapc = &conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */ /* for debug purposes */
static const char * const names[]={ static const char * const names[]={
@ -371,13 +372,12 @@ static void state(struct connectdata *conn,
"LOGOUT", "LOGOUT",
/* LAST */ /* LAST */
}; };
#endif
struct imap_conn *imapc = &conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(imapc->state != newstate) if(imapc->state != newstate)
infof(conn->data, "IMAP %p state change from %s to %s\n", infof(conn->data, "IMAP %p state change from %s to %s\n",
imapc, names[imapc->state], names[newstate]); imapc, names[imapc->state], names[newstate]);
#endif #endif
imapc->state = newstate; imapc->state = newstate;
} }
@ -413,7 +413,7 @@ static void imap_to_imaps(struct connectdata *conn)
#define imap_to_imaps(x) Curl_nop_stmt #define imap_to_imaps(x) Curl_nop_stmt
#endif #endif
/* for the initial server greeting */ /* For the initial server greeting */
static CURLcode imap_state_servergreet_resp(struct connectdata *conn, static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
int imapcode, int imapcode,
imapstate instate) imapstate instate)
@ -443,13 +443,14 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
return result; return result;
} }
/* for STARTTLS responses */ /* For STARTTLS responses */
static CURLcode imap_state_starttls_resp(struct connectdata *conn, static CURLcode imap_state_starttls_resp(struct connectdata *conn,
int imapcode, int imapcode,
imapstate instate) imapstate instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(imapcode != 'O') { if(imapcode != 'O') {
@ -495,7 +496,7 @@ static CURLcode imap_state_upgrade_tls(struct connectdata *conn)
return result; return result;
} }
/* for LOGIN responses */ /* For LOGIN responses */
static CURLcode imap_state_login_resp(struct connectdata *conn, static CURLcode imap_state_login_resp(struct connectdata *conn,
int imapcode, int imapcode,
imapstate instate) imapstate instate)
@ -510,6 +511,7 @@ static CURLcode imap_state_login_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED; result = CURLE_LOGIN_DENIED;
} }
/* End of connect phase */
state(conn, IMAP_STOP); state(conn, IMAP_STOP);
return result; return result;
@ -571,7 +573,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn,
} }
else { else {
/* cache is drained */ /* cache is drained */
free(pp->cache); Curl_safefree(pp->cache);
pp->cache = NULL; pp->cache = NULL;
pp->cache_size = 0; pp->cache_size = 0;
} }
@ -669,53 +671,55 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
struct pingpong *pp = &imapc->pp; struct pingpong *pp = &imapc->pp;
size_t nread = 0; size_t nread = 0;
/* busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
if(imapc->state == IMAP_UPGRADETLS) if(imapc->state == IMAP_UPGRADETLS)
return imap_state_upgrade_tls(conn); return imap_state_upgrade_tls(conn);
/* Flush any data that needs to be sent */
if(pp->sendleft) if(pp->sendleft)
return Curl_pp_flushsend(pp); return Curl_pp_flushsend(pp);
/* we read a piece of response */ /* Read the response from the server */
result = Curl_pp_readresp(sock, pp, &imapcode, &nread); result = Curl_pp_readresp(sock, pp, &imapcode, &nread);
if(result) if(result)
return result; return result;
if(imapcode) if(imapcode) {
/* we have now received a full IMAP server response */ /* We have now received a full IMAP server response */
switch(imapc->state) { switch(imapc->state) {
case IMAP_SERVERGREET: case IMAP_SERVERGREET:
result = imap_state_servergreet_resp(conn, imapcode, imapc->state); result = imap_state_servergreet_resp(conn, imapcode, imapc->state);
break; break;
case IMAP_LOGIN: case IMAP_LOGIN:
result = imap_state_login_resp(conn, imapcode, imapc->state); result = imap_state_login_resp(conn, imapcode, imapc->state);
break; break;
case IMAP_STARTTLS: case IMAP_STARTTLS:
result = imap_state_starttls_resp(conn, imapcode, imapc->state); result = imap_state_starttls_resp(conn, imapcode, imapc->state);
break; break;
case IMAP_FETCH: case IMAP_FETCH:
result = imap_state_fetch_resp(conn, imapcode, imapc->state); result = imap_state_fetch_resp(conn, imapcode, imapc->state);
break; break;
case IMAP_SELECT: case IMAP_SELECT:
result = imap_state_select_resp(conn, imapcode, imapc->state); result = imap_state_select_resp(conn, imapcode, imapc->state);
break; break;
case IMAP_LOGOUT: case IMAP_LOGOUT:
/* fallthrough, just stop! */ /* fallthrough, just stop! */
default: default:
/* internal error */ /* internal error */
state(conn, IMAP_STOP); state(conn, IMAP_STOP);
break; break;
}
} }
return result; return result;
} }
/* called repeatedly until done from multi.c */ /* Called repeatedly until done from multi.c */
static CURLcode imap_multi_statemach(struct connectdata *conn, static CURLcode imap_multi_statemach(struct connectdata *conn,
bool *done) bool *done)
{ {
@ -747,21 +751,20 @@ static CURLcode imap_easy_statemach(struct connectdata *conn)
return result; return result;
} }
/* /* Allocate and initialize the struct IMAP for the current SessionHandle if
* Allocate and initialize the struct IMAP for the current SessionHandle. If required */
* need be.
*/
static CURLcode imap_init(struct connectdata *conn) static CURLcode imap_init(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *imap = data->state.proto.imap; struct FTP *imap = data->state.proto.imap;
if(!imap) { if(!imap) {
imap = data->state.proto.imap = calloc(sizeof(struct FTP), 1); imap = data->state.proto.imap = calloc(sizeof(struct FTP), 1);
if(!imap) if(!imap)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
/* get some initial data into the imap struct */ /* Get some initial data into the imap struct */
imap->bytecountp = &data->req.bytecount; imap->bytecountp = &data->req.bytecount;
/* No need to duplicate user+password, the connectdata struct won't change /* No need to duplicate user+password, the connectdata struct won't change
@ -774,7 +777,8 @@ static CURLcode imap_init(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/* /***********************************************************************
*
* imap_connect() should do everything that is to be considered a part of * imap_connect() should do everything that is to be considered a part of
* the connection phase. * the connection phase.
* *
@ -810,18 +814,21 @@ static CURLcode imap_connect(struct connectdata *conn,
if((conn->handler->flags & PROTOPT_SSL) && if((conn->handler->flags & PROTOPT_SSL) &&
data->state.used_interface != Curl_if_multi) { data->state.used_interface != Curl_if_multi) {
/* BLOCKING */ /* IMAPS is simply imap with SSL for the control channel */
/* so perform the SSL initialization for this socket */
result = Curl_ssl_connect(conn, FIRSTSOCKET); result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(result) if(result)
return result; return result;
} }
Curl_pp_init(pp); /* init generic pingpong data */ /* Initialise the response reader stuff */
Curl_pp_init(pp);
/* When we connect, we start in the state where we await the server greeting /* Start off waiting for the server greeting response */
response */
state(conn, IMAP_SERVERGREET); state(conn, IMAP_SERVERGREET);
imapc->idstr = "*"; /* we start off waiting for a '*' response */
/* Start off with an id of '*' */
imapc->idstr = "*";
if(data->state.used_interface == Curl_if_multi) if(data->state.used_interface == Curl_if_multi)
result = imap_multi_statemach(conn, done); result = imap_multi_statemach(conn, done);
@ -849,6 +856,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *imap = data->state.proto.imap; struct FTP *imap = data->state.proto.imap;
CURLcode result=CURLE_OK; CURLcode result=CURLE_OK;
(void)premature; (void)premature;
if(!imap) if(!imap)
@ -861,10 +869,10 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
if(status) { if(status) {
conn->bits.close = TRUE; /* marked for closure */ conn->bits.close = TRUE; /* marked for closure */
result = status; /* use the already set error code */ result = status; /* use the already set error code */
} }
/* clear these for next connection */ /* Clear the transfer mode for the next connection */
imap->transfer = FTPTRANSFER_BODY; imap->transfer = FTPTRANSFER_BODY;
return result; return result;
@ -877,31 +885,28 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
* This is the actual DO function for IMAP. Get a file/directory according to * This is the actual DO function for IMAP. Get a file/directory according to
* the options previously setup. * the options previously setup.
*/ */
static CURLcode imap_perform(struct connectdata *conn, bool *connected,
static bool *dophase_done)
CURLcode imap_perform(struct connectdata *conn,
bool *connected, /* connect status after PASV / PORT */
bool *dophase_done)
{ {
/* this is IMAP and no proxy */ /* This is IMAP and no proxy */
CURLcode result=CURLE_OK; CURLcode result = CURLE_OK;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(conn->data, "DO phase starts\n"));
if(conn->data->set.opt_no_body) { if(conn->data->set.opt_no_body) {
/* requested no body means no transfer... */ /* Requested no body means no transfer */
struct FTP *imap = conn->data->state.proto.imap; struct FTP *imap = conn->data->state.proto.imap;
imap->transfer = FTPTRANSFER_INFO; imap->transfer = FTPTRANSFER_INFO;
} }
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */ /* Start the first command in the DO phase */
result = imap_select(conn); result = imap_select(conn);
if(result) if(result)
return result; return result;
/* run the state-machine */ /* Run the state-machine */
if(conn->data->state.used_interface == Curl_if_multi) if(conn->data->state.used_interface == Curl_if_multi)
result = imap_multi_statemach(conn, dophase_done); result = imap_multi_statemach(conn, dophase_done);
else { else {
@ -942,6 +947,7 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
if(retcode) if(retcode)
return retcode; return retcode;
/* Parse the URL path */
retcode = imap_parse_url_path(conn); retcode = imap_parse_url_path(conn);
if(retcode) if(retcode)
return retcode; return retcode;
@ -970,6 +976,7 @@ static CURLcode imap_logout(struct connectdata *conn)
result = imap_sendf(conn, str, "%s LOGOUT", str, NULL); result = imap_sendf(conn, str, "%s LOGOUT", str, NULL);
if(result) if(result)
return result; return result;
state(conn, IMAP_LOGOUT); state(conn, IMAP_LOGOUT);
result = imap_easy_statemach(conn); result = imap_easy_statemach(conn);
@ -988,13 +995,19 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
{ {
struct imap_conn *imapc= &conn->proto.imapc; struct imap_conn *imapc= &conn->proto.imapc;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to */
/* The IMAP session may or may not have been allocated/setup at this /* The IMAP session may or may not have been allocated/setup at this
point! */ point! */
if(!dead_connection && imapc->pp.conn) if(!dead_connection && imapc->pp.conn)
(void)imap_logout(conn); /* ignore errors on the LOGOUT */ (void)imap_logout(conn); /* ignore errors on the LOGOUT */
/* Disconnect from the server */
Curl_pp_disconnect(&imapc->pp); Curl_pp_disconnect(&imapc->pp);
/* Cleanup our connection based variables */
Curl_safefree(imapc->mailbox); Curl_safefree(imapc->mailbox);
return CURLE_OK; return CURLE_OK;
@ -1009,7 +1022,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
*/ */
static CURLcode imap_parse_url_path(struct connectdata *conn) static CURLcode imap_parse_url_path(struct connectdata *conn)
{ {
/* the imap struct is already inited in imap_connect() */ /* The imap struct is already inited in imap_connect() */
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
const char *path = data->state.path; const char *path = data->state.path;
@ -1017,15 +1030,15 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
if(!*path) if(!*path)
path = "INBOX"; path = "INBOX";
/* url decode the path and use this mailbox */ /* URL decode the path and use this mailbox */
return Curl_urldecode(data, path, 0, &imapc->mailbox, NULL, TRUE); return Curl_urldecode(data, path, 0, &imapc->mailbox, NULL, TRUE);
} }
/* call this when the DO phase has completed */ /* Call this when the DO phase has completed */
static CURLcode imap_dophase_done(struct connectdata *conn, static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
bool connected)
{ {
struct FTP *imap = conn->data->state.proto.imap; struct FTP *imap = conn->data->state.proto.imap;
(void)connected; (void)connected;
if(imap->transfer != FTPTRANSFER_BODY) if(imap->transfer != FTPTRANSFER_BODY)
@ -1035,18 +1048,17 @@ static CURLcode imap_dophase_done(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
/* called from multi.c while DOing */ /* Called from multi.c while DOing */
static CURLcode imap_doing(struct connectdata *conn, static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
bool *dophase_done)
{ {
CURLcode result; CURLcode result = imap_multi_statemach(conn, dophase_done);
result = imap_multi_statemach(conn, dophase_done);
if(*dophase_done) { if(*dophase_done) {
result = imap_dophase_done(conn, FALSE /* not connected */); result = imap_dophase_done(conn, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(conn->data, "DO phase is complete\n"));
} }
return result; return result;
} }
@ -1058,30 +1070,27 @@ static CURLcode imap_doing(struct connectdata *conn,
* *
* Performs all commands done before a regular transfer between a local and a * Performs all commands done before a regular transfer between a local and a
* remote host. * remote host.
*
*/ */
static static CURLcode imap_regular_transfer(struct connectdata *conn,
CURLcode imap_regular_transfer(struct connectdata *conn, bool *dophase_done)
bool *dophase_done)
{ {
CURLcode result=CURLE_OK; CURLcode result = CURLE_OK;
bool connected=FALSE; bool connected = FALSE;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
data->req.size = -1; /* make sure this is unknown at this point */
/* Make sure size is unknown at this point */
data->req.size = -1;
Curl_pgrsSetUploadCounter(data, 0); Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0); Curl_pgrsSetDownloadCounter(data, 0);
Curl_pgrsSetUploadSize(data, 0); Curl_pgrsSetUploadSize(data, 0);
Curl_pgrsSetDownloadSize(data, 0); Curl_pgrsSetDownloadSize(data, 0);
result = imap_perform(conn, result = imap_perform(conn, &connected, dophase_done);
&connected, /* have we connected after PASV/PORT */
dophase_done); /* all commands in the DO-phase done? */
if(CURLE_OK == result) { if(CURLE_OK == result) {
if(!*dophase_done) if(!*dophase_done)
/* the DO phase has not completed yet */ /* The DO phase has not completed yet */
return CURLE_OK; return CURLE_OK;
result = imap_dophase_done(conn, connected); result = imap_dophase_done(conn, connected);
@ -1110,11 +1119,10 @@ static CURLcode imap_setup_connection(struct connectdata * conn)
return CURLE_UNSUPPORTED_PROTOCOL; return CURLE_UNSUPPORTED_PROTOCOL;
#endif #endif
} }
/*
* We explicitly mark this connection as persistent here as we're doing /* We explicitly mark this connection as persistent here as we're doing
* IMAP over HTTP and thus we accidentally avoid setting this value IMAP over HTTP and thus we accidentally avoid setting this value
* otherwise. otherwise */
*/
conn->bits.close = FALSE; conn->bits.close = FALSE;
#else #else
failf(data, "IMAP over http proxy requires HTTP support built-in!"); failf(data, "IMAP over http proxy requires HTTP support built-in!");