diff options
author | roel <roel@7b491191-dbf0-0310-aff6-d879d4d69008> | 2001-07-20 13:27:27 +0000 |
---|---|---|
committer | roel <roel@7b491191-dbf0-0310-aff6-d879d4d69008> | 2001-07-20 13:27:27 +0000 |
commit | a0918439a5af6ee5d5f2b5452f234d3fb790f418 (patch) | |
tree | 90373da09f2a0c91010cd5ec03ac6ca0ecd45c07 | |
parent | 5038b4048c9510ca4af5c9a815823a2c057cdb3b (diff) |
*** empty log message ***
git-svn-id: https://svn.ic-s.nl/svn/dbmail/trunk/dbmail@63 7b491191-dbf0-0310-aff6-d879d4d69008
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | bounce.c | 7 | ||||
-rw-r--r-- | dbmysql.c | 634 | ||||
-rw-r--r-- | dbmysql.h | 24 | ||||
-rw-r--r-- | imapcommands.c | 4 | ||||
-rw-r--r-- | imaputil.c | 3 | ||||
-rw-r--r-- | list.c | 10 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | mime.c | 143 | ||||
-rw-r--r-- | mime.h | 1 | ||||
-rw-r--r-- | pipe.h | 5 | ||||
-rw-r--r-- | sql/create_tables.dev.sql | 1 |
12 files changed, 602 insertions, 241 deletions
@@ -4,11 +4,11 @@ SMTP_OBJECTS = list.o debug.o pipe.o mime.o dbmysql.o misc.o dbmd5.o md5.o bounce.o -POP_OBJECTS = pop3.o list.o debug.o dbmysql.o dbmd5.o md5.o +POP_OBJECTS = pop3.o list.o debug.o dbmysql.o dbmd5.o md5.o mime.o IMAP_OBJECTS = imap4.o debug.o dbmysql.o serverservice.o list.o dbmd5.o md5.o imaputil.o \ imapcommands.o mime.o DUMP_OBJECTS = debug.o dbmysql.o list.o dbmd5.o md5.o mime.o sstack.o -MAINTENANCE_OBJECTS = debug.o list.o dbmd5.o md5.o dbmysql.o +MAINTENANCE_OBJECTS = debug.o list.o dbmd5.o md5.o dbmysql.o mime.o CC = cc MYSQLLIBDIR=/usr/local/lib/mysql @@ -36,7 +36,7 @@ pop3d: pop3.h $(POP_OBJECTS) pop3d.c $(CC) pop3d.c -o dbmail-pop3d $(POP_OBJECTS) $(LIBS) $(LIB) imapd: imap4.h $(IMAP_OBJECTS) imapd.c - $(CC) imapd.c -o dbmail-imapd $(IMAP_OBJECTS) $(LIBS) $(LIB) + $(CC) $(CFLAGS) imapd.c -o dbmail-imapd $(IMAP_OBJECTS) $(LIBS) $(LIB) maintenance: maintenance.h $(MAINTENANCE_OBJECTS) maintenance.c $(CC) maintenance.c -o dbmail-maintenance $(MAINTENANCE_OBJECTS) $(LIBS) $(LIB) @@ -46,7 +46,7 @@ list.o: list.h debug.o: debug.h pipe.o: pipe.h config.h mime.o: mime.h config.h -dbmysql.o:dbmysql.h dbmd5.h config.h mime.h +dbmysql.o:dbmysql.h dbmd5.h config.h mime.h list.h misc.o:misc.h config.h pop3.o:pop3.h config.h dbmd5.o:dbmd5.h md5.h @@ -4,6 +4,11 @@ #include "bounce.h" #include "list.h" #include "mime.h" +extern char *header; + extern unsigned long headersize; + + extern struct list mimelist; + extern struct list users; int bounce (char *header, char *destination_address, int type) { @@ -23,7 +28,7 @@ int bounce (char *header, char *destination_address, int type) destination_address); list_init(&from_addresses); /* scan the from header for addresses */ - mail_adr_list ("from", &from_addresses); + mail_adr_list ("from", &from_addresses,&mimelist,&users,header,headersize); /* loop target addresses */ tmpelement=list_getstart (&from_addresses); @@ -7,16 +7,31 @@ #include "dbmd5.h" #include "list.h" #include "mime.h" +#include <ctype.h> #define DEF_QUERYSIZE 1024 -#define MSGBUF_WINDOWSIZE 65536ul +#define MSGBUF_WINDOWSIZE (128ul*1024ul) +#define MSGBUF_FORCE_UPDATE -1 MYSQL conn; MYSQL_RES *res,*_msg_result; MYSQL_ROW row; +MYSQL_ROW _msgrow; int _msg_fetch_inited = 0; + +/* + * CONDITIONS FOR MSGBUF + * + * rowlength length of current row + * rowpos current pos in row (_msgrow[0][rowpos-1] is last read char) + * msgidx index within msgbuf, 0 <= msgidx < buflen + * buflen current buffer length: msgbuf[buflen] == '\0' + * zeropos absolute position (block/offset) of msgbuf[0] + */ + char msgbuf[MSGBUF_WINDOWSIZE]; -unsigned lengths[2]; +unsigned long rowlength,msgidx,buflen,rowpos; +db_pos_t zeropos; int db_connect () @@ -769,7 +784,7 @@ int db_getmailbox(mailbox_t *mb, unsigned long userid) mysql_free_result(res); - /* now select messages: UNSEEN */ + /* now select messages: UNSEEN */ snprintf(query, DEF_QUERYSIZE, "SELECT COUNT(*) FROM message WHERE seen_flag=0 AND " "mailboxidnr = %lu AND status!=3", mb->uid); @@ -1222,7 +1237,7 @@ int db_copymsg(unsigned long msgid, unsigned long destmboxid) { char query[DEF_QUERYSIZE]; char *insert; - unsigned long newid,*lengths,len; + unsigned long newid,*lengths,len,allocsize; /* retrieve message */ snprintf(query, DEF_QUERYSIZE, "SELECT * FROM message WHERE messageidnr = %lu", msgid); @@ -1312,9 +1327,9 @@ int db_copymsg(unsigned long msgid, unsigned long destmboxid) return -1; } - while (row = mysql_fetch_row(res)) + while ((row = mysql_fetch_row(res))) { - lengths = mysql_fetch_lengths(row); + lengths = mysql_fetch_lengths(res); allocsize = DEF_QUERYSIZE + lengths[MESSAGEBLK_MESSAGEBLK]; insert = (char*)malloc(allocsize); @@ -1338,7 +1353,7 @@ int db_copymsg(unsigned long msgid, unsigned long destmboxid) allocsize-len-lengths[MESSAGEBLK_MESSAGEBLK], "', %lu, %lu)", strtoul(row[MESSAGEBLK_BLOCKSIZE], NULL, 10), newid); - len += strlen(&insert[len + lengts[MESSAGEBLK_MESSAGEBLK]]) ; + len += strlen(&insert[len + lengths[MESSAGEBLK_MESSAGEBLK]]) ; if (mysql_real_query(&conn, query, len)) { @@ -1667,14 +1682,14 @@ int db_get_msgdate(unsigned long mailboxuid, unsigned long msguid, char *date) * db_init_msgfetch() * * initializes a msg fetch - * returns -1 on error, 0 on success, 1 if already inited (call db_close_msgfetch() first) + * returns -1 on error, 1 on success, 0 if already inited (call db_close_msgfetch() first) */ int db_init_msgfetch(unsigned long uid) { char query[DEF_QUERYSIZE]; - + if (_msg_fetch_inited) - return 1; + return 0; snprintf(query, DEF_QUERYSIZE, "SELECT messageblk FROM messageblk WHERE " "messageidnr = %lu", uid); @@ -1693,65 +1708,152 @@ int db_init_msgfetch(unsigned long uid) } _msg_fetch_inited = 1; + msgidx = 0; - /* save rows (max 2) */ + /* save rows */ _msgrow = mysql_fetch_row(_msg_result); if (!_msgrow) - return -1; /* msg should have 1 block at least */ + { + _msg_fetch_inited = 0; + return -1; /* msg should have 1 block at least */ + } - lengths[0] = (mysql_fetch_lengths(_msgrow))[0]; + rowlength = (mysql_fetch_lengths(_msg_result))[0]; strncpy(msgbuf, _msgrow[0], MSGBUF_WINDOWSIZE-1); + zeropos.block = 0; + zeropos.pos = 0; - if (lengths[0] >= MSGBUF_WINDOWSIZE-1) + if (rowlength >= MSGBUF_WINDOWSIZE-1) { - msgbuf[MSGBUF_WINDOWSIZE-1] = '\0'; - return 0; /* msgbuf full */ + buflen = MSGBUF_WINDOWSIZE-1; + rowpos = MSGBUF_WINDOWSIZE; /* remember store pos */ + msgbuf[buflen] = '\0'; /* terminate buff */ + return 1; /* msgbuf full */ } - + + buflen = rowlength; /* NOTE \0 has been copied from _msgrow) */ + rowpos = rowlength; /* no more to read from this row */ _msgrow = mysql_fetch_row(_msg_result); if (!_msgrow) { - lengths[1] = 0; + rowlength = rowpos = 0; + return 1; + } + + rowlength = (mysql_fetch_lengths(_msg_result))[0]; + rowpos = 0; + strncpy(&msgbuf[buflen], _msgrow[0], MSGBUF_WINDOWSIZE - buflen - 1); + + if (rowlength <= MSGBUF_WINDOWSIZE - buflen - 1) + { + /* 2nd block fits entirely */ + rowpos = rowlength; + buflen += rowlength; } else { - lengths[1] = (mysql_fetch_lengths(_msgrow))[0]; - strncpy(&msgbuf[lengths[0]], _msgrow[0], MSGBUF_WINDOWSIZE - lengths[0] -1); + rowpos = MSGBUF_WINDOWSIZE - (buflen+1); + buflen = MSGBUF_WINDOWSIZE-1; } - strcat(msgbuf,""); /* add NULL */ - return 0; + msgbuf[buflen] = '\0'; /* add NULL */ + return 1; } /* * db_update_msgbuf() * - * updates msgbuf[]; if minlen == -1 the buffer is displaced to maximum new chars, - * else we make sure there is at least minlen room to the left of the buffer window - * (or end of msgblocks reached) + * update msgbuf: + * if minlen < 0, update is forced else update only if there are less than + * minlen chars left in buf * - * returns 1 on succes, -1 on error, 0 if could not displace that much + * returns 1 on succes, -1 on error, 0 if no more chars in rows */ -int db_update_msgbuf(int *idx, int minlen) +int db_update_msgbuf(int minlen) { - if (lengths[1] == 0) - return 1; /* no more */ + trace(TRACE_DEBUG,"update msgbuf start %lu %lu %lu %lu\n",MSGBUF_WINDOWSIZE, + buflen,rowlength,rowpos); - /* check for maximum displacement */ - if (minlen == -1) - { - /* try to make idx as low as possible (max displacement) */ + if (!_msgrow) + return 0; /* no more */ + + if (msgidx > buflen) + return -1; /* error, msgidx should be within buf */ + + if (minlen > 0 && (buflen-msgidx) > minlen) + return 1; /* ok, need no update */ + trace(TRACE_DEBUG,"update msgbuf updating\n"); - /* check if we need a new row */ - if ((lengths[1]-msgbufend) < minlen) + /* move buf to make msgidx 0 */ + memmove(msgbuf, &msgbuf[msgidx], msgidx); + if (msgidx > ((buflen+1) - rowpos)) + { + zeropos.block++; + zeropos.pos = (msgidx - ((buflen+1) - rowpos)); + } + else + zeropos.pos += msgidx; - row = mysql_fetch_row(_msg_result); - if (!row) - + buflen -= msgidx; + msgidx = 0; + + if ((rowlength-rowpos) >= (MSGBUF_WINDOWSIZE - buflen)) + { + trace(TRACE_DEBUG,"update msgbuf 1\n"); + + /* rest of row does not fit entirely in buf */ + strncpy(&msgbuf[buflen], &_msgrow[0][rowpos], MSGBUF_WINDOWSIZE - buflen); + rowpos += (MSGBUF_WINDOWSIZE - buflen); + + buflen = MSGBUF_WINDOWSIZE-1; + msgbuf[buflen] = '\0'; + + return 1; + } + + trace(TRACE_DEBUG,"update msgbuf 2 %s\n",_msgrow[0]); + + strncpy(&msgbuf[buflen], &_msgrow[0][rowpos], (rowlength-rowpos)); + buflen += (rowlength-rowpos); + msgbuf[buflen] = '\0'; + rowpos = rowlength; + + /* try to fetch a new row */ + _msgrow = mysql_fetch_row(_msg_result); + if (!_msgrow) + { + rowlength = rowpos = 0; + trace(TRACE_DEBUG,"update msgbuf succes NOMORE\n"); + return 0; + } + + rowlength = (mysql_fetch_lengths(_msg_result))[0]; + rowpos = 0; + + trace(TRACE_DEBUG,"update msgbuf 3\n"); + + strncpy(&msgbuf[buflen], _msgrow[0], MSGBUF_WINDOWSIZE - buflen - 1); + if (rowlength <= MSGBUF_WINDOWSIZE - buflen - 1) + { + /* 2nd block fits entirely */ + rowpos = rowlength; + buflen += rowlength; + } + else + { + rowpos = MSGBUF_WINDOWSIZE - (buflen+1); + buflen = MSGBUF_WINDOWSIZE-1; + } + + msgbuf[buflen] = '\0' ; /* add NULL */ + + trace(TRACE_DEBUG,"update msgbuf succes\n"); + return 1; +} /* @@ -1784,212 +1886,301 @@ void db_close_msgfetch() */ int db_fetch_headers(unsigned long msguid, mime_message_t *msg) { - char query[DEF_QUERYSIZE],*boundary; - int i,end; - char *boundary; - - /* first fetch msgblocks */ - snprintf(query, DEF_QUERYSIZE, "SELECT messageblk FROM messageblk WHERE messageidnr = %lu", - msguid); + int result; - if (db_query(query) == -1) + if (db_init_msgfetch(msguid) != 1) { - trace(TRACE_ERROR, "db_fetch_headers(): could not select messageblocks\n"); - return (-1); + trace(TRACE_ERROR,"db_fetch_headers(): could not init msgfetch\n"); + return -1; } - if ((res = mysql_store_result(&conn)) == NULL) + result = db_start_msg(msg, NULL); /* fetch message */ + if (result == -1) { - trace(TRACE_ERROR,"db_fetch_headers(): mysql_store_result failed: %s\n", - mysql_error(&conn)); - return (-1); + db_free_msg(msg); + return -1; } - - /* body of first part is total msg */ - msg->children = NULL; - msg->headerstart.block = 0; - msg->headerstart.pos = 0; - msg->bodystart.block = 1; - msg->bodystart.pos = 0; - msg->bodyend.block = mysql_num_rows(res); - msg->headerend.block = 0; + db_reverse_msg(msg); - row = mysql_fetch_row(res); - msg->headerend.pos = strlen(row[0]); + db_close_msgfetch(); + return 0; +} - /* first block is first header, find MIME-fields */ - if (mime_list(row[0], &msg->mimeheader) == -1) + +/* + * frees all the memory associated with a msg + */ +void db_free_msg(mime_message_t *msg) +{ + struct element *tmp; + + if (!msg) + return; + + /* free the children msg's */ + tmp = list_getstart(&msg->children); + + while (tmp) { - mysql_free_result(res); - return -1; + db_free_msg((mime_message_t*)tmp->data); + tmp = tmp->nextnode; } - /* retrieve boundary */ - boundary = mime_findfield("boundary", &msg->mimeheader, &record); - if (boundary) + tmp = list_getstart(&msg->children); + list_freelist(&tmp); + + tmp = list_getstart(&msg->mimeheader); + list_freelist(&tmp); + +} + + +/* + * reverses the children lists of a msg + */ +void db_reverse_msg(mime_message_t *msg) +{ + struct element *tmp; + + if (!msg) + return; + + /* reverse the children msg's */ + tmp = list_getstart(&msg->children); + + while (tmp) { - /* found a boundary item, multipart message */ - /* read value */ - boundary += strlen("boundary="); - if (*boundary == '\"') boundary++; - if (boundary[strlen(boundary)-1] == '\"') - boundary[strlen(boundary)-1] = '\0'; + db_reverse_msg((mime_message_t*)tmp->data); + tmp = tmp->nextnode; + } + + /* reverse this list */ + tmp = list_getstart(&msg->children); + list_reverse(tmp); +} + +void db_give_msgpos(db_pos_t *pos) +{ + if (msgidx > ((buflen+1)-rowpos)) + { + pos->block = zeropos.block+1; + pos->pos = ((buflen+1)-rowpos) - msgidx; } else { - while (row = mysql_fetch_row(res)) - msg->bodyend.pos = strlen(row[0]); - - mysql_free_result(res); - return 0; /* this is a single-part message; done */ + pos->block = zeropos.block; + pos->pos = zeropos.pos + msgidx; } +} - /* this is a multipart msg - * find the next boundary, then read the header that follows it (if present) and - */ - - msg->children = (struct list*)malloc(sizeof(struct list)); - if (!msg->children) - { - mysql_free_result(res); - return -1; - } +/* + * db_start_msg() + * + * reads in a msg + */ +int db_start_msg(mime_message_t *msg, char *stopbound) +{ + int len,sblen,result; + struct mime_record *mr; + char *newbound,*bptr; - list_init(msg->children); - row = mysql_fetch_result(res); - if (!row) + list_init(&msg->children); + db_give_msgpos(&msg->headerstart); + + /* read header */ + if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1) + return -1; + + mime_readheader(&msgbuf[msgidx], &msgidx, &msg->mimeheader); + db_give_msgpos(&msg->headerend); + + msgidx++; + db_give_msgpos(&msg->bodystart); + + mime_findfield("content-type", &msg->mimeheader, mr); + if (mr && strncasecmp(mr->value,"multipart", strlen("multipart")) == 0) { - mysql_free_result(res); - free(msg->children); - return -1; - } + trace(TRACE_DEBUG,"db_start_msg(): found multipart msg\n"); + + /* multipart msg, find new boundary */ + for (bptr = mr->value; *bptr; bptr++) + if ((*bptr == 'b' || *bptr == 'B') && + strncasecmp(bptr, "boundary=", strlen("boundary=")) == 0) + break; + + if (!bptr) + return -1; /* no new boundary ??? */ + + bptr += strlen("boundary="); + if (*bptr == '\"') + bptr++; + + newbound = bptr; + while (*newbound && *newbound != '\"' && !isspace(*newbound)) newbound++; + + len = newbound - bptr; + if (!(newbound = (char*)malloc(len+1))) + return -1; + + strncpy(newbound, bptr, len); + newbound[len] = '\0'; + + /* advance to first boundary */ + if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1) + { + free(newbound); + return -1; + } + + while (msgbuf[msgidx]) + { + if (msgbuf[msgidx] == '\n' && strncmp(&msgbuf[msgidx+1], newbound, strlen(newbound)) == 0) + break; + } + + if (msgbuf[msgidx]) msgidx++; /* skip newline */ + + if (!msgbuf[msgidx]) + { + free(newbound); + return -1; + } + + + /* find MIME-parts */ + if (db_add_mime_children(&msg->children, newbound) == -1) + { + free(newbound); + return -1; + } - cnt = 0; - blk = 1; - if (db_add_mime_children(boundary, 0, &cnt, msg->children) == -1) + free(newbound); + db_give_msgpos(&msg->bodyend); + return 0; /* done */ + } + else { - mysql_free_result(res); - free(msg->children); - return -1; + /* single part msg, read untill stopbound OR end of buffer */ + trace(TRACE_DEBUG,"db_start_msg(): found singlepart msg\n"); + + if (stopbound) + { + sblen = strlen(stopbound)+2; + + while (msgbuf[msgidx]) + { + if (db_update_msgbuf(sblen) == -1) + return -1; + + if (msgbuf[msgidx] == '\n' && + strncmp(&msgbuf[msgidx+1], stopbound, strlen(stopbound)) == 0) + { + db_give_msgpos(&msg->bodyend); + return 0; + } + } + + /* end of buffer reached, bodyend is prev pos */ + msgidx--; + db_give_msgpos(&msg->bodyend); + msgidx++; + } + else + { + /* walk on till end of buffer */ + do + { + msgidx = buflen - 1; + result = db_update_msgbuf(MSGBUF_FORCE_UPDATE); + if (result == -1) + return -1; + } while (result == 1); + + db_give_msgpos(&msg->bodyend); + } } - msg->bodyend.pos = cnt; + trace(TRACE_DEBUG,"db_start_msg(): exit\n"); return 0; } -int db_add_mime_children(char *boundary, unsigned start, unsigned *end, struct list *children) +/* + * assume to enter just after a splitbound + */ +int db_add_mime_children(struct list *brothers, char *splitbound) { - mime_message_t msg; - struct mime_record record; - char *nextboundary; - unsigned nextend; - unsigned long length; - - msg.children = NULL; - msg.headerstart.block = -1; /* presume no header */ - msg.headerstart.pos = -1; - msg.bodystart.block = blk; - msg.bodystart.pos = 0; - list_init(&msg.mimeheader); + mime_message_t part; + struct mime_record *mr; + char *boundary; + int sblen; trace(TRACE_DEBUG,"boundary: '%s'\n",boundary); do { - length = (mysql_fetch_lengths(res))[0]; - for (*end = start; msgbuf[*end]; *end++) - { - db_update_msgbuf(end, strlen(boundary)+1+1); + db_update_msgbuf(MSGBUF_FORCE_UPDATE); + memset(&part, 0, sizeof(part)); - /* start looking for a new line & boundary */ - if (msgbuf[*end] == '\n' && strcmp(&msgbuf[*end+1], boundary) == 0) - { - /* found boundary, maximum msgbuf update */ - db_update_msgbuf(end, -1); + /* should have a MIME header right here */ + mime_readheader(&msgbuf[msgidx], &msgidx, &part.mimeheader); + mime_findfield("content-type", &part.mimeheader, mr); - msg.bodyend.block = blk; - msg.bodyend.pos = *end; + if (mr && strncasecmp(mr->value, "message/rfc822", strlen("message/rfc822")) == 0) + { + /* a message will follow */ - *end++; - *end += strlen(boundary); /* skip */ - *end++; + db_start_msg(&part, splitbound); - if (*end == '\n') - { - /* end of this msg-part, add this part & exit */ - if (!list_nodeadd(children, &msg, sizeof(msg))) - return -1; - - return 0; - } + /* advance to after splitbound */ + msgidx++; + msgidx += strlen(splitbound); + + } + else + { + /* just body data follows, advance to splitbound */ + db_give_msgpos(&part.bodystart); + sblen = strlen(splitbound)+2; - /* ok find MIME-header fields */ - if (mime_list(&msgbuf[*end], &msg.mimeheader) == -1) + while (msgbuf[msgidx]) + { + if (db_update_msgbuf(sblen) == -1) return -1; - /* skip to end of MIME-header fields (\n\n) */ - while (msgbuf[*end]) - { - if (msgbuf[*end] == '\n' && msgbuf[*end+1] == '\n') - break; + if (msgbuf[msgidx] == '\n' && + strncmp(&msgbuf[msgidx+1], splitbound, strlen(splitbound)) == 0) + break; + } - *end++; - } - - /* check if there will be more kiddos */ - nextboundary = mime_findfield("boundary", &msg.mimeheader, &record); - if (nextboundary) - { - /* found a boundary item, multipart message */ - /* read value */ - nextboundary += strlen("boundary="); - if (*nextboundary == '\"') nextboundary++; - if (nextboundary[strlen(nextboundary)-1] == '\"') - nextboundary[strlen(nextboundary)-1] = '\0'; - - msg.children = (struct list*)malloc(sizeof(struct list)); - if (!msg.children) - return -1; - - list_init(msg.children); - - nextend = *end; - if (db_add_mime_children(nextboundary, *end, &nextend, msg.children) == -1) - return -1; - - *end = nextend; - } - else - { - /* single part message, this is the body */ - - } - - - - + if (!msgbuf[msgidx]) + { + /* ?? splitbound should follow */ + return -1; } + db_give_msgpos(&part.bodyend); } - } -} - - - - - - - - - + /* add this part to brother list */ + if (list_nodeadd(brothers, &part, sizeof(part)) == NULL) + return -1; + /* if double newline follows we're done */ + if (msgbuf[msgidx] && msgbuf[msgidx] == '\n' && msgbuf[msgidx+1] == '\n') + { + msgidx += 2; /* skip \n */ + return 0; + } + } + while (msgbuf[msgidx]) ; + return 0; +} /* @@ -1997,47 +2188,54 @@ int db_add_mime_children(char *boundary, unsigned start, unsigned *end, struct l * * dumps a message to stderr */ -int db_msgdump(unsigned long uid) +int db_msgdump(mime_message_t *msg) { - char query[DEF_QUERYSIZE]; - int i; - struct list mimelist; struct element *curr; struct mime_record *mr; - snprintf(query, DEF_QUERYSIZE, "SELECT messageblk FROM messageblk WHERE " - "messageidnr = %lu", uid); - - if (db_query(query) == -1) + if (!msg) { - trace(TRACE_ERROR, "db_msgdump(): could not get message\n"); - return (-1); + trace(TRACE_DEBUG,"db_msgdump: got null\n"); + return 0; } - if ((res = mysql_store_result(&conn)) == NULL) + trace(TRACE_DEBUG,"MIME-header: \n"); + curr = list_getstart(&msg->mimeheader); + if (!curr) + trace(TRACE_DEBUG,"null\n"); + else { - trace(TRACE_ERROR,"db_msgdump(): mysql_store_result failed: %s\n",mysql_error(&conn)); - return (-1); + while (curr) + { + mr = (struct mime_record *)curr->data; + trace(TRACE_DEBUG,"[%s] : [%s]\n",mr->field, mr->value); + curr = curr->nextnode; + } } + + trace(TRACE_DEBUG,"RFC822-header: \n"); + db_dump_range(msg->headerstart, msg->headerend); + trace(TRACE_DEBUG,"*** header end\n"); - trace(TRACE_DEBUG,"message %lu:\n",uid); - row = mysql_fetch_row(res); - mime_list(row[0],&mimelist); - trace(TRACE_DEBUG,"**** mimelist build\n"); - - /* dump MIME list */ - curr = list_getstart(&mimelist); + trace(TRACE_DEBUG,"body: \n"); + db_dump_range(msg->bodystart, msg->bodyend); + trace(TRACE_DEBUG,"*** body end\n"); + + trace(TRACE_DEBUG,"Children of this msg:\n"); + curr = list_getstart(&msg->children); while (curr) { - mr = (struct mime_record*)curr->data; - trace(TRACE_DEBUG,"'%s':'%s'\n",mr->field,mr->value); + db_msgdump((mime_message_t*)curr->data); curr = curr->nextnode; } - - mysql_free_result(res); - return 0; + return 1; } +void db_dump_range(db_pos_t start, db_pos_t end) +{ + + trace(TRACE_DEBUG,"Range: (%d,%d) - (%d,%d)\n",start.block, start.pos, end.block, end.pos); +} @@ -8,6 +8,7 @@ #include "debug.h" #include "imap4.h" #include "mime.h" +#include "list.h" struct session; struct list; @@ -85,10 +86,10 @@ typedef struct typedef struct { - struct list mimeheaders; - db_pos_t headerstart,headerend; - db_pos_t bodystart,bodyend; - struct list *children; + struct list mimeheader; /* the MIME header of this part (if present) */ + db_pos_t headerstart,headerend; /* RFC822 header of this part (if present) */ + db_pos_t bodystart,bodyend; /* the body of this part */ + struct list children; /* the children (multipart msg) */ } mime_message_t; @@ -141,15 +142,20 @@ unsigned long db_first_unseen(unsigned long uid); int db_get_msgflag(const char *name, unsigned long mailboxuid, unsigned long msguid); int db_set_msgflag(const char *name, unsigned long mailboxuid, unsigned long msguid, int val); int db_get_msgdate(unsigned long mailboxuid, unsigned long msguid, char *date); + int db_init_msgfetch(unsigned long uid); -int db_msgfetch_next(char **data); +int db_update_msgbuf(int minlen); void db_close_msgfetch(); +void db_give_msgpos(db_pos_t *pos); -int db_fetch_headers(unsigned long msguid, db_header_t **headers, unsigned maxheaders, - unsigned *nheaders); +void db_free_msg(mime_message_t *msg); +void db_reverse_msg(mime_message_t *msg); -int db_update_msgbuf(int *idx, int minlen); +int db_fetch_headers(unsigned long msguid, mime_message_t *msg); +int db_add_mime_children(struct list *brothers, char *splitbound); +int db_start_msg(mime_message_t *msg, char *stopbound); -int db_msgdump(unsigned long uid); +void db_dump_range(db_pos_t start, db_pos_t end); +int db_msgdump(mime_message_t *msg); #endif diff --git a/imapcommands.c b/imapcommands.c index 7511ede9..fc68e01e 100644 --- a/imapcommands.c +++ b/imapcommands.c @@ -1360,6 +1360,7 @@ int _ic_fetch(char *tag, char **args, ClientInfo *ci) imap_userdata_t *ud = (imap_userdata_t*)ci->userData; int i,fetch_start,fetch_end,delimpos,result,setseen,j; fetch_items_t fetchitems; + mime_message_t msg; char date[IMAP_INTERNALDATE_LEN]; if (ud->state != IMAPCS_SELECTED) @@ -1537,6 +1538,9 @@ int _ic_fetch(char *tag, char **args, ClientInfo *ci) { } + db_fetch_headers(ud->mailbox.seq_list[i], &msg); + db_msgdump(&msg); + for (j=0; j<fetchitems.nbodyfetches; j++) { switch (fetchitems.bodyfetches[j].itemtype) @@ -120,6 +120,7 @@ int get_fetch_items(char **args, fetch_items_t *fi) for ( ; args[i]; i++) { + trace(TRACE_DEBUG,"a[i]: %s\n",args[i]); if (strcasecmp(args[i], "flags") == 0) { fi->getFlags = 1; @@ -146,7 +147,7 @@ int get_fetch_items(char **args, fetch_items_t *fi) } else if (strcasecmp(args[i], "body") == 0 || strcasecmp(args[i],"body.peek") == 0) { - if (strcmp(args[i+1],"[") != 0) + if (!args[i+1] || strcmp(args[i+1],"[") != 0) { if (strcasecmp(args[i],"body.peek") == 0) { @@ -44,13 +44,13 @@ void list_freelist(struct element **start) */ void list_reverse(struct element *start) { - if (!start || !start->next) + if (!start || !start->nextnode) return; /* nothing to reverse */ - list_reverse(start->next); /* reverse rest of list */ - start->next->next = start; + list_reverse(start->nextnode); /* reverse rest of list */ + start->nextnode->nextnode = start; - start->next = NULL; /* terminate list */ + start->nextnode = NULL; /* terminate list */ } @@ -115,7 +115,7 @@ struct element *list_nodepop(struct list *list) ret = list->start; - list->start = list->start->next; + list->start = list->start->nextnode; return ret; } @@ -3,6 +3,7 @@ #include "config.h" #include "main.h" +#include "pipe.h" #define MESSAGEIDSIZE 100 #define NORMAL_DELIVERY 1 @@ -59,7 +60,7 @@ int main (int argc, char *argv[]) { trace(TRACE_STOP,"main(): fatal error creating MIME-header list\n"); /* parse for destination addresses */ - if (!mail_adr_list("deliver-to",&users,&mimelist)) + if (!mail_adr_list ("deliver-to",&users,&mimelist,&users,header,headersize)) trace(TRACE_STOP,"main(): scanner found no email addresses"); } @@ -27,7 +27,7 @@ int mime_list(char *blkdata, struct list *mimelist) struct mime_record *mr; struct element *el; - trace (TRACE_INFO, "mime_list(): entering mime loop"); + trace (TRACE_INFO, "mime_list(): entering mime loop\n"); list_init(mimelist); /* alloc mem */ @@ -151,6 +151,145 @@ int mime_list(char *blkdata, struct list *mimelist) } /* success */ + trace(TRACE_DEBUG," *** mime_list() done ***\n"); + return 0; +} + + + +/* + * mime_readheader() + * + * same as mime_list() but keeps track of idx in blkdata + * + * returns -1 on failure, 0 on success + */ +int mime_readheader(char *blkdata, unsigned long *blkidx, struct list *mimelist) +{ + int valid_mime_lines=0,idx; + + char *endptr, *startptr, *delimiter; + struct mime_record *mr; + struct element *el; + + trace (TRACE_INFO, "mime_readheader(): entering mime loop\n"); + + list_init(mimelist); + /* alloc mem */ + mr=(struct mime_record *)malloc(sizeof(struct mime_record)); + + if (!mr) + { + trace(TRACE_ERROR, "mime_readheader(): out of memory\n"); + return -1; + } + + startptr = blkdata; + while (*startptr) + { + /* quick hack to jump over those naughty \n\t fields */ + endptr = startptr; + while (*endptr) + { + if (endptr[0]=='\n' && endptr[1]!='\t') + { + if (endptr != blkdata && *(endptr-1) == ';') + { + endptr++; + continue; + } + else + { + break; + } + } + endptr++; + } + + if (!(*endptr)) + { + /* end of data block reached */ + free(mr); + return 0; + } + + /* endptr points to linebreak now */ + /* MIME field+value is string from startptr till endptr */ + + *endptr = '\0'; /* replace newline to terminated string */ + +/* trace(TRACE_DEBUG,"mime_readheader(): captured array [%s]\n",startptr); +*/ + /* parsing tmpstring for field and data */ + /* field is name:value */ + + delimiter = strchr(startptr,':'); + + if (delimiter) + { + /* found ':' */ + valid_mime_lines++; + *delimiter = '\0'; /* split up strings */ + + /* skip all spaces and colons after the fieldname */ + idx = 1; + while ((delimiter[idx]==':') || (delimiter[idx]==' ')) idx++; + + /* &delimiter[idx] is field value, startptr is field name */ + strcpy(mr->field, startptr); + strcpy(mr->value, &delimiter[idx]); + + trace (TRACE_DEBUG,"mime_readheader(): mimepair found: [%s] [%s] \n",mr->field, mr->value); + + el = list_nodeadd(mimelist,mr,sizeof (*mr)); + if (!el) + { + trace(TRACE_ERROR, "mime_readheader(): cannot add element to list\n"); + free(mr); + return -1; + } + + /* restore blkdata */ + *delimiter = ':'; + *endptr = '\n'; + + *blkidx += (endptr-startptr); + *blkidx++; + + startptr = endptr+1; /* advance to next field */ + + if (*startptr == '\n') + { + /* end of header: double newline */ + trace(TRACE_DEBUG,"mime_readheader(): found double newline\n"); + free(mr); + return 0; + } + } + else + { + /* no field/value delimiter found, non-valid MIME-header */ + free(mr); + trace(TRACE_DEBUG,"Non valid mimeheader found, freeing list...\n"); + list_freelist(&mimelist->start); + mimelist->total_nodes = 0; + trace(TRACE_DEBUG,"freeing list done, start: %X\n ",mimelist->start); + + return -1; + } + } + + free(mr); /* no longer need this */ + + trace(TRACE_DEBUG,"mime_readheader(): mimeloop finished\n"); + if (valid_mime_lines < 2) + { + trace(TRACE_ERROR,"mime_readheader(): no valid mime headers found\n"); + return -1; + } + + /* success */ + trace(TRACE_DEBUG," *** mime_readheader() done ***\n"); return 0; } @@ -171,7 +310,7 @@ void mime_findfield(const char *fname, struct list *mimelist, struct mime_record { mr = current->data; /* get field/value */ - if (strcasecmp(mr->field, fname) == 0) + if (strncasecmp(mr->field, fname, strlen(fname)) == 0) return; /* found */ current = current->nextnode; @@ -21,5 +21,6 @@ int mime_list(char *blkdata, struct list *mimelist); void mime_findfield(const char *fname, struct list *mimelist, struct mime_record *mr); int mail_adr_list(char *scan_for_field, struct list *targetlist, struct list *mimelist, struct list *users, char *header, unsigned long headersize); +int mime_readheader(char *blkdata, unsigned long *blkidx, struct list *mimelist); #endif @@ -7,4 +7,9 @@ #include "debug.h" #include "list.h" #include "bounce.h" + +void create_unique_id(char *target, unsigned long messageid); +char *read_header(unsigned long *blksize); +int insert_messages(char *firstblock, unsigned long headersize); + #endif diff --git a/sql/create_tables.dev.sql b/sql/create_tables.dev.sql index fe5e499e..2d25d4d7 100644 --- a/sql/create_tables.dev.sql +++ b/sql/create_tables.dev.sql @@ -50,6 +50,7 @@ CREATE TABLE message ( recent_flag tinyint(1) default '0' not null, draft_flag tinyint(1) default '0' not null, unique_id varchar(70) NOT NULL, + internal_date date default '0' not null, status tinyint(3) unsigned zerofill default '000' not null, PRIMARY KEY (messageidnr), KEY messageidnr (messageidnr), |