mirror of
https://bitbucket.org/jsuto/piler.git
synced 2024-11-07 23:31:58 +01:00
fixing a parser bug in process_imap_folder()
This commit is contained in:
parent
5ee5644ae7
commit
ec0f324601
197
src/imap.c
197
src/imap.c
@ -38,16 +38,58 @@ unsigned long resolve_host(char *host){
|
||||
}
|
||||
|
||||
|
||||
int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, struct __config *cfg){
|
||||
int rc=ERR, i, n, pos, messages=0, len, readlen, fd;
|
||||
char *p, *q, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], buf[MAXBUFSIZE], puf[MAXBUFSIZE], filename[SMALLBUFSIZE];
|
||||
int get_message_length_from_imap_answer(char *s, int *_1st_line_bytes){
|
||||
char *p, *q;
|
||||
int len=0;
|
||||
|
||||
|
||||
p = strstr(s, "\r\n");
|
||||
if(!p){
|
||||
printf("invalid reply: %s", s);
|
||||
return len;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
*_1st_line_bytes = strlen(s)+2;
|
||||
|
||||
if(*(p-1) == '}') *(p-1) = '\0';
|
||||
|
||||
|
||||
q = strchr(s, '{');
|
||||
if(q){
|
||||
q++;
|
||||
len = atoi(q);
|
||||
}
|
||||
|
||||
*(p-1) = '}';
|
||||
*p = '\r';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int is_last_complete_packet(char *s, int len, char *tagok, char *tagbad){
|
||||
|
||||
if(*(s+len-2) == '\r' && *(s+len-1) == '\n'){
|
||||
if(strstr(s, tagok)) return 1;
|
||||
if(strstr(s, tagbad)) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, struct __config *cfg){
|
||||
int rc=ERR, i, n, pos, messages=0, len, readlen, fd, lastpos, nreads, processed_messages=0;
|
||||
char *p, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], tagbad[SMALLBUFSIZE], buf[MAXBUFSIZE], filename[SMALLBUFSIZE];
|
||||
char aggrbuf[3*MAXBUFSIZE];
|
||||
|
||||
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "\r\nA%d OK", (*seq)++);
|
||||
snprintf(buf, sizeof(buf)-1, "%s SELECT %s\r\n", tag, folder);
|
||||
snprintf(buf, sizeof(buf)-1, "%s SELECT \"%s\"\r\n", tag, folder);
|
||||
send(sd, buf, strlen(buf), 0);
|
||||
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
|
||||
|
||||
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
|
||||
|
||||
if(!strstr(buf, tagok)){
|
||||
trimBuffer(buf);
|
||||
@ -55,27 +97,28 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
p = &buf[0];
|
||||
do {
|
||||
memset(puf, 0, sizeof(puf));
|
||||
p = split(p, '\n', puf, sizeof(puf)-1);
|
||||
|
||||
q = strstr(puf, " EXISTS");
|
||||
if(q){
|
||||
*q = '\0';
|
||||
messages = atoi(puf+2);
|
||||
p = strstr(buf, " EXISTS");
|
||||
if(p){
|
||||
*p = '\0';
|
||||
p = strrchr(buf, '\n');
|
||||
if(p){
|
||||
while(!isdigit(*p)){ p++; }
|
||||
messages = atoi(p);
|
||||
}
|
||||
|
||||
} while(p);
|
||||
|
||||
}
|
||||
|
||||
printf("found %d messages\n", messages);
|
||||
|
||||
if(messages <= 0) return rc;
|
||||
for(i=1; i<=messages; i++){
|
||||
|
||||
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "\r\nA%d OK", (*seq)++);
|
||||
for(i=1; i<=messages; i++){
|
||||
printf("processed: %7d\r", processed_messages); fflush(stdout);
|
||||
processed_messages++;
|
||||
|
||||
snprintf(tag, sizeof(tag)-1, "A%d", *seq);
|
||||
snprintf(tagok, sizeof(tagok)-1, "\r\nA%d OK", (*seq)++);
|
||||
snprintf(tagbad, sizeof(tagbad)-1, "\r\n%s BAD", tag);
|
||||
|
||||
snprintf(buf, sizeof(buf)-1, "%s FETCH %d (BODY.PEEK[])\r\n", tag, i);
|
||||
|
||||
snprintf(filename, sizeof(filename)-1, "%s-%d.txt", folder, i);
|
||||
@ -89,69 +132,59 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
|
||||
|
||||
|
||||
send(sd, buf, strlen(buf), 0);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
|
||||
|
||||
readlen = 0;
|
||||
pos = 0;
|
||||
len = 0;
|
||||
nreads = 0;
|
||||
|
||||
memset(aggrbuf, 0, sizeof(aggrbuf));
|
||||
lastpos = 0;
|
||||
|
||||
|
||||
len = 0; readlen = n;
|
||||
|
||||
p = strstr(buf, "\r\n");
|
||||
if(!p){
|
||||
printf("invalid reply: %s", buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
pos = strlen(buf) + 2;
|
||||
|
||||
|
||||
if(*(p-1) == '}') *(p-1) = '\0';
|
||||
|
||||
|
||||
q = strchr(buf, '{');
|
||||
if(q){
|
||||
q++;
|
||||
len = atoi(q);
|
||||
}
|
||||
|
||||
if(len < 10){
|
||||
printf("too short message: %s\n", buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
n -= pos;
|
||||
|
||||
q = strstr(p+2, tagok);
|
||||
if(q){
|
||||
n -= strlen(q) + 1;
|
||||
}
|
||||
|
||||
|
||||
write(fd, p+2, n);
|
||||
|
||||
|
||||
while(readlen < len){
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = recvtimeout(sd, buf, MAXBUFSIZE, 3);
|
||||
while((n = recvtimeout(sd, buf, sizeof(buf), 15)) > 0){
|
||||
nreads++;
|
||||
readlen += n;
|
||||
|
||||
p = strstr(buf, tagok);
|
||||
if(p){
|
||||
n -= strlen(p)+1;
|
||||
if(nreads == 1){
|
||||
len = get_message_length_from_imap_answer(buf, &pos);
|
||||
|
||||
if(len < 10){
|
||||
printf("%d: too short message! %s\n", i, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
write(fd, buf, n);
|
||||
|
||||
}
|
||||
if(lastpos + n + sizeof(buf) > sizeof(aggrbuf)){
|
||||
write(fd, aggrbuf, lastpos);
|
||||
memset(aggrbuf, 0, sizeof(aggrbuf));
|
||||
lastpos = 0;
|
||||
}
|
||||
|
||||
memcpy(aggrbuf+lastpos, buf, n);
|
||||
lastpos += n;
|
||||
|
||||
if(is_last_complete_packet(aggrbuf, lastpos, tagok, tagbad) == 1){
|
||||
write(fd, aggrbuf, lastpos);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
write(fd, aggrbuf, lastpos-n);
|
||||
memmove(aggrbuf, aggrbuf+lastpos-n, n);
|
||||
lastpos = n;
|
||||
memset(aggrbuf+lastpos, 0, sizeof(aggrbuf)-lastpos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
close(fd);
|
||||
|
||||
rc = import_message(filename, sdata, data, cfg);
|
||||
|
||||
unlink(filename);
|
||||
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -180,7 +213,6 @@ int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, c
|
||||
}
|
||||
|
||||
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
|
||||
//printf("connected...\n");
|
||||
|
||||
|
||||
/*
|
||||
@ -209,8 +241,6 @@ int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, c
|
||||
return ERR;
|
||||
}
|
||||
|
||||
//printf("logged in...\n");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -219,11 +249,9 @@ int list_folders(int sd, int *seq, char *folders, int foldersize){
|
||||
int n;
|
||||
char *p, *q, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], buf[MAXBUFSIZE], puf[MAXBUFSIZE];
|
||||
|
||||
snprintf(folders, foldersize-1, "INBOX");
|
||||
|
||||
|
||||
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "A%d OK", (*seq)++);
|
||||
snprintf(buf, sizeof(buf)-1, "%s LIST \"\" %%\r\n", tag);
|
||||
//snprintf(buf, sizeof(buf)-1, "%s LIST \"\" %%\r\n", tag);
|
||||
snprintf(buf, sizeof(buf)-1, "%s LIST \"\" \"*\"\r\n", tag);
|
||||
|
||||
send(sd, buf, strlen(buf), 0);
|
||||
|
||||
@ -236,15 +264,17 @@ int list_folders(int sd, int *seq, char *folders, int foldersize){
|
||||
trimBuffer(puf);
|
||||
|
||||
if(strncmp(puf, "* LIST ", 7) == 0){
|
||||
q = strrchr(puf, ' ');
|
||||
q = strstr(puf, "\".\"");
|
||||
if(q){
|
||||
if(*(q+1) == '"') q += 2;
|
||||
if(puf[strlen(puf)-1] == '"') puf[strlen(puf)-1] = '\0';
|
||||
q += 3;
|
||||
|
||||
if(*q == ' ') q++;
|
||||
if(*q == '"') q++;
|
||||
|
||||
if(strncasecmp(q, "junk", 4) && strncasecmp(q, "trash", 5) && strncasecmp(q, "spam", 4) && strncasecmp(q, "draft", 5)){
|
||||
strncat(folders, "\n", foldersize-1);
|
||||
strncat(folders, q, foldersize-1);
|
||||
}
|
||||
if(q[strlen(q)-1] == '"') q[strlen(q)-1] = '\0';
|
||||
|
||||
strncat(folders, "\n", foldersize-1);
|
||||
strncat(folders, q, foldersize-1);
|
||||
|
||||
}
|
||||
}
|
||||
@ -254,7 +284,6 @@ int list_folders(int sd, int *seq, char *folders, int foldersize){
|
||||
|
||||
} while(p);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
#define SKIPLIST "junk,trash,spam,draft"
|
||||
|
||||
int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, char *password);
|
||||
int list_folders(int sd, int *seq, char *folders, int foldersize);
|
||||
@ -123,11 +124,12 @@ int import_from_maildir(char *directory, struct session_data *sdata, struct __da
|
||||
}
|
||||
|
||||
|
||||
int import_from_imap_server(char *imapserver, char *username, char *password, struct session_data *sdata, struct __data *data, struct __config *cfg){
|
||||
int rc=ERR, ret=OK, sd, seq=1;
|
||||
char *p, puf[MAXBUFSIZE];
|
||||
int import_from_imap_server(char *imapserver, char *username, char *password, struct session_data *sdata, struct __data *data, char *skiplist, struct __config *cfg){
|
||||
int rc=ERR, ret=OK, sd, seq=1, skipmatch;
|
||||
char *p, puf[SMALLBUFSIZE];
|
||||
char *q, muf[SMALLBUFSIZE];
|
||||
char folders[MAXBUFSIZE];
|
||||
|
||||
|
||||
if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
|
||||
printf("cannot create socket\n");
|
||||
return ERR;
|
||||
@ -147,6 +149,27 @@ int import_from_imap_server(char *imapserver, char *username, char *password, st
|
||||
memset(puf, 0, sizeof(puf));
|
||||
p = split(p, '\n', puf, sizeof(puf)-1);
|
||||
|
||||
if(strlen(puf) < 1) continue;
|
||||
|
||||
skipmatch = 0;
|
||||
|
||||
if(skiplist && strlen(skiplist) > 0){
|
||||
q = skiplist;
|
||||
do {
|
||||
memset(muf, 0, sizeof(muf));
|
||||
q = split(q, ',', muf, sizeof(muf)-1);
|
||||
if(strncasecmp(puf, muf, strlen(muf)) == 0){
|
||||
skipmatch = 1;
|
||||
break;
|
||||
}
|
||||
} while(q);
|
||||
}
|
||||
|
||||
if(skipmatch == 1){
|
||||
printf("SKIPPING FOLDER: %s\n", puf);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("processing folder: %s... ", puf);
|
||||
|
||||
rc = process_imap_folder(sd, &seq, puf, sdata, data, cfg);
|
||||
@ -170,13 +193,13 @@ void usage(){
|
||||
int main(int argc, char **argv){
|
||||
int i, rc=0;
|
||||
char *configfile=CONFIG_FILE, *mailbox=NULL, *emlfile=NULL, *directory=NULL;
|
||||
char *imapserver=NULL, *username=NULL, *password=NULL;
|
||||
char *imapserver=NULL, *username=NULL, *password=NULL, *skiplist=SKIPLIST;
|
||||
struct session_data sdata;
|
||||
struct __config cfg;
|
||||
struct __data data;
|
||||
|
||||
|
||||
while((i = getopt(argc, argv, "c:m:e:d:i:u:p:h?")) > 0){
|
||||
while((i = getopt(argc, argv, "c:m:e:d:i:u:p:x:h?")) > 0){
|
||||
switch(i){
|
||||
|
||||
case 'c' :
|
||||
@ -207,6 +230,10 @@ int main(int argc, char **argv){
|
||||
password = optarg;
|
||||
break;
|
||||
|
||||
case 'x' :
|
||||
skiplist = optarg;
|
||||
break;
|
||||
|
||||
case 'h' :
|
||||
case '?' :
|
||||
usage();
|
||||
@ -253,7 +280,7 @@ int main(int argc, char **argv){
|
||||
if(emlfile) rc = import_message(emlfile, &sdata, &data, &cfg);
|
||||
if(mailbox) rc = import_from_mailbox(mailbox, &sdata, &data, &cfg);
|
||||
if(directory) rc = import_from_maildir(directory, &sdata, &data, &cfg);
|
||||
if(imapserver && username && password) rc = import_from_imap_server(imapserver, username, password, &sdata, &data, &cfg);
|
||||
if(imapserver && username && password) rc = import_from_imap_server(imapserver, username, password, &sdata, &data, skiplist, &cfg);
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user