diff options
-rw-r--r-- | lib/imap.c | 67 |
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: |