summaryrefslogtreecommitdiff
path: root/lib/imap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/imap.c')
-rw-r--r--lib/imap.c154
1 files changed, 82 insertions, 72 deletions
diff --git a/lib/imap.c b/lib/imap.c
index 6163899bb..e1704b299 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -78,6 +78,7 @@
#include "multiif.h"
#include "url.h"
#include "strcase.h"
+#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
@@ -101,19 +102,19 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode imap_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static char *imap_atom(const char *str, bool escape_only);
-static CURLcode imap_sendf(struct Curl_easy *data,
- struct connectdata *conn, const char *fmt, ...);
+static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...);
static CURLcode imap_parse_url_options(struct connectdata *conn);
static CURLcode imap_parse_url_path(struct Curl_easy *data);
static CURLcode imap_parse_custom_request(struct Curl_easy *data);
static CURLcode imap_perform_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
const char *mech,
- const char *initresp);
+ const struct bufref *initresp);
static CURLcode imap_continue_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
- const char *resp);
-static void imap_get_message(char *buffer, char **outptr);
+ const char *mech,
+ const struct bufref *resp);
+static CURLcode imap_cancel_authenticate(struct Curl_easy *data,
+ const char *mech);
+static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out);
/*
* IMAP protocol handler.
@@ -180,12 +181,15 @@ const struct Curl_handler Curl_handler_imaps = {
/* SASL parameters for the imap protocol */
static const struct SASLproto saslimap = {
"imap", /* The service name */
- '+', /* Code received when continuation is expected */
- IMAP_RESP_OK, /* Code to receive upon authentication success */
- 0, /* Maximum initial response length (no max) */
imap_perform_authenticate, /* Send authentication command */
imap_continue_authenticate, /* Send authentication continuation */
- imap_get_message /* Get SASL response message */
+ imap_cancel_authenticate, /* Send authentication cancellation */
+ imap_get_message, /* Get SASL response message */
+ 0, /* No maximum initial response length */
+ '+', /* Code received when continuation is expected */
+ IMAP_RESP_OK, /* Code to receive upon authentication success */
+ SASL_AUTH_DEFAULT, /* Default mechanisms */
+ SASL_FLAG_BASE64 /* Configuration flags */
};
@@ -352,34 +356,32 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
*
* Gets the authentication message from the response buffer.
*/
-static void imap_get_message(char *buffer, char **outptr)
+static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
{
- size_t len = strlen(buffer);
- char *message = NULL;
+ char *message = data->state.buffer;
+ size_t len = strlen(message);
if(len > 2) {
/* Find the start of the message */
len -= 2;
- for(message = buffer + 2; *message == ' ' || *message == '\t';
- message++, len--)
+ for(message += 2; *message == ' ' || *message == '\t'; message++, len--)
;
/* Find the end of the message */
- for(; len--;)
+ while(len--)
if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
message[len] != '\t')
break;
/* Terminate the message */
- if(++len) {
- message[len] = '\0';
- }
+ message[++len] = '\0';
+ Curl_bufref_set(out, message, len, NULL);
}
else
/* junk input => zero length output */
- message = &buffer[len];
+ Curl_bufref_set(out, "", 0, NULL);
- *outptr = message;
+ return CURLE_OK;
}
/***********************************************************************
@@ -437,7 +439,7 @@ static CURLcode imap_perform_capability(struct Curl_easy *data,
imapc->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPABILITY command */
- result = imap_sendf(data, conn, "CAPABILITY");
+ result = imap_sendf(data, "CAPABILITY");
if(!result)
state(data, IMAP_CAPABILITY);
@@ -451,11 +453,10 @@ static CURLcode imap_perform_capability(struct Curl_easy *data,
*
* Sends the STARTTLS command to start the upgrade to TLS.
*/
-static CURLcode imap_perform_starttls(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_starttls(struct Curl_easy *data)
{
/* Send the STARTTLS command */
- CURLcode result = imap_sendf(data, conn, "STARTTLS");
+ CURLcode result = imap_sendf(data, "STARTTLS");
if(!result)
state(data, IMAP_STARTTLS);
@@ -516,7 +517,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
passwd = imap_atom(conn->passwd, false);
/* Send the LOGIN command */
- result = imap_sendf(data, conn, "LOGIN %s %s", user ? user : "",
+ result = imap_sendf(data, "LOGIN %s %s", user ? user : "",
passwd ? passwd : "");
free(user);
@@ -536,20 +537,19 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
* SASL authentication mechanism.
*/
static CURLcode imap_perform_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
const char *mech,
- const char *initresp)
+ const struct bufref *initresp)
{
CURLcode result = CURLE_OK;
- (void)data;
+ const char *ir = (const char *) Curl_bufref_ptr(initresp);
- if(initresp) {
+ if(ir) {
/* Send the AUTHENTICATE command with the initial response */
- result = imap_sendf(data, conn, "AUTHENTICATE %s %s", mech, initresp);
+ result = imap_sendf(data, "AUTHENTICATE %s %s", mech, ir);
}
else {
/* Send the AUTHENTICATE command */
- result = imap_sendf(data, conn, "AUTHENTICATE %s", mech);
+ result = imap_sendf(data, "AUTHENTICATE %s", mech);
}
return result;
@@ -559,15 +559,34 @@ static CURLcode imap_perform_authenticate(struct Curl_easy *data,
*
* imap_continue_authenticate()
*
- * Sends SASL continuation data or cancellation.
+ * Sends SASL continuation data.
*/
static CURLcode imap_continue_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
- const char *resp)
+ const char *mech,
+ const struct bufref *resp)
{
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc = &data->conn->proto.imapc;
+
+ (void)mech;
- return Curl_pp_sendf(data, &imapc->pp, "%s", resp);
+ return Curl_pp_sendf(data, &imapc->pp,
+ "%s", (const char *) Curl_bufref_ptr(resp));
+}
+
+/***********************************************************************
+ *
+ * imap_cancel_authenticate()
+ *
+ * Sends SASL cancellation.
+ */
+static CURLcode imap_cancel_authenticate(struct Curl_easy *data,
+ const char *mech)
+{
+ struct imap_conn *imapc = &data->conn->proto.imapc;
+
+ (void)mech;
+
+ return Curl_pp_sendf(data, &imapc->pp, "*");
}
/***********************************************************************
@@ -594,8 +613,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
}
/* Calculate the SASL login details */
- result = Curl_sasl_start(&imapc->sasl, data, conn,
- imapc->ir_supported, &progress);
+ result = Curl_sasl_start(&imapc->sasl, data, imapc->ir_supported, &progress);
if(!result) {
if(progress == SASL_INPROGRESS)
@@ -622,12 +640,11 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
static CURLcode imap_perform_list(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
struct IMAP *imap = data->req.p.imap;
if(imap->custom)
/* Send the custom request */
- result = imap_sendf(data, conn, "%s%s", imap->custom,
+ result = imap_sendf(data, "%s%s", imap->custom,
imap->custom_params ? imap->custom_params : "");
else {
/* Make sure the mailbox is in the correct atom format if necessary */
@@ -637,7 +654,7 @@ static CURLcode imap_perform_list(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the LIST command */
- result = imap_sendf(data, conn, "LIST \"%s\" *", mailbox);
+ result = imap_sendf(data, "LIST \"%s\" *", mailbox);
free(mailbox);
}
@@ -678,7 +695,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the SELECT command */
- result = imap_sendf(data, conn, "SELECT %s", mailbox);
+ result = imap_sendf(data, "SELECT %s", mailbox);
free(mailbox);
@@ -694,8 +711,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
*
* Sends a FETCH command to initiate the download of a message.
*/
-static CURLcode imap_perform_fetch(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_fetch(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = data->req.p.imap;
@@ -704,21 +720,21 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data,
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]<%s>",
+ result = imap_sendf(data, "UID FETCH %s BODY[%s]<%s>",
imap->uid, imap->section ? imap->section : "",
imap->partial);
else
- result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]",
+ result = imap_sendf(data, "UID FETCH %s BODY[%s]",
imap->uid, imap->section ? imap->section : "");
}
else if(imap->mindex) {
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(data, conn, "FETCH %s BODY[%s]<%s>",
+ result = imap_sendf(data, "FETCH %s BODY[%s]<%s>",
imap->mindex, imap->section ? imap->section : "",
imap->partial);
else
- result = imap_sendf(data, conn, "FETCH %s BODY[%s]",
+ result = imap_sendf(data, "FETCH %s BODY[%s]",
imap->mindex, imap->section ? imap->section : "");
}
else {
@@ -740,7 +756,6 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data,
static CURLcode imap_perform_append(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
struct IMAP *imap = data->req.p.imap;
char *mailbox;
@@ -791,7 +806,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the APPEND command */
- result = imap_sendf(data, conn,
+ result = imap_sendf(data,
"APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
mailbox, data->state.infilesize);
@@ -809,8 +824,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
*
* Sends a SEARCH command.
*/
-static CURLcode imap_perform_search(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_search(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = data->req.p.imap;
@@ -822,7 +836,7 @@ static CURLcode imap_perform_search(struct Curl_easy *data,
}
/* Send the SEARCH command */
- result = imap_sendf(data, conn, "SEARCH %s", imap->query);
+ result = imap_sendf(data, "SEARCH %s", imap->query);
if(!result)
state(data, IMAP_SEARCH);
@@ -836,11 +850,10 @@ static CURLcode imap_perform_search(struct Curl_easy *data,
*
* Performs the logout action prior to sclose() being called.
*/
-static CURLcode imap_perform_logout(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_logout(struct Curl_easy *data)
{
/* Send the LOGOUT command */
- CURLcode result = imap_sendf(data, conn, "LOGOUT");
+ CURLcode result = imap_sendf(data, "LOGOUT");
if(!result)
state(data, IMAP_LOGOUT);
@@ -938,7 +951,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
/* PREAUTH is not compatible with STARTTLS. */
if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
/* Switch to TLS connection now */
- result = imap_perform_starttls(data, conn);
+ result = imap_perform_starttls(data);
}
else if(data->set.use_ssl <= CURLUSESSL_TRY)
result = imap_perform_authentication(data, conn);
@@ -993,7 +1006,7 @@ static CURLcode imap_state_auth_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&imapc->sasl, data, conn, imapcode, &progress);
+ result = Curl_sasl_continue(&imapc->sasl, data, imapcode, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
@@ -1094,9 +1107,9 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
if(imap->custom)
result = imap_perform_list(data);
else if(imap->query)
- result = imap_perform_search(data, conn);
+ result = imap_perform_search(data);
else
- result = imap_perform_fetch(data, conn);
+ result = imap_perform_fetch(data);
}
}
else {
@@ -1441,7 +1454,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
/* Set the default preferred authentication type and mechanism */
imapc->preftype = IMAP_TYPE_ANY;
- Curl_sasl_init(&imapc->sasl, &saslimap);
+ Curl_sasl_init(&imapc->sasl, data, &saslimap);
Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
/* Initialise the pingpong layer */
@@ -1568,10 +1581,10 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
result = imap_perform_list(data);
else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
- result = imap_perform_fetch(data, conn);
+ result = imap_perform_fetch(data);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
- result = imap_perform_search(data, conn);
+ result = imap_perform_search(data);
else if(imap->mailbox && !selected &&
(imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
@@ -1643,7 +1656,7 @@ static CURLcode imap_disconnect(struct Curl_easy *data,
/* The IMAP session may or may not have been allocated/setup at this
point! */
if(!dead_connection && conn->bits.protoconnstart) {
- if(!imap_perform_logout(data, conn))
+ if(!imap_perform_logout(data))
(void)imap_block_statemach(data, conn, TRUE); /* ignore errors */
}
@@ -1747,17 +1760,16 @@ static CURLcode imap_setup_connection(struct Curl_easy *data,
*
* Designed to never block.
*/
-static CURLcode imap_sendf(struct Curl_easy *data,
- struct connectdata *conn, const char *fmt, ...)
+static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc = &data->conn->proto.imapc;
DEBUGASSERT(fmt);
/* Calculate the tag based on the connection ID and command ID */
msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
- 'A' + curlx_sltosi(conn->connection_id % 26),
+ 'A' + curlx_sltosi(data->conn->connection_id % 26),
(++imapc->cmdid)%1000);
/* start with a blank buffer */
@@ -1911,8 +1923,6 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
struct imap_conn *imapc = &conn->proto.imapc;
const char *ptr = conn->options;
- imapc->sasl.resetprefs = TRUE;
-
while(!result && ptr && *ptr) {
const char *key = ptr;
const char *value;