mirror of
https://github.com/curl/curl.git
synced 2025-09-28 06:56:50 +03:00
POP3: fixed escaped dot not being striped out
Changed the eob detection to work across the whole of the buffer so that lines that begin with a dot (which the server will have escaped) are passed to the client application correctly.
This commit is contained in:
parent
c92234c3bc
commit
bdb647814e
101
lib/pop3.c
101
lib/pop3.c
|
@ -1040,61 +1040,75 @@ CURLcode Curl_pop3_write(struct connectdata *conn,
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct SingleRequest *k = &data->req;
|
struct SingleRequest *k = &data->req;
|
||||||
|
|
||||||
/* Detect the end-of-body marker, which is 5 bytes:
|
|
||||||
0d 0a 2e 0d 0a. This marker can of course be spread out
|
|
||||||
over up to 5 different data chunks.
|
|
||||||
*/
|
|
||||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
|
bool strip_dot = FALSE;
|
||||||
|
size_t last = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
/* since the EOB string must be within the last 5 bytes, get the index
|
/* Search through the buffer looking for the end-of-body marker which is
|
||||||
position of where to start to scan for it */
|
5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches
|
||||||
size_t checkstart = (nread>POP3_EOB_LEN)?nread-POP3_EOB_LEN:0;
|
the eob so the server will have prefixed it with an extra dot which we
|
||||||
|
need to strip out. Additionally the marker could of course be spread out
|
||||||
if(checkstart) {
|
over 5 different data chunks */
|
||||||
/* write out the first piece, if any */
|
for(i = 0; i < nread; i++) {
|
||||||
result = Curl_client_write(conn, CLIENTWRITE_BODY, str, checkstart);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
pop3c->eob=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=checkstart; i<nread; i++) {
|
|
||||||
size_t prev = pop3c->eob;
|
size_t prev = pop3c->eob;
|
||||||
|
|
||||||
switch(str[i]) {
|
switch(str[i]) {
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
if((pop3c->eob == 0) || (pop3c->eob == 3))
|
if(pop3c->eob == 0) {
|
||||||
|
pop3c->eob++;
|
||||||
|
|
||||||
|
if(i) {
|
||||||
|
/* Write out the body part that didn't match */
|
||||||
|
result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
|
||||||
|
i - last);
|
||||||
|
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
last = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(pop3c->eob == 3)
|
||||||
pop3c->eob++;
|
pop3c->eob++;
|
||||||
else
|
else
|
||||||
/* if it wasn't 0 or 3, it restarts the pattern match again */
|
/* If the character match wasn't at position 0 or 3 then restart the
|
||||||
|
pattern matching */
|
||||||
pop3c->eob = 1;
|
pop3c->eob = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
if((pop3c->eob == 1) || (pop3c->eob == 4))
|
if(pop3c->eob == 1 || pop3c->eob == 4)
|
||||||
pop3c->eob++;
|
pop3c->eob++;
|
||||||
else
|
else
|
||||||
|
/* If the character match wasn't at position 1 or 4 then start the
|
||||||
|
search again */
|
||||||
pop3c->eob = 0;
|
pop3c->eob = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2e:
|
case 0x2e:
|
||||||
if(pop3c->eob == 2)
|
if(pop3c->eob == 2)
|
||||||
pop3c->eob++;
|
pop3c->eob++;
|
||||||
|
else if(pop3c->eob == 3) {
|
||||||
|
/* We have an extra dot after the CRLF which we need to strip off */
|
||||||
|
strip_dot = TRUE;
|
||||||
|
pop3c->eob = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
/* If the character match wasn't at position 2 then start the search
|
||||||
|
again */
|
||||||
pop3c->eob = 0;
|
pop3c->eob = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pop3c->eob = 0;
|
pop3c->eob = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(pop3c->eob == POP3_EOB_LEN) {
|
|
||||||
/* full match, the transfer is done! */
|
|
||||||
k->keepon &= ~KEEP_RECV;
|
|
||||||
pop3c->eob = 0;
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
else if(prev && (prev >= pop3c->eob)) {
|
|
||||||
|
|
||||||
/* strip can only be non-zero for the very first mismatch after CRLF and
|
/* Did we have a partial match which has subsequently failed? */
|
||||||
then both prev and strip are equal and nothing will be output
|
if(prev && prev >= pop3c->eob) {
|
||||||
|
/* Strip can only be non-zero for the very first mismatch after CRLF
|
||||||
|
and then both prev and strip are equal and nothing will be output
|
||||||
below */
|
below */
|
||||||
while(prev && pop3c->strip) {
|
while(prev && pop3c->strip) {
|
||||||
prev--;
|
prev--;
|
||||||
|
@ -1102,27 +1116,34 @@ CURLcode Curl_pop3_write(struct connectdata *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(prev) {
|
if(prev) {
|
||||||
/* write out the body part that didn't match */
|
/* If the partial match was the CRLF and dot then only write the CRLF
|
||||||
|
as the server would have inserted the dot */
|
||||||
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
|
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
|
||||||
prev);
|
strip_dot ? prev - 1 : prev);
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
last = i;
|
||||||
|
strip_dot = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pop3c->eob == POP3_EOB_LEN) {
|
||||||
|
/* We have a full match so the transfer is done! */
|
||||||
|
k->keepon &= ~KEEP_RECV;
|
||||||
|
pop3c->eob = 0;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if(pop3c->eob)
|
if(pop3c->eob)
|
||||||
/* while EOB is matching, don't output it! */
|
/* While EOB is matching nothing should be output */
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
while(nread && pop3c->strip) {
|
if(nread - last) {
|
||||||
nread--;
|
result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
|
||||||
pop3c->strip--;
|
nread - last);
|
||||||
str++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nread) {
|
|
||||||
result = Curl_client_write(conn, CLIENTWRITE_BODY, str, nread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user