aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJiri Hruska <jirka@fud.cz>2013-03-03 11:09:44 +0100
committerSteve Holme <steve_holme@hotmail.com>2013-03-03 13:10:31 +0000
commit226c1c6876fffd362f22c4a507be360fb1bc8103 (patch)
tree4f05488538f541eb4594931c480a6cc47a33ad83 /lib
parent711065e4df72a3a6c8828eac30750a95d8d556d0 (diff)
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/imap.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/imap.c b/lib/imap.c
index 69ec3524e..274513950 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -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,
int *resp)
{
+ struct IMAP *imap = conn->data->state.proto.imap;
struct imap_conn *imapc = &conn->proto.imapc;
const char *id = imapc->resptag;
size_t id_len = strlen(id);
@@ -406,6 +407,17 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
return FALSE;
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 */
default:
return FALSE;
@@ -739,6 +751,24 @@ static CURLcode imap_append(struct connectdata *conn)
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 */
static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
int imapcode,
@@ -1434,6 +1464,39 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn,
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)
{
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);
break;
+ case IMAP_CUSTOM:
+ result = imap_state_custom_resp(conn, imapcode, imapc->state);
+ break;
+
case IMAP_LOGOUT:
/* fallthrough, just stop! */
default: