imap: Added custom request perform and response handler functions

Added imap_custom(), which initiates the custom command processing,
and an associated response handler imap_state_custom_resp(), which
handles any responses by sending them to the client as body data.

All untagged responses with the same name as the first word of the
custom request string are accepted, with the exception of SELECT and
EXAMINE which have responses that cannot be easily identified. An
extra check has been provided for them so that any untagged responses
are accepted for them.
This commit is contained in:
Jiri Hruska 2013-03-03 11:09:44 +01:00 committed by Steve Holme
parent 711065e4df
commit 226c1c6876

View File

@ -364,6 +364,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
int *resp) int *resp)
{ {
struct IMAP *imap = conn->data->state.proto.imap;
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
const char *id = imapc->resptag; const char *id = imapc->resptag;
size_t id_len = strlen(id); size_t id_len = strlen(id);
@ -406,6 +407,17 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
return FALSE; return FALSE;
break; break;
case IMAP_CUSTOM:
/* When dealing with a custom command, we are interested in all
intermediate responses which match the parameter name. The
exceptions are SELECT and EXAMINE commands, for which no
filtering is (or can be easily) done. */
if(!imap_matchresp(line, len, imap->custom) &&
strcmp(imap->custom, "SELECT") &&
strcmp(imap->custom, "EXAMINE"))
return FALSE;
break;
/* Ignore other untagged responses */ /* Ignore other untagged responses */
default: default:
return FALSE; return FALSE;
@ -739,6 +751,24 @@ static CURLcode imap_append(struct connectdata *conn)
return result; return result;
} }
static CURLcode imap_custom(struct connectdata *conn)
{
struct IMAP *imap = conn->data->state.proto.imap;
/* Send the custom request */
CURLcode result = imap_sendf(conn, "%s%s", imap->custom,
imap->custom_params ? imap->custom_params : "");
if(!result) {
/* We don't know how much data will be received */
Curl_pgrsSetDownloadSize(conn->data, -1);
state(conn, IMAP_CUSTOM);
}
return result;
}
/* 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,
@ -1434,6 +1464,39 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn,
return result; return result;
} }
/* For custom request responses */
static CURLcode imap_state_custom_resp(struct connectdata *conn,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
char *line = conn->data->state.buffer;
size_t len = strlen(line);
(void)instate; /* No use for this yet */
if(imapcode == '*') {
/* The client which asked for this custom command should know best
how to cope with the result, just send it as body.
Add back the LF character temporarily while saving. */
line[len] = '\n';
result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
}
else {
/* Final response. Stop and return the final status. */
if(imapcode != 'O')
result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
else
result = CURLE_OK;
/* End of DO phase */
state(conn, IMAP_STOP);
}
return result;
}
static CURLcode imap_statemach_act(struct connectdata *conn) static CURLcode imap_statemach_act(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1544,6 +1607,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
result = imap_state_append_final_resp(conn, imapcode, imapc->state); result = imap_state_append_final_resp(conn, imapcode, imapc->state);
break; break;
case IMAP_CUSTOM:
result = imap_state_custom_resp(conn, imapcode, imapc->state);
break;
case IMAP_LOGOUT: case IMAP_LOGOUT:
/* fallthrough, just stop! */ /* fallthrough, just stop! */
default: default: