[dovecot-cvs] dovecot/src/lib-imap imap-bodystructure.c,1.32,1.33 imap-envelope.c,1.24,1.25 imap-envelope.h,1.9,1.10 imap-quote.c,1.10,1.11

cras at procontrol.fi cras at procontrol.fi
Wed Mar 26 19:29:04 EET 2003


Update of /home/cvs/dovecot/src/lib-imap
In directory danu:/tmp/cvs-serv10853/lib-imap

Modified Files:
	imap-bodystructure.c imap-envelope.c imap-envelope.h 
	imap-quote.c 
Log Message:
Better handling for multiline headers. Before we skipped headers larger than
input buffer size (8k with read (default), 256k with mmap). The skipping was
also a bit buggy.

Now we parse the lines one at a time. There's also a way to read the header
fully into memory before parsing it, if really needed.



Index: imap-bodystructure.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-bodystructure.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- imap-bodystructure.c	25 Feb 2003 21:05:52 -0000	1.32
+++ imap-bodystructure.c	26 Mar 2003 17:29:02 -0000	1.33
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
+#include "buffer.h"
 #include "istream.h"
 #include "str.h"
 #include "message-parser.h"
@@ -141,99 +142,114 @@
 	message_tokenize_deinit(tok);
 }
 
-static void parse_header(struct message_part *part,
-			 const unsigned char *name, size_t name_len,
-			 const unsigned char *value, size_t value_len,
-			 void *context)
+static void parse_content_header(struct message_part_body_data *d,
+				 struct message_header_line *hdr,
+				 pool_t pool)
 {
-	pool_t pool = context;
-	struct message_part_body_data *part_data;
-	int parent_rfc822;
+	const char *name = hdr->name;
+	const unsigned char *value;
+	size_t value_len;
 
-	parent_rfc822 = part->parent != NULL &&
-		(part->parent->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822);
-	if (!parent_rfc822 && (name_len <= 8 ||
-			       memcasecmp(name, "Content-", 8) != 0))
+	if (strncasecmp(name, "Content-", 8) != 0)
 		return;
+	name += 8;
 
-	if (part->context == NULL) {
-		/* initialize message part data */
-		part->context = part_data =
-			p_new(pool, struct message_part_body_data, 1);
-		part_data->pool = pool;
+	if (hdr->continues) {
+		hdr->use_full_value = TRUE;
+		return;
 	}
-	part_data = part->context;
 
-	t_push();
+	value = hdr->full_value;
+	value_len = hdr->full_value_len;
 
-	switch (name_len) {
-	case 10:
-		if (memcasecmp(name, "Content-ID", 10) == 0 &&
-		    part_data->content_id == NULL) {
-			part_data->content_id =
-				imap_quote(pool, value, value_len);
-		}
+	switch (*name) {
+	case 'i':
+	case 'I':
+		if (strcasecmp(name, "ID") == 0 && d->content_id == NULL)
+			d->content_id = imap_quote(pool, value, value_len);
 		break;
 
-	case 11:
-		if (memcasecmp(name, "Content-MD5", 11) == 0 &&
-		    part_data->content_md5 == NULL) {
-			part_data->content_md5 =
-				imap_quote(pool, value, value_len);
-		}
+	case 'm':
+	case 'M':
+		if (strcasecmp(name, "MD5") == 0 && d->content_md5 == NULL)
+			d->content_md5 = imap_quote(pool, value, value_len);
 		break;
 
-	case 12:
-		if (memcasecmp(name, "Content-Type", 12) != 0 ||
-		    part_data->content_type != NULL)
-			break;
-
-		part_data->str = t_str_new(256);
-		message_content_parse_header(value, value_len,
-					     parse_content_type,
-					     parse_save_params_list, part_data);
-		part_data->content_type_params =
-			p_strdup_empty(pool, str_c(part_data->str));
+	case 't':
+	case 'T':
+		if (strcasecmp(name, "Type") == 0 && d->content_type == NULL) {
+			d->str = t_str_new(256);
+			message_content_parse_header(value, value_len,
+						     parse_content_type,
+						     parse_save_params_list, d);
+			d->content_type_params =
+				p_strdup_empty(pool, str_c(d->str));
+		}
+		if (strcasecmp(name, "Transfer-Encoding") == 0 &&
+		    d->content_transfer_encoding == NULL) {
+			message_content_parse_header(value, value_len,
+				parse_content_transfer_encoding,
+				NULL, d);
+		}
 		break;
 
-	case 16:
-		if (memcasecmp(name, "Content-Language", 16) == 0)
-			parse_content_language(value, value_len, part_data);
+	case 'l':
+	case 'L':
+		if (strcasecmp(name, "Language") == 0 &&
+		    d->content_language == NULL)
+			parse_content_language(value, value_len, d);
 		break;
 
-	case 19:
-		if (memcasecmp(name, "Content-Description", 19) == 0 &&
-		    part_data->content_description == NULL) {
-			part_data->content_description =
+	case 'd':
+	case 'D':
+		if (strcasecmp(name, "Description") == 0 &&
+		    d->content_description == NULL) {
+			d->content_description =
 				imap_quote(pool, value, value_len);
 		}
-		if (memcasecmp(name, "Content-Disposition", 19) == 0 &&
-		    part_data->content_disposition_params == NULL) {
-			part_data->str = t_str_new(256);
+		if (strcasecmp(name, "Disposition") == 0 &&
+		    d->content_disposition_params == NULL) {
+			d->str = t_str_new(256);
 			message_content_parse_header(value, value_len,
 						     parse_content_disposition,
-						     parse_save_params_list,
-						     part_data);
-			part_data->content_disposition_params =
-				p_strdup_empty(pool, str_c(part_data->str));
+						     parse_save_params_list, d);
+			d->content_disposition_params =
+				p_strdup_empty(pool, str_c(d->str));
 		}
 		break;
+	}
+}
 
-	case 25:
-		if (memcasecmp(name, "Content-Transfer-Encoding", 25) != 0 ||
-		    part_data->content_transfer_encoding != NULL)
-			break;
+static void parse_header(struct message_part *part,
+                         struct message_header_line *hdr, void *context)
+{
+	pool_t pool = context;
+	struct message_part_body_data *part_data;
+	int parent_rfc822;
 
-		message_content_parse_header(value, value_len,
-					     parse_content_transfer_encoding,
-					     NULL, part_data);
-		break;
+	if (hdr == NULL)
+		return;
+
+	parent_rfc822 = part->parent != NULL &&
+		(part->parent->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822);
+	if (!parent_rfc822 && strncasecmp(hdr->name, "Content-", 8) != 0)
+		return;
+
+	if (part->context == NULL) {
+		/* initialize message part data */
+		part->context = part_data =
+			p_new(pool, struct message_part_body_data, 1);
+		part_data->pool = pool;
 	}
+	part_data = part->context;
+
+	t_push();
+
+	parse_content_header(part_data, hdr, pool);
 
 	if (parent_rfc822) {
 		/* message/rfc822, we need the envelope */
-		imap_envelope_parse_header(pool, &part_data->envelope,
-					   name, name_len, value, value_len);
+		imap_envelope_parse_header(pool, &part_data->envelope, hdr);
 	}
 	t_pop();
 }
@@ -249,7 +265,6 @@
 			      (input->v_offset - start_offset));
 
 		message_parse_header(part, input, NULL, parse_header, pool);
-
 		if (part->children != NULL) {
 			part_parse_headers(part->children, input,
 					   start_offset, pool);

Index: imap-envelope.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-envelope.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- imap-envelope.c	26 Mar 2003 15:40:16 -0000	1.24
+++ imap-envelope.c	26 Mar 2003 17:29:02 -0000	1.25
@@ -4,6 +4,7 @@
 #include "istream.h"
 #include "str.h"
 #include "message-address.h"
+#include "message-parser.h"
 #include "imap-parser.h"
 #include "imap-envelope.h"
 #include "imap-quote.h"
@@ -18,12 +19,80 @@
 	char *in_reply_to, *message_id;
 };
 
+int imap_envelope_get_field(const char *name, enum imap_envelope_field *ret)
+{
+	*ret = (enum imap_envelope_field)-1;
+
+	switch (*name) {
+	case 'B':
+	case 'b':
+		if (strcasecmp(name, "Bcc") == 0)
+			*ret = IMAP_ENVELOPE_BCC;
+		break;
+	case 'C':
+	case 'c':
+		if (strcasecmp(name, "Cc") == 0)
+			*ret = IMAP_ENVELOPE_CC;
+		break;
+	case 'D':
+	case 'd':
+		if (strcasecmp(name, "Date") == 0)
+			*ret = IMAP_ENVELOPE_DATE;
+		break;
+	case 'F':
+	case 'f':
+		if (strcasecmp(name, "From") == 0)
+			*ret = IMAP_ENVELOPE_FROM;
+		break;
+	case 'I':
+	case 'i':
+		if (strcasecmp(name, "In-reply-to") == 0)
+			*ret = IMAP_ENVELOPE_IN_REPLY_TO;
+		break;
+	case 'M':
+	case 'm':
+		if (strcasecmp(name, "Message-id") == 0)
+			*ret = IMAP_ENVELOPE_MESSAGE_ID;
+		break;
+	case 'R':
+	case 'r':
+		if (strcasecmp(name, "Reply-to") == 0)
+			*ret = IMAP_ENVELOPE_REPLY_TO;
+		break;
+	case 'S':
+	case 's':
+		if (strcasecmp(name, "Subject") == 0)
+			*ret = IMAP_ENVELOPE_SUBJECT;
+		if (strcasecmp(name, "Sender") == 0)
+			*ret = IMAP_ENVELOPE_SENDER;
+		break;
+	case 'T':
+	case 't':
+		if (strcasecmp(name, "To") == 0)
+			*ret = IMAP_ENVELOPE_TO;
+		break;
+	}
+
+	return *ret != (enum imap_envelope_field)-1;
+}
+
 void imap_envelope_parse_header(pool_t pool,
 				struct message_part_envelope_data **data,
-				const unsigned char *name, size_t name_len,
-				const unsigned char *value, size_t value_len)
+				struct message_header_line *hdr)
 {
 	struct message_part_envelope_data *d;
+	enum imap_envelope_field field;
+	struct message_address **addr_p;
+	char **str_p;
+
+	if (hdr == NULL || !imap_envelope_get_field(hdr->name, &field))
+		return;
+
+	if (hdr->continues) {
+		/* wait for full value */
+		hdr->use_full_value = TRUE;
+		return;
+	}
 
 	if (*data == NULL) {
 		*data = p_new(pool, struct message_part_envelope_data, 1);
@@ -31,61 +100,50 @@
 	}
 	d = *data;
 
-	t_push();
-
-	switch (name_len) {
-	case 2:
-		if (memcasecmp(name, "To", 2) == 0 && d->to == NULL) {
-			d->to = message_address_parse(pool, value,
-						      value_len, 0);
-		} else if (memcasecmp(name, "Cc", 2) == 0 && d->cc == NULL) {
-			d->cc = message_address_parse(pool, value,
-						      value_len, 0);
-		}
+	addr_p = NULL; str_p = NULL;
+	switch (field) {
+	case IMAP_ENVELOPE_DATE:
+		str_p = &d->date;
 		break;
-	case 3:
-		if (memcasecmp(name, "Bcc", 3) == 0 && d->bcc == NULL) {
-			d->bcc = message_address_parse(pool, value,
-						       value_len, 0);
-		}
+	case IMAP_ENVELOPE_SUBJECT:
+		str_p = &d->subject;
 		break;
-	case 4:
-		if (memcasecmp(name, "From", 4) == 0 && d->from == NULL) {
-			d->from = message_address_parse(pool, value,
-							value_len, 0);
-		} else if (memcasecmp(name, "Date", 4) == 0 && d->date == NULL)
-			d->date = imap_quote(pool, value, value_len);
+	case IMAP_ENVELOPE_MESSAGE_ID:
+		str_p = &d->message_id;
 		break;
-	case 6:
-		if (memcasecmp(name, "Sender", 6) == 0 && d->sender == NULL) {
-			d->sender = message_address_parse(pool, value,
-							  value_len, 0);
-		}
+	case IMAP_ENVELOPE_IN_REPLY_TO:
+		str_p = &d->in_reply_to;
 		break;
-	case 7:
-		if (memcasecmp(name, "Subject", 7) == 0 && d->subject == NULL)
-			d->subject = imap_quote(pool, value, value_len);
+
+	case IMAP_ENVELOPE_CC:
+		addr_p = &d->cc;
 		break;
-	case 8:
-		if (memcasecmp(name, "Reply-To", 8) == 0 &&
-		    d->reply_to == NULL) {
-			d->reply_to = message_address_parse(pool, value,
-							    value_len, 0);
-		}
+	case IMAP_ENVELOPE_BCC:
+		addr_p = &d->bcc;
 		break;
-	case 10:
-		if (memcasecmp(name, "Message-Id", 10) == 0 &&
-		    d->message_id == NULL)
-			d->message_id = imap_quote(pool, value, value_len);
+	case IMAP_ENVELOPE_FROM:
+		addr_p = &d->from;
 		break;
-	case 11:
-		if (memcasecmp(name, "In-Reply-To", 11) == 0 &&
-		    d->in_reply_to == NULL)
-			d->in_reply_to = imap_quote(pool, value, value_len);
+	case IMAP_ENVELOPE_SENDER:
+		addr_p = &d->sender;
+		break;
+	case IMAP_ENVELOPE_TO:
+		addr_p = &d->to;
+		break;
+	case IMAP_ENVELOPE_REPLY_TO:
+		addr_p = &d->reply_to;
+		break;
+	case IMAP_ENVELOPE_FIELDS:
 		break;
 	}
 
-	t_pop();
+	if (addr_p != NULL) {
+		*addr_p = message_address_parse(pool, hdr->full_value,
+						hdr->full_value_len, 0);
+	}
+
+	if (str_p != NULL)
+		*str_p = imap_quote(pool, hdr->full_value, hdr->full_value_len);
 }
 
 static void imap_write_address(string_t *str, struct message_address *addr)

Index: imap-envelope.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-envelope.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- imap-envelope.h	26 Mar 2003 15:40:16 -0000	1.9
+++ imap-envelope.h	26 Mar 2003 17:29:02 -0000	1.10
@@ -1,6 +1,8 @@
 #ifndef __IMAP_ENVELOPE_H
 #define __IMAP_ENVELOPE_H
 
+struct message_header_line;
+
 enum imap_envelope_field {
 	/* NOTE: in the same order as listed in ENVELOPE */
 	IMAP_ENVELOPE_DATE = 0,
@@ -24,11 +26,12 @@
 
 struct message_part_envelope_data;
 
+int imap_envelope_get_field(const char *name, enum imap_envelope_field *ret);
+
 /* Update envelope data based from given header field */
 void imap_envelope_parse_header(pool_t pool,
 				struct message_part_envelope_data **data,
-				const unsigned char *name, size_t name_len,
-				const unsigned char *value, size_t value_len);
+				struct message_header_line *hdr);
 
 /* Write envelope to given string */
 void imap_envelope_write_part_data(struct message_part_envelope_data *data,

Index: imap-quote.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-quote.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- imap-quote.c	26 Mar 2003 15:40:16 -0000	1.10
+++ imap-quote.c	26 Mar 2003 17:29:02 -0000	1.11
@@ -53,11 +53,18 @@
 char *imap_quote(pool_t pool, const unsigned char *value, size_t value_len)
 {
 	string_t *str;
+	char *ret;
+
+	i_assert(pool != data_stack_pool);
 
 	if (value == NULL)
 		return "NIL";
 
+	t_push();
 	str = t_str_new(value_len + MAX_INT_STRLEN + 5);
 	imap_quote_append(str, value, value_len);
-	return p_strndup(pool, str_data(str), str_len(str));
+	ret = p_strndup(pool, str_data(str), str_len(str));
+	t_pop();
+
+	return ret;
 }




More information about the dovecot-cvs mailing list