aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/lib/pop3.c
diff options
context:
space:
mode:
authorMaxim Yurchuk <maxim-yurchuk@ydb.tech>2024-10-18 20:31:38 +0300
committerGitHub <noreply@github.com>2024-10-18 20:31:38 +0300
commit2a74bac2d2d3bccb4e10120f1ead805640ec9dd0 (patch)
tree047e4818ced5aaf73f58517629e5260b5291f9f0 /contrib/libs/curl/lib/pop3.c
parent2d9656823e9521d8c29ea4c9a1d0eab78391abfc (diff)
parent3d834a1923bbf9403cd4a448e7f32b670aa4124f (diff)
downloadydb-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.c211
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;