mirror of
https://github.com/curl/curl.git
synced 2025-04-18 16:30:45 +08:00
POP3: fix multi-line responses
Some POP3 commands are multi-line, e.g. have responses terminated by a last line with '.', but some are not. Define the known command properties and fix response handling. Add test case for STAT. Fixes #14677 Reported-by: ralfjunker on github Closes #14707
This commit is contained in:
parent
bc81292ea6
commit
4cd10ee28b
65
lib/pop3.c
65
lib/pop3.c
@ -83,6 +83,10 @@
|
||||
#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);
|
||||
@ -199,6 +203,53 @@ 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, TRUE },
|
||||
{ "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()
|
||||
@ -614,18 +665,20 @@ 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",
|
||||
(pop3->custom && pop3->custom[0] != '\0' ?
|
||||
pop3->custom : command), pop3->id);
|
||||
command, pop3->id);
|
||||
else
|
||||
result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s",
|
||||
(pop3->custom && pop3->custom[0] != '\0' ?
|
||||
pop3->custom : command));
|
||||
result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", command);
|
||||
|
||||
if(!result)
|
||||
if(!result) {
|
||||
pop3_state(data, POP3_COMMAND);
|
||||
data->req.no_body = !pop3_is_multiline(command);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ test961 test962 test963 test964 test965 test966 test967 test968 test969 \
|
||||
test970 test971 test972 test973 test974 test975 test976 test977 test978 \
|
||||
test979 test980 test981 test982 test983 test984 test985 test986 test987 \
|
||||
test988 test989 test990 test991 test992 test993 test994 test995 test996 \
|
||||
\
|
||||
test997 \
|
||||
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
|
||||
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
|
||||
test1016 test1017 test1018 test1019 test1020 test1021 test1022 test1023 \
|
||||
|
47
tests/data/test997
Normal file
47
tests/data/test997
Normal file
@ -0,0 +1,47 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
POP3
|
||||
Clear Text
|
||||
STAT
|
||||
CUSTOMREQUEST
|
||||
RFC2449
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<servercmd>
|
||||
CAPA TOP USER
|
||||
</servercmd>
|
||||
<data>
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
pop3
|
||||
</server>
|
||||
<name>
|
||||
POP3 retrieve STAT (CUSTOMREQUEST)
|
||||
</name>
|
||||
<command>
|
||||
pop3://%HOSTIP:%POP3PORT -u user:secret -X 'STAT'
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
CAPA
|
||||
USER user
|
||||
PASS secret
|
||||
STAT
|
||||
QUIT
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
Loading…
x
Reference in New Issue
Block a user