diff options
Diffstat (limited to 'Utilities/cmcurl/lib/imap.c')
-rw-r--r-- | Utilities/cmcurl/lib/imap.c | 148 |
1 files changed, 69 insertions, 79 deletions
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c index e6d83f2..123ea3b 100644 --- a/Utilities/cmcurl/lib/imap.c +++ b/Utilities/cmcurl/lib/imap.c @@ -5,11 +5,11 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. + * are also available at https://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is @@ -80,10 +80,10 @@ #include "rawstr.h" #include "curl_sasl.h" #include "warnless.h" -#include "curl_printf.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" #include "curl_memory.h" -/* The last #include file should be: */ #include "memdebug.h" /* Local API functions */ @@ -98,7 +98,7 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks); static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done); static CURLcode imap_setup_connection(struct connectdata *conn); -static char *imap_atom(const char *str); +static char *imap_atom(const char *str, bool escape_only); static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...); static CURLcode imap_parse_url_options(struct connectdata *conn); static CURLcode imap_parse_url_path(struct connectdata *conn); @@ -227,7 +227,11 @@ static const struct SASLproto saslimap = { #ifdef USE_SSL static void imap_to_imaps(struct connectdata *conn) { + /* Change the connection handler */ conn->handler = &Curl_handler_imaps; + + /* Set the connection's upgraded to TLS flag */ + conn->tls_upgraded = TRUE; } #else #define imap_to_imaps(x) Curl_nop_stmt @@ -360,8 +364,8 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, a space and optionally some text as per RFC-3501 for the AUTHENTICATE and APPEND commands and as outlined in Section 4. Examples of RFC-4959 but some e-mail servers ignore this and only send a single + instead. */ - if((len == 3 && !memcmp("+", line, 1)) || - (len >= 2 && !memcmp("+ ", line, 2))) { + if(imap && !imap->custom && ((len == 3 && !memcmp("+", line, 1)) || + (len >= 2 && !memcmp("+ ", line, 2)))) { switch(imapc->state) { /* States which are interested in continuation responses */ case IMAP_AUTHENTICATE: @@ -540,8 +544,8 @@ static CURLcode imap_perform_login(struct connectdata *conn) } /* Make sure the username and password are in the correct atom format */ - user = imap_atom(conn->user); - passwd = imap_atom(conn->passwd); + user = imap_atom(conn->user, false); + passwd = imap_atom(conn->passwd, false); /* Send the LOGIN command */ result = imap_sendf(conn, "LOGIN %s %s", user ? user : "", @@ -644,7 +648,7 @@ static CURLcode imap_perform_authentication(struct connectdata *conn) static CURLcode imap_perform_list(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.protop; char *mailbox; @@ -653,8 +657,8 @@ static CURLcode imap_perform_list(struct connectdata *conn) result = imap_sendf(conn, "%s%s", imap->custom, imap->custom_params ? imap->custom_params : ""); else { - /* Make sure the mailbox is in the correct atom format */ - mailbox = imap_atom(imap->mailbox ? imap->mailbox : ""); + /* Make sure the mailbox is in the correct atom format if necessary */ + mailbox = imap->mailbox ? imap_atom(imap->mailbox, true) : strdup(""); if(!mailbox) return CURLE_OUT_OF_MEMORY; @@ -679,7 +683,7 @@ static CURLcode imap_perform_list(struct connectdata *conn) static CURLcode imap_perform_select(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.protop; struct imap_conn *imapc = &conn->proto.imapc; char *mailbox; @@ -695,7 +699,7 @@ static CURLcode imap_perform_select(struct connectdata *conn) } /* Make sure the mailbox is in the correct atom format */ - mailbox = imap_atom(imap->mailbox); + mailbox = imap_atom(imap->mailbox, false); if(!mailbox) return CURLE_OUT_OF_MEMORY; @@ -769,7 +773,7 @@ static CURLcode imap_perform_append(struct connectdata *conn) } /* Make sure the mailbox is in the correct atom format */ - mailbox = imap_atom(imap->mailbox); + mailbox = imap_atom(imap->mailbox, false); if(!mailbox) return CURLE_OUT_OF_MEMORY; @@ -836,7 +840,7 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; (void)instate; /* no use for this yet */ @@ -856,7 +860,7 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct imap_conn *imapc = &conn->proto.imapc; const char *line = data->state.buffer; size_t wordlen; @@ -906,8 +910,8 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, wordlen -= 5; /* Test the word for a matching authentication mechanism */ - if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) && - llen == wordlen) + mechbit = Curl_sasl_decode_mech(line, wordlen, &llen); + if(mechbit && llen == wordlen) imapc->sasl.authmechs |= mechbit; } @@ -943,7 +947,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; (void)instate; /* no use for this yet */ @@ -967,7 +971,7 @@ static CURLcode imap_state_auth_resp(struct connectdata *conn, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct imap_conn *imapc = &conn->proto.imapc; saslprogress progress; @@ -1001,7 +1005,7 @@ static CURLcode imap_state_login_resp(struct connectdata *conn, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; (void)instate; /* no use for this yet */ @@ -1016,9 +1020,10 @@ static CURLcode imap_state_login_resp(struct connectdata *conn, return result; } -/* For LIST responses */ -static CURLcode imap_state_list_resp(struct connectdata *conn, int imapcode, - imapstate instate) +/* For LIST and SEARCH responses */ +static CURLcode imap_state_listsearch_resp(struct connectdata *conn, + int imapcode, + imapstate instate) { CURLcode result = CURLE_OK; char *line = conn->data->state.buffer; @@ -1046,7 +1051,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap = conn->data->req.protop; struct imap_conn *imapc = &conn->proto.imapc; const char *line = data->state.buffer; @@ -1093,12 +1098,12 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct imap_conn *imapc = &conn->proto.imapc; struct pingpong *pp = &imapc->pp; const char *ptr = data->state.buffer; bool parsed = FALSE; - curl_off_t size; + curl_off_t size = 0; (void)instate; /* no use for this yet */ @@ -1206,7 +1211,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; (void)instate; /* No use for this yet */ @@ -1245,31 +1250,6 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn, return result; } -/* For SEARCH responses */ -static CURLcode imap_state_search_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 == '*') { - /* Temporarily add the LF character back and send as body to the client */ - line[len] = '\n'; - result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); - line[len] = '\0'; - } - else if(imapcode != 'O') - result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */ - else - /* End of DO phase */ - state(conn, IMAP_STOP); - - return result; -} - static CURLcode imap_statemach_act(struct connectdata *conn) { CURLcode result = CURLE_OK; @@ -1323,7 +1303,7 @@ static CURLcode imap_statemach_act(struct connectdata *conn) break; case IMAP_LIST: - result = imap_state_list_resp(conn, imapcode, imapc->state); + result = imap_state_listsearch_resp(conn, imapcode, imapc->state); break; case IMAP_SELECT: @@ -1347,7 +1327,7 @@ static CURLcode imap_statemach_act(struct connectdata *conn) break; case IMAP_SEARCH: - result = imap_state_search_resp(conn, imapcode, imapc->state); + result = imap_state_listsearch_resp(conn, imapcode, imapc->state); break; case IMAP_LOGOUT: @@ -1391,12 +1371,12 @@ static CURLcode imap_block_statemach(struct connectdata *conn) return result; } -/* Allocate and initialize the struct IMAP for the current SessionHandle if +/* Allocate and initialize the struct IMAP for the current Curl_easy if required */ static CURLcode imap_init(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap; imap = data->req.protop = calloc(sizeof(struct IMAP), 1); @@ -1476,16 +1456,12 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, bool premature) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.protop; (void)premature; if(!imap) - /* When the easy handle is removed from the multi interface while libcurl - is still trying to resolve the host name, the IMAP struct is not yet - initialized. However, the removal action calls Curl_done() which in - turn calls this function, so we simply return success. */ return CURLE_OK; if(status) { @@ -1508,8 +1484,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, TODO: when the multi interface is used, this _really_ should be using the imap_multi_statemach function but we have no general support for - non-blocking DONE operations, not in the multi state machine and with - Curl_done() invokes on several places in the code! + non-blocking DONE operations! */ if(!result) result = imap_block_statemach(conn); @@ -1543,7 +1518,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected, { /* This is IMAP and no proxy */ CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.protop; struct imap_conn *imapc = &conn->proto.imapc; bool selected = FALSE; @@ -1708,7 +1683,7 @@ static CURLcode imap_regular_transfer(struct connectdata *conn, { CURLcode result = CURLE_OK; bool connected = FALSE; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; /* Make sure size is unknown at this point */ data->req.size = -1; @@ -1731,13 +1706,17 @@ static CURLcode imap_regular_transfer(struct connectdata *conn, static CURLcode imap_setup_connection(struct connectdata *conn) { - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; /* Initialise the IMAP layer */ CURLcode result = imap_init(conn); if(result) return result; + /* Clear the TLS upgraded flag */ + conn->tls_upgraded = FALSE; + + /* Set up the proxy if necessary */ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { /* Unless we have asked to tunnel IMAP operations through the proxy, we switch and use HTTP operations only */ @@ -1815,38 +1794,49 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) * The returned string needs to be freed. * */ -static char *imap_atom(const char *str) +static char *imap_atom(const char *str, bool escape_only) { + /* !checksrc! disable PARENBRACE 1 */ + const char atom_specials[] = "(){ %*]"; const char *p1; char *p2; size_t backsp_count = 0; size_t quote_count = 0; - bool space_exists = FALSE; + bool others_exists = FALSE; size_t newlen = 0; char *newstr = NULL; if(!str) return NULL; - /* Count any unescaped characters */ + /* Look for "atom-specials", counting the backslash and quote characters as + these will need escapping */ p1 = str; while(*p1) { if(*p1 == '\\') backsp_count++; else if(*p1 == '"') quote_count++; - else if(*p1 == ' ') - space_exists = TRUE; + else if(!escape_only) { + const char *p3 = atom_specials; + + while(*p3 && !others_exists) { + if(*p1 == *p3) + others_exists = TRUE; + + p3++; + } + } p1++; } - /* Does the input contain any unescaped characters? */ - if(!backsp_count && !quote_count && !space_exists) + /* Does the input contain any "atom-special" characters? */ + if(!backsp_count && !quote_count && !others_exists) return strdup(str); /* Calculate the new string length */ - newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0); + newlen = strlen(str) + backsp_count + quote_count + (others_exists ? 2 : 0); /* Allocate the new string */ newstr = (char *) malloc((newlen + 1) * sizeof(char)); @@ -1855,7 +1845,7 @@ static char *imap_atom(const char *str) /* Surround the string in quotes if necessary */ p2 = newstr; - if(space_exists) { + if(others_exists) { newstr[0] = '"'; newstr[newlen - 1] = '"'; p2++; @@ -1981,7 +1971,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn) { /* The imap struct is already initialised in imap_connect() */ CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.protop; const char *begin = data->state.path; const char *ptr = begin; @@ -2111,7 +2101,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn) static CURLcode imap_parse_custom_request(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; + struct Curl_easy *data = conn->data; struct IMAP *imap = data->req.protop; const char *custom = data->set.str[STRING_CUSTOMREQUEST]; |