Refactored pop3 download function to fix a dot stuffing error

Signed-off-by: Janos SUTO <sj@acts.hu>
This commit is contained in:
Janos SUTO 2021-07-03 16:21:48 +02:00
parent 0b18c6060f
commit 9745b078f5

View File

@ -23,16 +23,6 @@
#include <piler.h> #include <piler.h>
int is_last_complete_pop3_packet(char *s, int len){
if(*(s+len-5) == '\r' && *(s+len-4) == '\n' && *(s+len-3) == '.' && *(s+len-2) == '\r' && *(s+len-1) == '\n'){
return 1;
}
return 0;
}
int connect_to_pop3_server(struct data *data){ int connect_to_pop3_server(struct data *data){
char buf[MAXBUFSIZE]; char buf[MAXBUFSIZE];
@ -86,66 +76,79 @@ void get_number_of_total_messages(struct data *data){
int pop3_download_email(struct data *data, int i){ int pop3_download_email(struct data *data, int i){
int n, fd, pos=0, lastpos=0, nreads=0; char *p, buf[MAXBUFSIZE], savedbuf[MAXBUFSIZE], copybuf[2*MAXBUFSIZE];
char *p, buf[MAXBUFSIZE];
char aggrbuf[3*MAXBUFSIZE];
data->import->processed_messages++; data->import->processed_messages++;
snprintf(data->import->filename, SMALLBUFSIZE-1, "pop3-tmp-%d-%d.txt", getpid(), i); snprintf(data->import->filename, SMALLBUFSIZE-1, "pop3-tmp-%d-%d.txt", getpid(), i);
unlink(data->import->filename); unlink(data->import->filename);
fd = open(data->import->filename, O_CREAT|O_EXCL|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); int fd = open(data->import->filename, O_CREAT|O_EXCL|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
if(fd == -1){ if(fd == -1){
printf("cannot open: %s\n", data->import->filename); printf("cannot open: %s\n", data->import->filename);
return ERR; return ERR;
} }
memset(savedbuf, 0, sizeof(savedbuf));
snprintf(buf, sizeof(buf)-1, "RETR %d\r\n", i); snprintf(buf, sizeof(buf)-1, "RETR %d\r\n", i);
write1(data->net, buf, strlen(buf)); write1(data->net, buf, strlen(buf));
memset(aggrbuf, 0, sizeof(aggrbuf)); int nlines = 0;
int endofmessage = 0;
int savedlen = 0;
int n = 0;
while((n = recvtimeoutssl(data->net, buf, sizeof(buf))) > 0){ while((n = recvtimeoutssl(data->net, buf, sizeof(buf))) > 0){
nreads++; if(savedlen){
memset(copybuf, 0, sizeof(copybuf));
memcpy(copybuf, savedbuf, savedlen);
memcpy(&copybuf[savedlen], buf, n);
if(nreads == 1){ savedlen = 0;
memset(savedbuf, 0, sizeof(savedbuf));
if(strncmp(buf, "+OK", 3) == 0){
p = strchr(&buf[3], '\n');
if(p){
*p = '\0';
pos = strlen(buf)+1;
*p = '\n';
}
}
else { printf("error: %s", buf); return ERR; }
p = &copybuf[0];
} else {
p = &buf[0];
} }
if((uint)(lastpos + 1 + n) < sizeof(aggrbuf)){ int puflen=0;
int rc=OK;
do {
char puf[MAXBUFSIZE];
if(nreads == 1){ puflen = read_one_line(p, '\n', puf, sizeof(puf)-1, &rc);
memcpy(aggrbuf+lastpos, buf+pos, n-pos); nlines++;
lastpos += n-pos;
}
else {
memcpy(aggrbuf+lastpos, buf, n);
lastpos += n;
}
}
else {
if(write(fd, aggrbuf, sizeof(buf)) == -1) printf("ERROR: writing to fd\n");
memmove(aggrbuf, aggrbuf+sizeof(buf), lastpos-sizeof(buf)); if(nlines == 1){
lastpos -= sizeof(buf); if(strncmp(puf, "+OK", 3)){
printf("error: %s", puf);
memcpy(aggrbuf+lastpos, buf, n); return ERR;
lastpos += n; }
} else {
if(puf[puflen-1] == '\n'){
if(puflen == 3 && puf[0] == '.' && puf[1] == '\r' && puf[2] == '\n'){
endofmessage = 1;
break;
} }
if(is_last_complete_pop3_packet(aggrbuf, lastpos) == 1){ int dotstuff = 0;
if(write(fd, aggrbuf, lastpos-3) == -1) printf("ERROR: writing to fd\n"); if(puf[0] == '.' && puf[1] != '\r' && puf[1] != '\n') dotstuff = 1;
if(write(fd, &puf[dotstuff], puflen-dotstuff) == -1) printf("ERROR: writing to fd\n");
} else if(puflen > 0) {
savedlen = puflen;
snprintf(savedbuf, sizeof(savedbuf)-1, "%s", puf);
}
}
p += puflen;
} while(puflen > 0);
if(endofmessage){
break; break;
} }
} }