mirror of
https://bitbucket.org/jsuto/piler.git
synced 2024-12-25 07:40:12 +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 get_message_length_from_imap_answer(char *s, int *_1st_line_bytes){
|
||||||
int rc=ERR, i, n, pos, messages=0, len, readlen, fd;
|
char *p, *q;
|
||||||
char *p, *q, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], buf[MAXBUFSIZE], puf[MAXBUFSIZE], filename[SMALLBUFSIZE];
|
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(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);
|
send(sd, buf, strlen(buf), 0);
|
||||||
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
|
|
||||||
|
|
||||||
|
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
|
||||||
|
|
||||||
if(!strstr(buf, tagok)){
|
if(!strstr(buf, tagok)){
|
||||||
trimBuffer(buf);
|
trimBuffer(buf);
|
||||||
@ -55,27 +97,28 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p = strstr(buf, " EXISTS");
|
||||||
p = &buf[0];
|
if(p){
|
||||||
do {
|
*p = '\0';
|
||||||
memset(puf, 0, sizeof(puf));
|
p = strrchr(buf, '\n');
|
||||||
p = split(p, '\n', puf, sizeof(puf)-1);
|
if(p){
|
||||||
|
while(!isdigit(*p)){ p++; }
|
||||||
q = strstr(puf, " EXISTS");
|
messages = atoi(p);
|
||||||
if(q){
|
|
||||||
*q = '\0';
|
|
||||||
messages = atoi(puf+2);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} while(p);
|
|
||||||
|
|
||||||
|
|
||||||
printf("found %d messages\n", messages);
|
printf("found %d messages\n", messages);
|
||||||
|
|
||||||
if(messages <= 0) return rc;
|
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(buf, sizeof(buf)-1, "%s FETCH %d (BODY.PEEK[])\r\n", tag, i);
|
||||||
|
|
||||||
snprintf(filename, sizeof(filename)-1, "%s-%d.txt", folder, 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);
|
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;
|
while((n = recvtimeout(sd, buf, sizeof(buf), 15)) > 0){
|
||||||
|
nreads++;
|
||||||
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);
|
|
||||||
readlen += n;
|
readlen += n;
|
||||||
|
|
||||||
p = strstr(buf, tagok);
|
if(nreads == 1){
|
||||||
if(p){
|
len = get_message_length_from_imap_answer(buf, &pos);
|
||||||
n -= strlen(p)+1;
|
|
||||||
|
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);
|
close(fd);
|
||||||
|
|
||||||
rc = import_message(filename, sdata, data, cfg);
|
rc = import_message(filename, sdata, data, cfg);
|
||||||
|
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
return OK;
|
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);
|
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;
|
return ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("logged in...\n");
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,11 +249,9 @@ int list_folders(int sd, int *seq, char *folders, int foldersize){
|
|||||||
int n;
|
int n;
|
||||||
char *p, *q, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], buf[MAXBUFSIZE], puf[MAXBUFSIZE];
|
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(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);
|
send(sd, buf, strlen(buf), 0);
|
||||||
|
|
||||||
@ -236,15 +264,17 @@ int list_folders(int sd, int *seq, char *folders, int foldersize){
|
|||||||
trimBuffer(puf);
|
trimBuffer(puf);
|
||||||
|
|
||||||
if(strncmp(puf, "* LIST ", 7) == 0){
|
if(strncmp(puf, "* LIST ", 7) == 0){
|
||||||
q = strrchr(puf, ' ');
|
q = strstr(puf, "\".\"");
|
||||||
if(q){
|
if(q){
|
||||||
if(*(q+1) == '"') q += 2;
|
q += 3;
|
||||||
if(puf[strlen(puf)-1] == '"') puf[strlen(puf)-1] = '\0';
|
|
||||||
|
if(*q == ' ') q++;
|
||||||
|
if(*q == '"') q++;
|
||||||
|
|
||||||
if(strncasecmp(q, "junk", 4) && strncasecmp(q, "trash", 5) && strncasecmp(q, "spam", 4) && strncasecmp(q, "draft", 5)){
|
if(q[strlen(q)-1] == '"') q[strlen(q)-1] = '\0';
|
||||||
strncat(folders, "\n", foldersize-1);
|
|
||||||
strncat(folders, q, foldersize-1);
|
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);
|
} while(p);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
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 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);
|
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 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;
|
int rc=ERR, ret=OK, sd, seq=1, skipmatch;
|
||||||
char *p, puf[MAXBUFSIZE];
|
char *p, puf[SMALLBUFSIZE];
|
||||||
|
char *q, muf[SMALLBUFSIZE];
|
||||||
char folders[MAXBUFSIZE];
|
char folders[MAXBUFSIZE];
|
||||||
|
|
||||||
if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
|
if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
|
||||||
printf("cannot create socket\n");
|
printf("cannot create socket\n");
|
||||||
return ERR;
|
return ERR;
|
||||||
@ -147,6 +149,27 @@ int import_from_imap_server(char *imapserver, char *username, char *password, st
|
|||||||
memset(puf, 0, sizeof(puf));
|
memset(puf, 0, sizeof(puf));
|
||||||
p = split(p, '\n', puf, sizeof(puf)-1);
|
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);
|
printf("processing folder: %s... ", puf);
|
||||||
|
|
||||||
rc = process_imap_folder(sd, &seq, puf, sdata, data, cfg);
|
rc = process_imap_folder(sd, &seq, puf, sdata, data, cfg);
|
||||||
@ -170,13 +193,13 @@ void usage(){
|
|||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
int i, rc=0;
|
int i, rc=0;
|
||||||
char *configfile=CONFIG_FILE, *mailbox=NULL, *emlfile=NULL, *directory=NULL;
|
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 session_data sdata;
|
||||||
struct __config cfg;
|
struct __config cfg;
|
||||||
struct __data data;
|
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){
|
switch(i){
|
||||||
|
|
||||||
case 'c' :
|
case 'c' :
|
||||||
@ -207,6 +230,10 @@ int main(int argc, char **argv){
|
|||||||
password = optarg;
|
password = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'x' :
|
||||||
|
skiplist = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h' :
|
case 'h' :
|
||||||
case '?' :
|
case '?' :
|
||||||
usage();
|
usage();
|
||||||
@ -253,7 +280,7 @@ int main(int argc, char **argv){
|
|||||||
if(emlfile) rc = import_message(emlfile, &sdata, &data, &cfg);
|
if(emlfile) rc = import_message(emlfile, &sdata, &data, &cfg);
|
||||||
if(mailbox) rc = import_from_mailbox(mailbox, &sdata, &data, &cfg);
|
if(mailbox) rc = import_from_mailbox(mailbox, &sdata, &data, &cfg);
|
||||||
if(directory) rc = import_from_maildir(directory, &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