aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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: