imap protocol fix

This commit is contained in:
SJ 2014-07-08 15:16:23 +02:00
parent bbd81faf0b
commit 5411414981
2 changed files with 50 additions and 66 deletions

View File

@ -14,7 +14,7 @@
#define VERSION "0.1.25-rc3" #define VERSION "0.1.25-rc3"
#define BUILD 878 #define BUILD 879
#define HOSTID "mailarchiver" #define HOSTID "mailarchiver"

View File

@ -26,12 +26,11 @@
void update_import_job_stat(struct session_data *sdata, struct __data *data); void update_import_job_stat(struct session_data *sdata, struct __data *data);
int get_message_length_from_imap_answer(char *s, int *_1st_line_bytes){ int get_message_length_from_imap_answer(char *s){
char *p, *q; char *p, *q;
int len=0; int len=0;
p = strstr(s, "\r");
p = strstr(s, "\r\n");
if(!p){ if(!p){
printf("invalid reply: %s", s); printf("invalid reply: %s", s);
return len; return len;
@ -39,9 +38,6 @@ int get_message_length_from_imap_answer(char *s, int *_1st_line_bytes){
*p = '\0'; *p = '\0';
//*_1st_line_bytes = strlen(s)+2;
*_1st_line_bytes = p-s+2;
if(*(p-1) == '}') *(p-1) = '\0'; if(*(p-1) == '}') *(p-1) = '\0';
@ -58,24 +54,6 @@ int get_message_length_from_imap_answer(char *s, int *_1st_line_bytes){
} }
int is_last_complete_packet(char *s, int len, char *tagok, char *tagbad, int *pos){
char *p;
*pos = 0;
if(*(s+len-2) == '\r' && *(s+len-1) == '\n'){
if((p = strstr(s, tagok))){
*pos = p - s;
if(*pos > 0) *pos -= 1;
return 1;
}
if(strstr(s, tagbad)) return 1;
}
return 0;
}
int read_response(int sd, char *buf, int buflen, int *seq, struct __data *data, int use_ssl){ int read_response(int sd, char *buf, int buflen, int *seq, struct __data *data, int use_ssl){
int i=0, n, len=0, rc=0; int i=0, n, len=0, rc=0;
char puf[MAXBUFSIZE], tagok[SMALLBUFSIZE], tagno[SMALLBUFSIZE]; char puf[MAXBUFSIZE], tagok[SMALLBUFSIZE], tagno[SMALLBUFSIZE];
@ -109,9 +87,8 @@ END:
int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, int use_ssl, int dryrun, struct __config *cfg){ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, int use_ssl, int dryrun, struct __config *cfg){
int rc=ERR, i, n, pos, endpos, messages=0, len, readlen, fd, lastpos, nreads; int rc=ERR, i, n, messages=0, len, readlen, fd, nreads, readpos, finished, msglen, msg_written_len, tagoklen, tagbadlen;
char *p, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], tagbad[SMALLBUFSIZE], buf[MAXBUFSIZE], filename[SMALLBUFSIZE]; char *p, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], tagbad[SMALLBUFSIZE], buf[MAXBUFSIZE], puf[MAXBUFSIZE], filename[SMALLBUFSIZE];
char aggrbuf[3*MAXBUFSIZE];
/* imap cmd: SELECT */ /* imap cmd: SELECT */
@ -145,8 +122,11 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
printf("processed: %7d\r", data->import->processed_messages); fflush(stdout); printf("processed: %7d\r", data->import->processed_messages); fflush(stdout);
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tag, sizeof(tag)-1, "A%d", *seq);
snprintf(tagok, sizeof(tagok)-1, "\r\nA%d OK", (*seq)++); snprintf(tagok, sizeof(tagok)-1, "A%d OK", (*seq)++);
snprintf(tagbad, sizeof(tagbad)-1, "\r\n%s BAD", tag); snprintf(tagbad, sizeof(tagbad)-1, "%s BAD", tag);
tagoklen = strlen(tagok);
tagbadlen = strlen(tagbad);
snprintf(buf, sizeof(buf)-1, "%s FETCH %d (BODY.PEEK[])\r\n", tag, i); snprintf(buf, sizeof(buf)-1, "%s FETCH %d (BODY.PEEK[])\r\n", tag, i);
@ -163,56 +143,60 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
n = write1(sd, buf, strlen(buf), use_ssl, data->ssl); n = write1(sd, buf, strlen(buf), use_ssl, data->ssl);
readlen = 0; readlen = 0;
pos = 0;
len = 0;
nreads = 0; nreads = 0;
endpos = 0; readpos = 0;
finished = 0;
msglen = 0;
msg_written_len = 0;
memset(aggrbuf, 0, sizeof(aggrbuf)); while((n = recvtimeoutssl(sd, &buf[readpos], sizeof(buf)-readpos, 15, use_ssl, data->ssl)) > 0){
lastpos = 0;
while((n = recvtimeoutssl(sd, buf, sizeof(buf), 15, use_ssl, data->ssl)) > 0){
nreads++;
readlen += n; readlen += n;
if(nreads == 1){ if(strchr(buf, '\n')){
len = get_message_length_from_imap_answer(buf, &pos); readpos = 0;
p = &buf[0];
do {
nreads++;
memset(puf, 0, sizeof(puf));
p = split(p, '\n', puf, sizeof(puf)-1);
len = strlen(puf);
if(len < 10){ if(nreads == 1){
printf("%d: too short message! %s\n", i, buf); msglen = get_message_length_from_imap_answer(puf);
break; continue;
} }
}
if(lastpos + 1 + n < sizeof(aggrbuf)){ if(len > 0){
if(msg_written_len < msglen){
write(fd, puf, len);
write(fd, "\n", 1);
msg_written_len += len + 1;
}
}
if(nreads == 1){ if(strncmp(puf, tagok, tagoklen) == 0){
memcpy(aggrbuf+lastpos, buf+pos, n-pos); finished = 1;
lastpos += n-pos; break;
} }
else {
memcpy(aggrbuf+lastpos, buf, n); if(strncmp(puf, tagbad, tagbadlen) == 0){
lastpos += n; printf("ERROR happened reading the message!\n");
} finished = 1;
break;
}
} while(p);
} }
else { else {
write(fd, aggrbuf, sizeof(buf)); readpos += n;
memmove(aggrbuf, aggrbuf+sizeof(buf), lastpos-sizeof(buf));
lastpos -= sizeof(buf);
memcpy(aggrbuf+lastpos, buf, n);
lastpos += n;
}
if(is_last_complete_packet(aggrbuf, lastpos, tagok, tagbad, &endpos) == 1){
write(fd, aggrbuf, lastpos-(lastpos-endpos));
break;
} }
if(finished == 1) break;
} }
close(fd); close(fd);
if(dryrun == 0) rc = import_message(filename, sdata, data, cfg); if(dryrun == 0) rc = import_message(filename, sdata, data, cfg);