diff options
author | Maxim Yurchuk <maxim-yurchuk@ydb.tech> | 2024-10-18 20:31:38 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-18 20:31:38 +0300 |
commit | 2a74bac2d2d3bccb4e10120f1ead805640ec9dd0 (patch) | |
tree | 047e4818ced5aaf73f58517629e5260b5291f9f0 /contrib/libs/curl/lib/pop3.c | |
parent | 2d9656823e9521d8c29ea4c9a1d0eab78391abfc (diff) | |
parent | 3d834a1923bbf9403cd4a448e7f32b670aa4124f (diff) | |
download | ydb-2a74bac2d2d3bccb4e10120f1ead805640ec9dd0.tar.gz |
Merge pull request #10502 from ydb-platform/mergelibs-241016-1210
Library import 241016-1210
Diffstat (limited to 'contrib/libs/curl/lib/pop3.c')
-rw-r--r-- | contrib/libs/curl/lib/pop3.c | 211 |
1 files changed, 77 insertions, 134 deletions
diff --git a/contrib/libs/curl/lib/pop3.c b/contrib/libs/curl/lib/pop3.c index 1f5334d917..3e0f20a690 100644 --- a/contrib/libs/curl/lib/pop3.c +++ b/contrib/libs/curl/lib/pop3.c @@ -77,16 +77,11 @@ #include "curl_sasl.h" #include "curl_md5.h" #include "warnless.h" -#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -#endif - /* Local API functions */ static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done); static CURLcode pop3_do(struct Curl_easy *data, bool *done); @@ -111,17 +106,12 @@ static CURLcode pop3_continue_auth(struct Curl_easy *data, const char *mech, static CURLcode pop3_cancel_auth(struct Curl_easy *data, const char *mech); static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out); -/* This function scans the body after the end-of-body and writes everything - * until the end is found */ -static CURLcode pop3_write(struct Curl_easy *data, - const char *str, size_t nread, bool is_eos); - /* * POP3 protocol handler. */ const struct Curl_handler Curl_handler_pop3 = { - "pop3", /* scheme */ + "POP3", /* scheme */ pop3_setup_connection, /* setup_connection */ pop3_do, /* do_it */ pop3_done, /* done */ @@ -134,8 +124,7 @@ const struct Curl_handler Curl_handler_pop3 = { ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ pop3_disconnect, /* disconnect */ - pop3_write, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ PORT_POP3, /* defport */ @@ -151,7 +140,7 @@ const struct Curl_handler Curl_handler_pop3 = { */ const struct Curl_handler Curl_handler_pop3s = { - "pop3s", /* scheme */ + "POP3S", /* scheme */ pop3_setup_connection, /* setup_connection */ pop3_do, /* do_it */ pop3_done, /* done */ @@ -164,8 +153,7 @@ const struct Curl_handler Curl_handler_pop3s = { ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ pop3_disconnect, /* disconnect */ - pop3_write, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ PORT_POP3S, /* defport */ @@ -203,53 +191,6 @@ static void pop3_to_pop3s(struct connectdata *conn) #define pop3_to_pop3s(x) Curl_nop_stmt #endif -struct pop3_cmd { - const char *name; - unsigned short nlen; - BIT(multiline); /* response is multi-line with last '.' line */ - BIT(multiline_with_args); /* is multi-line when command has args */ -}; - -static const struct pop3_cmd pop3cmds[] = { - { "APOP", 4, FALSE, FALSE }, - { "AUTH", 4, FALSE, FALSE }, - { "CAPA", 4, TRUE, TRUE }, - { "DELE", 4, FALSE, FALSE }, - { "LIST", 4, TRUE, FALSE }, - { "MSG", 3, TRUE, TRUE }, - { "NOOP", 4, FALSE, FALSE }, - { "PASS", 4, FALSE, FALSE }, - { "QUIT", 4, FALSE, FALSE }, - { "RETR", 4, TRUE, TRUE }, - { "RSET", 4, FALSE, FALSE }, - { "STAT", 4, FALSE, FALSE }, - { "STLS", 4, FALSE, FALSE }, - { "TOP", 3, TRUE, TRUE }, - { "UIDL", 4, TRUE, FALSE }, - { "USER", 4, FALSE, FALSE }, - { "UTF8", 4, FALSE, FALSE }, - { "XTND", 4, TRUE, TRUE }, -}; - -/* Return iff a command is defined as "multi-line" (RFC 1939), - * has a response terminated by a last line with a '.'. - */ -static bool pop3_is_multiline(const char *cmdline) -{ - size_t i; - for(i = 0; i < ARRAYSIZE(pop3cmds); ++i) { - if(strncasecompare(pop3cmds[i].name, cmdline, pop3cmds[i].nlen)) { - if(!cmdline[pop3cmds[i].nlen]) - return pop3cmds[i].multiline; - else if(cmdline[pop3cmds[i].nlen] == ' ') - return pop3cmds[i].multiline_with_args; - } - } - /* Unknown command, assume multi-line for backward compatibility with - * earlier curl versions that only could do multi-line responses. */ - return TRUE; -} - /*********************************************************************** * * pop3_endofresp() @@ -310,8 +251,8 @@ static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn, */ static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out) { - char *message = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf); - size_t len = data->conn->proto.pop3c.pp.nfinal; + char *message = data->state.buffer; + size_t len = strlen(message); if(len > 2) { /* Find the start of the message */ @@ -462,7 +403,7 @@ static CURLcode pop3_perform_user(struct Curl_easy *data, CURLcode result = CURLE_OK; /* Check we have a username and password to authenticate with and end the - connect phase if we do not */ + connect phase if we don't */ if(!data->state.aptr.user) { pop3_state(data, POP3_STOP); @@ -496,7 +437,7 @@ static CURLcode pop3_perform_apop(struct Curl_easy *data, char secret[2 * MD5_DIGEST_LEN + 1]; /* Check we have a username and password to authenticate with and end the - connect phase if we do not */ + connect phase if we don't */ if(!data->state.aptr.user) { pop3_state(data, POP3_STOP); @@ -606,7 +547,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data, saslprogress progress = SASL_IDLE; /* Check we have enough data to authenticate with and end the - connect phase if we do not */ + connect phase if we don't */ if(!Curl_sasl_can_authenticate(&pop3c->sasl, data)) { pop3_state(data, POP3_STOP); return result; @@ -665,20 +606,18 @@ static CURLcode pop3_perform_command(struct Curl_easy *data) else command = "RETR"; - if(pop3->custom && pop3->custom[0] != '\0') - command = pop3->custom; - /* Send the command */ if(pop3->id[0] != '\0') result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s %s", - command, pop3->id); + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command), pop3->id); else - result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", command); + result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command)); - if(!result) { + if(!result) pop3_state(data, POP3_COMMAND); - data->req.no_body = !pop3_is_multiline(command); - } return result; } @@ -709,8 +648,8 @@ static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; - const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf); - size_t len = data->conn->proto.pop3c.pp.nfinal; + const char *line = data->state.buffer; + size_t len = strlen(line); (void)instate; /* no use for this yet */ @@ -718,35 +657,44 @@ static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data, failf(data, "Got unexpected pop3-server response"); result = CURLE_WEIRD_SERVER_REPLY; } - else if(len > 3) { + else { /* Does the server support APOP authentication? */ - char *lt; - char *gt = NULL; - - /* Look for the APOP timestamp */ - lt = memchr(line, '<', len); - if(lt) - /* search the remainder for '>' */ - gt = memchr(lt, '>', len - (lt - line)); - if(gt) { - /* the length of the timestamp, including the brackets */ - size_t timestamplen = gt - lt + 1; - char *at = memchr(lt, '@', timestamplen); - /* If the timestamp does not contain '@' it is not (as required by - RFC-1939) conformant to the RFC-822 message id syntax, and we - therefore do not use APOP authentication. */ - if(at) { - /* dupe the timestamp */ - pop3c->apoptimestamp = Curl_memdup0(lt, timestamplen); - if(!pop3c->apoptimestamp) - return CURLE_OUT_OF_MEMORY; - /* Store the APOP capability */ - pop3c->authtypes |= POP3_TYPE_APOP; + if(len >= 4 && line[len - 2] == '>') { + /* Look for the APOP timestamp */ + size_t i; + for(i = 3; i < len - 2; ++i) { + if(line[i] == '<') { + /* Calculate the length of the timestamp */ + size_t timestamplen = len - 1 - i; + char *at; + if(!timestamplen) + break; + + /* Allocate some memory for the timestamp */ + pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1); + + if(!pop3c->apoptimestamp) + break; + + /* Copy the timestamp */ + memcpy(pop3c->apoptimestamp, line + i, timestamplen); + pop3c->apoptimestamp[timestamplen] = '\0'; + + /* If the timestamp does not contain '@' it is not (as required by + RFC-1939) conformant to the RFC-822 message id syntax, and we + therefore do not use APOP authentication. */ + at = strchr(pop3c->apoptimestamp, '@'); + if(!at) + Curl_safefree(pop3c->apoptimestamp); + else + /* Store the APOP capability */ + pop3c->authtypes |= POP3_TYPE_APOP; + break; + } } } - if(!result) - result = pop3_perform_capa(data, conn); + result = pop3_perform_capa(data, conn); } return result; @@ -759,8 +707,8 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; struct pop3_conn *pop3c = &conn->proto.pop3c; - const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf); - size_t len = data->conn->proto.pop3c.pp.nfinal; + const char *line = data->state.buffer; + size_t len = strlen(line); (void)instate; /* no use for this yet */ @@ -816,7 +764,7 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, } } else { - /* Clear text is supported when CAPA is not recognised */ + /* Clear text is supported when CAPA isn't recognised */ if(pop3code != '+') pop3c->authtypes |= POP3_TYPE_CLEARTEXT; @@ -847,7 +795,7 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data, (void)instate; /* no use for this yet */ /* Pipelining in response is forbidden. */ - if(data->conn->proto.pop3c.pp.overflow) + if(data->conn->proto.pop3c.pp.cache_size) return CURLE_WEIRD_SERVER_REPLY; if(pop3code != '+') { @@ -989,36 +937,31 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data, pop3c->eob = 2; /* But since this initial CR LF pair is not part of the actual body, we set - the strip counter here so that these bytes will not be delivered. */ + the strip counter here so that these bytes won't be delivered. */ pop3c->strip = 2; if(pop3->transfer == PPTRANSFER_BODY) { /* POP3 download */ - Curl_xfer_setup1(data, CURL_XFER_RECV, -1, FALSE); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); - if(pp->overflow) { - /* The recv buffer contains data that is actually body content so send - it as such. Note that there may even be additional "headers" after - the body */ - - /* keep only the overflow */ - Curl_dyn_tail(&pp->recvbuf, pp->overflow); - pp->nfinal = 0; /* done */ + if(pp->cache) { + /* The header "cache" contains a bunch of data that is actually body + content so send it as such. Note that there may even be additional + "headers" after the body */ if(!data->req.no_body) { - result = pop3_write(data, Curl_dyn_ptr(&pp->recvbuf), - Curl_dyn_len(&pp->recvbuf), FALSE); + result = Curl_pop3_write(data, pp->cache, pp->cache_size); if(result) return result; } - /* reset the buffer */ - Curl_dyn_reset(&pp->recvbuf); - pp->overflow = 0; + /* Free the cache */ + Curl_safefree(pp->cache); + + /* Reset the cache size */ + pp->cache_size = 0; } } - else - pp->overflow = 0; /* End of DO phase */ pop3_state(data, POP3_STOP); @@ -1030,6 +973,7 @@ static CURLcode pop3_statemachine(struct Curl_easy *data, struct connectdata *conn) { CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; int pop3code; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; @@ -1046,7 +990,7 @@ static CURLcode pop3_statemachine(struct Curl_easy *data, do { /* Read the response from the server */ - result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &pop3code, &nread); + result = Curl_pp_readresp(data, sock, pp, &pop3code, &nread); if(result) return result; @@ -1187,7 +1131,8 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done) Curl_sasl_init(&pop3c->sasl, data, &saslpop3); /* Initialise the pingpong layer */ - Curl_pp_init(pp); + Curl_pp_setup(pp); + Curl_pp_init(data, pp); /* Parse the URL options */ result = pop3_parse_url_options(conn); @@ -1505,13 +1450,12 @@ static CURLcode pop3_parse_custom_request(struct Curl_easy *data) /*********************************************************************** * - * pop3_write() + * Curl_pop3_write() * * This function scans the body after the end-of-body and writes everything * until the end is found. */ -static CURLcode pop3_write(struct Curl_easy *data, const char *str, - size_t nread, bool is_eos) +CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread) { /* This code could be made into a special function in the handler struct */ CURLcode result = CURLE_OK; @@ -1521,7 +1465,6 @@ static CURLcode pop3_write(struct Curl_easy *data, const char *str, bool strip_dot = FALSE; size_t last = 0; size_t i; - (void)is_eos; /* Search through the buffer looking for the end-of-body marker which is 5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches @@ -1537,7 +1480,7 @@ static CURLcode pop3_write(struct Curl_easy *data, const char *str, pop3c->eob++; if(i) { - /* Write out the body part that did not match */ + /* Write out the body part that didn't match */ result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last], i - last); @@ -1550,7 +1493,7 @@ static CURLcode pop3_write(struct Curl_easy *data, const char *str, else if(pop3c->eob == 3) pop3c->eob++; else - /* If the character match was not at position 0 or 3 then restart the + /* If the character match wasn't at position 0 or 3 then restart the pattern matching */ pop3c->eob = 1; break; @@ -1559,7 +1502,7 @@ static CURLcode pop3_write(struct Curl_easy *data, const char *str, if(pop3c->eob == 1 || pop3c->eob == 4) pop3c->eob++; else - /* If the character match was not at position 1 or 4 then start the + /* If the character match wasn't at position 1 or 4 then start the search again */ pop3c->eob = 0; break; @@ -1573,7 +1516,7 @@ static CURLcode pop3_write(struct Curl_easy *data, const char *str, pop3c->eob = 0; } else - /* If the character match was not at position 2 then start the search + /* If the character match wasn't at position 2 then start the search again */ pop3c->eob = 0; break; |