summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroel <roel@7b491191-dbf0-0310-aff6-d879d4d69008>2001-07-20 13:27:27 +0000
committerroel <roel@7b491191-dbf0-0310-aff6-d879d4d69008>2001-07-20 13:27:27 +0000
commita0918439a5af6ee5d5f2b5452f234d3fb790f418 (patch)
tree90373da09f2a0c91010cd5ec03ac6ca0ecd45c07
parent5038b4048c9510ca4af5c9a815823a2c057cdb3b (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--Makefile8
-rw-r--r--bounce.c7
-rw-r--r--dbmysql.c634
-rw-r--r--dbmysql.h24
-rw-r--r--imapcommands.c4
-rw-r--r--imaputil.c3
-rw-r--r--list.c10
-rw-r--r--main.c3
-rw-r--r--mime.c143
-rw-r--r--mime.h1
-rw-r--r--pipe.h5
-rw-r--r--sql/create_tables.dev.sql1
12 files changed, 602 insertions, 241 deletions
diff --git a/Makefile b/Makefile
index f93de1fe..4fa70984 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/bounce.c b/bounce.c
index 331ec513..83f89659 100644
--- a/bounce.c
+++ b/bounce.c
@@ -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);
diff --git a/dbmysql.c b/dbmysql.c
index 7fe9f513..125a1735 100644
--- a/dbmysql.c
+++ b/dbmysql.c
@@ -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);
+}
diff --git a/dbmysql.h b/dbmysql.h
index bbf9863d..12fcdd9f 100644
--- a/dbmysql.h
+++ b/dbmysql.h
@@ -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)
diff --git a/imaputil.c b/imaputil.c
index 976fe8cd..59b6cbee 100644
--- a/imaputil.c
+++ b/imaputil.c
@@ -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)
{
diff --git a/list.c b/list.c
index b50d1db6..74811bc5 100644
--- a/list.c
+++ b/list.c
@@ -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;
}
diff --git a/main.c b/main.c
index 4255bb8f..ca7c9225 100644
--- a/main.c
+++ b/main.c
@@ -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");
}
diff --git a/mime.c b/mime.c
index 698f09b8..0621865f 100644
--- a/mime.c
+++ b/mime.c
@@ -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;
diff --git a/mime.h b/mime.h
index b1effb80..0772e131 100644
--- a/mime.h
+++ b/mime.h
@@ -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
diff --git a/pipe.h b/pipe.h
index 5e0d9f21..5c16147f 100644
--- a/pipe.h
+++ b/pipe.h
@@ -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),