[dovecot-cvs] dovecot/src/lib-index/mbox mbox-index.c,1.66,1.67 mbox-index.h,1.25,1.26 mbox-rewrite.c,1.53,1.54

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


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

Modified Files:
	mbox-index.c mbox-index.h mbox-rewrite.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: mbox-index.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-index.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -d -r1.66 -r1.67
--- mbox-index.c	6 Mar 2003 19:23:45 -0000	1.66
+++ mbox-index.c	26 Mar 2003 17:29:02 -0000	1.67
@@ -248,16 +248,14 @@
 }
 
 void mbox_header_cb(struct message_part *part __attr_unused__,
-		    const unsigned char *name, size_t name_len,
-		    const unsigned char *value, size_t value_len,
-		    void *context)
+		    struct message_header_line *hdr, void *context)
 {
 	struct mbox_header_context *ctx = context;
 	uoff_t start_offset, end_offset;
 	size_t i;
 	int fixed = FALSE;
 
-	if (name_len == 0) {
+	if (hdr == NULL) {
 		/* End of headers */
 		if (!ctx->set_read_limit)
 			return;
@@ -281,99 +279,109 @@
 		return;
 	}
 
+	if (hdr->eoh)
+		return;
+
 	/* Pretty much copy&pasted from popa3d by Solar Designer */
-	switch (*name) {
+	switch (*hdr->name) {
 	case 'R':
 	case 'r':
-		if (!ctx->received && name_len == 8 &&
-		    memcasecmp(name, "Received", 8) == 0) {
-			ctx->received = TRUE;
+		if (!ctx->received &&
+		    strcasecmp(hdr->name, "Received") == 0) {
+			/* get only the first received-header */
 			fixed = TRUE;
+			if (!hdr->continues)
+				ctx->received = TRUE;
 		}
 		break;
 
 	case 'C':
 	case 'c':
-		if (name_len == 14 && ctx->set_read_limit &&
-		    memcasecmp(name, "Content-Length", 14) == 0) {
+		if (ctx->set_read_limit &&
+		    strcasecmp(hdr->name, "Content-Length") == 0) {
 			/* manual parsing, so we can deal with uoff_t */
 			ctx->content_length = 0;
-			for (i = 0; i < value_len; i++) {
-				if (value[i] < '0' || value[i] > '9') {
+			for (i = 0; i < hdr->value_len; i++) {
+				if (hdr->value[i] < '0' ||
+				    hdr->value[i] > '9') {
 					/* invalid */
 					ctx->content_length = 0;
 					break;
 				}
 
 				ctx->content_length = ctx->content_length * 10 +
-					(value[i] - '0');
+					(hdr->value[i] - '0');
 			}
 		}
 		break;
 
 	case 'D':
 	case 'd':
-		if (name_len == 12)
-			fixed = memcasecmp(name, "Delivered-To", 12) == 0;
-		else if (name_len == 4) {
+		if (strcasecmp(hdr->name, "Delivered-To") == 0)
+			fixed = TRUE;
+		else if (!ctx->received && strcasecmp(hdr->name, "Date") == 0) {
 			/* Received-header contains date too,
 			   and more trusted one */
-			fixed = !ctx->received &&
-				memcasecmp(name, "Date", 4) == 0;
+			fixed = TRUE;
 		}
 		break;
 
 	case 'M':
 	case 'm':
-		if (name_len == 10) {
+		if (!ctx->received &&
+		    strcasecmp(hdr->name, "Message-ID") == 0) {
 			/* Received-header contains unique ID too,
 			   and more trusted one */
-			fixed = !ctx->received &&
-				memcasecmp(name, "Message-ID", 10) == 0;
+			fixed = TRUE;
 		}
 		break;
 
 	case 'S':
 	case 's':
-		if (name_len == 6 && memcasecmp(name, "Status", 6) == 0) {
+		if (strcasecmp(hdr->name, "Status") == 0) {
 			/* update message flags */
-			ctx->flags |= mbox_get_status_flags(value, value_len);
+			ctx->flags |= mbox_get_status_flags(hdr->value,
+							    hdr->value_len);
 		}
 		break;
 
 	case 'X':
 	case 'x':
-		if (name_len == 13) {
+		if (strcasecmp(hdr->name, "X-Delivery-ID:") == 0) {
 			/* Let the local delivery agent help generate unique
 			   ID's but don't blindly trust this header alone as
 			   it could just as easily come from the remote. */
-			fixed = memcasecmp(name, "X-Delivery-ID:", 13) == 0;
-		} else if (name_len == 5 &&
-			   memcasecmp(name, "X-UID", 5) == 0) {
+			fixed = TRUE;
+		} else if (strcasecmp(hdr->name, "X-UID") == 0) {
 			ctx->uid = 0;
-			for (i = 0; i < value_len; i++) {
-				if (value[i] < '0' || value[i] > '9')
+			for (i = 0; i < hdr->value_len; i++) {
+				if (hdr->value[i] < '0' ||
+				    hdr->value[i] > '9')
 					break;
-				ctx->uid = ctx->uid * 10 + (value[i]-'0');
+				ctx->uid = ctx->uid * 10 + (hdr->value[i]-'0');
 			}
-		} else if (name_len == 8 &&
-			   memcasecmp(name, "X-Status", 8) == 0) {
+		} else if (strcasecmp(hdr->name, "X-Status") == 0) {
 			/* update message flags */
-			ctx->flags |= mbox_get_status_flags(value, value_len);
-		} else if (name_len == 10 &&
-			   memcasecmp(name, "X-Keywords", 10) == 0) {
+			ctx->flags |= mbox_get_status_flags(hdr->value,
+							    hdr->value_len);
+		} else if (strcasecmp(hdr->name, "X-Keywords") == 0) {
 			/* update custom message flags */
-			ctx->flags |= mbox_get_keyword_flags(value, value_len,
+			ctx->flags |= mbox_get_keyword_flags(hdr->value,
+							     hdr->value_len,
 							     ctx->custom_flags);
-		} else if (name_len == 10 &&
-			   memcasecmp(name, "X-IMAPbase", 10) == 0) {
-			mbox_parse_imapbase(value, value_len, ctx);
+		} else if (strcasecmp(hdr->name, "X-IMAPbase") == 0) {
+			if (hdr->continues) {
+				hdr->use_full_value = TRUE;
+				break;
+			}
+			mbox_parse_imapbase(hdr->full_value,
+					    hdr->full_value_len, ctx);
 		}
 		break;
 	}
 
 	if (fixed)
-		md5_update(&ctx->md5, value, value_len);
+		md5_update(&ctx->md5, hdr->value, hdr->value_len);
 }
 
 void mbox_keywords_parse(const unsigned char *value, size_t len,

Index: mbox-index.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-index.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mbox-index.h	6 Mar 2003 19:23:45 -0000	1.25
+++ mbox-index.h	26 Mar 2003 17:29:02 -0000	1.26
@@ -33,10 +33,8 @@
 			      struct mail_index *index,
 			      struct istream *input);
 void mbox_header_free_context(struct mbox_header_context *ctx);
-void mbox_header_cb(struct message_part *part __attr_unused__,
-		    const unsigned char *name, size_t name_len,
-		    const unsigned char *value, size_t value_len,
-		    void *context);
+void mbox_header_cb(struct message_part *part,
+		    struct message_header_line *hdr, void *context);
 void mbox_keywords_parse(const unsigned char *value, size_t len,
 			 const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT],
 			 void (*func)(const unsigned char *, size_t,

Index: mbox-rewrite.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-rewrite.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- mbox-rewrite.c	6 Mar 2003 19:23:45 -0000	1.53
+++ mbox-rewrite.c	26 Mar 2003 17:29:02 -0000	1.54
@@ -20,7 +20,6 @@
 
 struct mbox_rewrite_context {
 	struct ostream *output;
-	int failed;
 
 	uoff_t content_length;
 	unsigned int seq, uid;
@@ -258,51 +257,96 @@
 	return str_len(str) == 0 ? NULL : str_c(str);
 }
 
-static void header_cb(struct message_part *part __attr_unused__,
-		      const unsigned char *name, size_t name_len,
-		      const unsigned char *value, size_t value_len,
-		      void *context)
+static int write_header(struct mbox_rewrite_context *ctx,
+			struct message_header_line *hdr)
 {
-	struct mbox_rewrite_context *ctx = context;
 	const char *str;
 
-	if (ctx->failed)
-		return;
+	switch (hdr->name_len) {
+	case 5:
+		if (strcasecmp(hdr->name, "X-UID") == 0) {
+			if (ctx->xuid_found)
+				return TRUE;
+
+			ctx->xuid_found = TRUE;
+			return mbox_write_xuid(ctx);
+		}
+		break;
+	case 6:
+		if (strcasecmp(hdr->name, "Status") == 0) {
+			if (ctx->status_found)
+				return TRUE;
+			if (hdr->continues) {
+				hdr->use_full_value = TRUE;
+				return TRUE;
+			}
+
+			ctx->status_found = TRUE;
+			str = strip_chars(hdr->full_value,
+					  hdr->full_value_len, "RO");
+			return mbox_write_status(ctx, str);
+		}
+		break;
+	case 8:
+		if (strcasecmp(hdr->name, "X-Status") == 0) {
+			if (ctx->xstatus_found)
+				return TRUE;
+			if (hdr->continues) {
+				hdr->use_full_value = TRUE;
+				return TRUE;
+			}
+
+			ctx->xstatus_found = TRUE;
+			str = strip_chars(hdr->full_value,
+					  hdr->full_value_len, "ADFT");
+			return mbox_write_xstatus(ctx, str);
+		}
+		break;
+	case 10:
+		if (strcasecmp(hdr->name, "X-Keywords") == 0) {
+			if (ctx->xkeywords_found)
+				return TRUE;
+			if (hdr->continues) {
+				hdr->use_full_value = TRUE;
+				return TRUE;
+			}
+
+			ctx->xkeywords_found = TRUE;
+			str = strip_custom_flags(hdr->full_value,
+						 hdr->full_value_len, ctx);
+			return mbox_write_xkeywords(ctx, str);
+		} else if (strcasecmp(hdr->name, "X-IMAPbase") == 0) {
+			if (ctx->seq != 1 || ctx->ximapbase_found)
+				return TRUE;
 
-	if (name_len == 6 && memcasecmp(name, "Status", 6) == 0) {
-		ctx->status_found = TRUE;
-		str = strip_chars(value, value_len, "RO");
-		(void)mbox_write_status(ctx, str);
-	} else if (name_len == 8 && memcasecmp(name, "X-Status", 8) == 0) {
-		ctx->xstatus_found = TRUE;
-		str = strip_chars(value, value_len, "ADFT");
-		(void)mbox_write_xstatus(ctx, str);
-	} else if (name_len == 10 && memcasecmp(name, "X-Keywords", 10) == 0) {
-		ctx->xkeywords_found = TRUE;
-		str = strip_custom_flags(value, value_len, ctx);
-		(void)mbox_write_xkeywords(ctx, str);
-	} else if (name_len == 10 && memcasecmp(name, "X-IMAPbase", 10) == 0) {
-		if (ctx->seq == 1) {
 			ctx->ximapbase_found = TRUE;
-			(void)mbox_write_ximapbase(ctx);
+			return mbox_write_ximapbase(ctx);
 		}
-	} else if (name_len == 5 && memcasecmp(name, "X-UID", 5) == 0) {
-		ctx->xuid_found = TRUE;
-		(void)mbox_write_xuid(ctx);
-	} else if (name_len == 14 &&
-		   memcasecmp(name, "Content-Length", 14) == 0) {
-		ctx->content_length_found = TRUE;
-		(void)mbox_write_content_length(ctx);
-	} else if (name_len > 0) {
+		break;
+	case 14:
+		if (strcasecmp(hdr->name, "Content-Length") == 0) {
+			if (ctx->content_length_found)
+				return TRUE;
+
+			ctx->content_length_found = TRUE;
+			return mbox_write_content_length(ctx);
+		}
+		break;
+	}
+
+	if (!hdr->eoh) {
 		/* save this header */
-		(void)o_stream_send(ctx->output, name, name_len);
-		(void)o_stream_send(ctx->output, ": ", 2);
-		(void)o_stream_send(ctx->output, value, value_len);
-		(void)o_stream_send(ctx->output, "\n", 1);
+		if (!hdr->continued) {
+			(void)o_stream_send(ctx->output, hdr->name,
+					    hdr->name_len);
+			(void)o_stream_send(ctx->output, ": ", 2);
+		}
+		(void)o_stream_send(ctx->output, hdr->value, hdr->value_len);
+		if (!hdr->no_newline)
+			(void)o_stream_send(ctx->output, "\n", 1);
 	}
 
-	if (ctx->output->closed)
-		ctx->failed = TRUE;
+	return !ctx->output->closed;
 }
 
 static int mbox_write_header(struct mail_index *index,
@@ -323,6 +367,8 @@
 	   Last used UID is also not updated, and set to 0 initially.
 	*/
 	struct mbox_rewrite_context ctx;
+	struct message_header_parser_ctx *hdr_ctx;
+	struct message_header_line *hdr;
 	struct message_size hdr_parsed_size;
 
 	if (input->v_offset >= end_offset) {
@@ -346,7 +392,12 @@
 	ctx.custom_flags = mail_custom_flags_list_get(index->custom_flags);
 
 	i_stream_set_read_limit(input, input->v_offset + hdr_size);
-	message_parse_header(NULL, input, &hdr_parsed_size, header_cb, &ctx);
+
+	hdr_ctx = message_parse_header_init(input, &hdr_parsed_size);
+	while ((hdr = message_parse_header_next(hdr_ctx)) != NULL)
+		write_header(&ctx, hdr);
+	message_parse_header_deinit(hdr_ctx);
+
 	i_stream_set_read_limit(input, 0);
 
 	i_assert(hdr_parsed_size.physical_size == hdr_size);




More information about the dovecot-cvs mailing list