[dovecot-cvs] dovecot/src/lib-mail message-body-search.c,1.3,1.4 message-header-search.c,1.5,1.6 message-header-search.h,1.2,1.3 message-parser.c,1.26,1.27 message-part-serialize.c,1.6,1.7 message-part-serialize.h,1.4,1.5 quoted-printable.c,1.1,1.2 Message-Id: <20021208052310.917F5238CA@danu.procontrol.fi>

cras at procontrol.fi cras at procontrol.fi
Sun Dec 8 07:23:10 EET 2002


Update of /home/cvs/dovecot/src/lib-mail
In directory danu:/tmp/cvs-serv19285/lib-mail

Modified Files:
	message-body-search.c message-header-search.c 
	message-header-search.h message-parser.c 
	message-part-serialize.c message-part-serialize.h 
	quoted-printable.c quoted-printable.h 
Log Message:
Added buffer API. Point is to hide all buffer writing behind this API which
verifies that nothing overflows. Much better than doing the same checks all
around the code, even if it is slightly slower.

Buffer reading is still mostly done directly, that isn't such a big security
risk and I can't think of a reasonable API for it anyway.



Index: message-body-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-body-search.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- message-body-search.c	6 Dec 2002 01:09:23 -0000	1.3
+++ message-body-search.c	8 Dec 2002 05:23:08 -0000	1.4
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "base64.h"
+#include "buffer.h"
 #include "istream.h"
 #include "charset-utf8.h"
 #include "rfc822-tokenize.h"
@@ -30,14 +31,13 @@
 	HeaderSearchContext *hdr_search_ctx;
 	CharsetTranslation *translation;
 
-	unsigned char decode_buf[DECODE_BLOCK_SIZE];
-	size_t decode_buf_used;
+	Buffer *decode_buf;
 
 	size_t *matches;
 	ssize_t match_count;
 
-	const char *content_type;
-	const char *content_charset;
+	char *content_type;
+	char *content_charset;
 
 	unsigned int content_qp:1;
 	unsigned int content_base64:1;
@@ -53,7 +53,8 @@
 	PartSearchContext *ctx = context;
 
 	if (ctx->content_type != NULL && tokens[0].token == 'A') {
-		ctx->content_type = rfc822_tokens_get_value(tokens, count);
+		ctx->content_type =
+			i_strdup(rfc822_tokens_get_value(tokens, count));
 		ctx->content_type_text =
 			strncasecmp(ctx->content_type, "text/", 5) == 0 ||
 			strncasecmp(ctx->content_type, "message/", 8) == 0;
@@ -71,7 +72,7 @@
 
 	if (ctx->content_charset == NULL) {
 		ctx->content_charset =
-			rfc822_tokens_get_value(value, value_count);
+			i_strdup(rfc822_tokens_get_value(value, value_count));
 	}
 }
 
@@ -117,10 +118,12 @@
 		return;
 
 	if (!ctx->ignore_header) {
-		ctx->found = message_header_search(value, &value_len,
+		ctx->found = message_header_search(value, value_len,
 						   ctx->hdr_search_ctx);
 	}
 
+	t_push();
+
 	if (name_len == 12 && strncasecmp(name, "Content-Type", 12) == 0) {
 		(void)message_content_parse_header(t_strndup(value, value_len),
 						   parse_content_type,
@@ -132,6 +135,8 @@
 						   parse_content_encoding,
 						   NULL, ctx);
 	}
+
+	t_pop();
 }
 
 static int message_search_header(PartSearchContext *ctx, IStream *input)
@@ -148,26 +153,24 @@
 	return ctx->found;
 }
 
-static int message_search_decoded_block(PartSearchContext *ctx,
-					const unsigned char *data, size_t size)
+static int message_search_decoded_block(PartSearchContext *ctx, Buffer *block)
 {
 	const unsigned char *p, *end, *key;
-	size_t key_len;
+	size_t key_len, block_size;
 	ssize_t i;
-	int found;
 
 	key = (const unsigned char *) ctx->body_ctx->key;
 	key_len = ctx->body_ctx->key_len;
 
-	end = data + size; found = 0;
-	for (p = data; p != end; p++) {
+	p = buffer_get_data(block, &block_size);
+	end = p + block_size;
+	for (; p != end; p++) {
 		for (i = ctx->match_count-1; i >= 0; i--) {
 			if (key[ctx->matches[i]] == *p) {
 				if (++ctx->matches[i] == key_len) {
 					/* full match */
 					p++;
-					found = TRUE;
-					break;
+					return TRUE;
 				}
 			} else {
 				/* non-match */
@@ -180,73 +183,75 @@
 			}
 		}
 
-		if (found)
-			break;
-
 		if (*p == key[0]) {
 			if (key_len == 1) {
 				/* only one character in search key */
 				p++;
-				found = 1;
-				break;
+				return TRUE;
 			}
+
 			i_assert((size_t)ctx->match_count < key_len);
 			ctx->matches[ctx->match_count++] = 1;
 		}
 	}
 
-	return found;
+	return FALSE;
 }
 
-static int message_search_body_block(PartSearchContext *ctx,
-				     const unsigned char *data, size_t size)
+/* returns 1 = found, 0 = not found, -1 = error in input data */
+static int message_search_body_block(PartSearchContext *ctx, Buffer *block)
 {
-	const unsigned char *inbuf;
-	unsigned char outbuf[DECODE_BLOCK_SIZE];
-	size_t inbuf_size, outbuf_size, max_size;
-
-	while (size > 0) {
-		if (ctx->decode_buf_used == 0) {
-			inbuf = data;
-			inbuf_size = I_MIN(size, sizeof(ctx->decode_buf));
+	Buffer *inbuf, *outbuf;
+        CharsetResult result;
+	size_t block_pos, inbuf_pos, inbuf_left, ret;
 
-			data += inbuf_size;
-			size -= inbuf_size;
+	outbuf = buffer_create_static(data_stack_pool, DECODE_BLOCK_SIZE);
+	for (block_pos = 0; block_pos < buffer_get_used_size(block); ) {
+		if (buffer_get_used_size(ctx->decode_buf) == 0) {
+			/* we can use the buffer directly without copying */
+			inbuf = block;
+			inbuf_pos = block_pos;
+			block_pos += buffer_get_used_size(block);
 		} else {
 			/* some characters already in buffer, ie. last
 			   conversion contained partial data */
-			max_size = sizeof(ctx->decode_buf) -
-				ctx->decode_buf_used;
-			if (max_size > size)
-				max_size = size;
-
-			memcpy(ctx->decode_buf + ctx->decode_buf_used,
-			       data, max_size);
-			ctx->decode_buf_used += max_size;
+			block_pos += buffer_append_buf(ctx->decode_buf,
+						       block, block_pos,
+						       (size_t)-1);
 
 			inbuf = ctx->decode_buf;
-			inbuf_size = ctx->decode_buf_used;
-
-			data += max_size;
-			size -= max_size;
+			inbuf_pos = 0;
 		}
 
-		outbuf_size = sizeof(outbuf);
-		if (!charset_to_ucase_utf8(ctx->translation,
-					   &inbuf, &inbuf_size,
-					   outbuf, &outbuf_size)) {
-			/* something failed */
+		buffer_set_used_size(outbuf, 0);
+		result = charset_to_ucase_utf8(ctx->translation,
+					       inbuf, &inbuf_pos, outbuf);
+		inbuf_left = buffer_get_used_size(inbuf) - inbuf_pos;
+
+		switch (result) {
+		case CHARSET_RET_OUTPUT_FULL:
+			/* we should have copied the incomplete sequence.. */
+			i_assert(inbuf_left <= block_pos);
+			/* fall through */
+		case CHARSET_RET_OK:
+			buffer_set_used_size(ctx->decode_buf, 0);
+			block_pos -= inbuf_left;
+			break;
+		case CHARSET_RET_INCOMPLETE_INPUT:
+			/* save the partial sequence to buffer */
+			ret = buffer_copy(ctx->decode_buf, 0,
+					  inbuf, inbuf_pos, inbuf_left);
+			i_assert(ret == inbuf_left);
+
+			buffer_set_used_size(ctx->decode_buf, ret);
+			break;
+
+		case CHARSET_RET_INVALID_INPUT:
 			return -1;
 		}
 
-		if (message_search_decoded_block(ctx, outbuf, outbuf_size))
+		if (message_search_decoded_block(ctx, outbuf))
 			return 1;
-
-		if (inbuf_size > 0) {
-			/* partial input, save it */
-			memmove(ctx->decode_buf, inbuf, inbuf_size);
-			ctx->decode_buf_used = inbuf_size;
-		}
 	}
 
 	return 0;
@@ -255,9 +260,9 @@
 static int message_search_body(PartSearchContext *ctx, IStream *input,
 			       MessagePart *part)
 {
-	const unsigned char *data, *decoded;
-	unsigned char *decodebuf;
-	size_t data_size, decoded_size, pos;
+	const unsigned char *data;
+	Buffer *decodebuf;
+	size_t data_size, pos;
 	uoff_t old_limit;
 	ssize_t ret;
 	int found;
@@ -277,6 +282,8 @@
 	if (ctx->translation == NULL)
 		ctx->translation = charset_to_utf8_begin("ascii", NULL);
 
+	ctx->decode_buf = buffer_create_static(data_stack_pool, 256);
+
 	ctx->match_count = 0;
 	ctx->matches = t_malloc(sizeof(size_t) * ctx->body_ctx->key_len);
 
@@ -296,28 +303,35 @@
 
 		t_push();
 		if (ctx->content_qp) {
-			decoded = decodebuf = t_malloc(data_size);
-			decoded_size = quoted_printable_decode(data, &data_size,
-							       decodebuf);
+			decodebuf = buffer_create_static_hard(data_stack_pool,
+							      data_size);
+			quoted_printable_decode(data, data_size,
+						&data_size, decodebuf);
 		} else if (ctx->content_base64) {
-			decoded_size = MAX_BASE64_DECODED_SIZE(data_size);
-			decoded = decodebuf = t_malloc(decoded_size);
+			size_t size = MAX_BASE64_DECODED_SIZE(data_size);
+			decodebuf = buffer_create_static_hard(data_stack_pool,
+							      size);
 
-			ret = base64_decode(data, &data_size, decodebuf);
-			decoded_size = ret < 0 ? 0 : (size_t)decoded_size;
+			if (base64_decode(data, data_size,
+					  &data_size, decodebuf) < 0) {
+				/* corrupted base64 data, don't bother with
+				   the rest of it */
+				t_pop();
+				break;
+			}
 		} else {
-			decoded = data;
-			decoded_size = data_size;
+			decodebuf = buffer_create_const_data(data_stack_pool,
+							     data, data_size);
 		}
 
-		ret = message_search_body_block(ctx, decoded, decoded_size);
+		ret = message_search_body_block(ctx, decodebuf);
+		t_pop();
+
 		if (ret != 0) {
-			t_pop();
 			found = ret > 0;
 			break;
 		}
 
-		t_pop();
 		i_stream_skip(input, data_size);
 		pos -= data_size;
 	}
@@ -333,25 +347,26 @@
 				    const char *charset, int *unknown_charset,
 				    int search_header)
 {
-	size_t size;
+	Buffer *keybuf;
+	size_t key_len;
 
 	memset(ctx, 0, sizeof(BodySearchContext));
 
 	/* get the key uppercased */
-	size = strlen(key);
+        keybuf = buffer_create_const_data(data_stack_pool, key, strlen(key));
 	key = charset_to_ucase_utf8_string(charset, unknown_charset,
-					   (const unsigned char *) key, &size);
+					   keybuf, &key_len);
 	if (key == NULL)
 		return FALSE;
 
-	i_assert(size <= SSIZE_T_MAX/sizeof(size_t));
-
 	ctx->key = key;
-	ctx->key_len = size;
+	ctx->key_len = key_len;
 	ctx->charset = charset;
 	ctx->unknown_charset = charset == NULL;
 	ctx->search_header = search_header;
 
+	i_assert(ctx->key_len <= SSIZE_T_MAX/sizeof(size_t));
+
 	return TRUE;
 }
 
@@ -384,6 +399,9 @@
 			if (message_search_body(&part_ctx, input, part))
 				found = TRUE;
 		}
+
+		i_free(part_ctx.content_type);
+		i_free(part_ctx.content_charset);
 
 		t_pop();
 

Index: message-header-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-header-search.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- message-header-search.c	1 Dec 2002 18:17:53 -0000	1.5
+++ message-header-search.c	8 Dec 2002 05:23:08 -0000	1.6
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "base64.h"
+#include "buffer.h"
 #include "charset-utf8.h"
 #include "rfc822-tokenize.h"
 #include "quoted-printable.h"
@@ -19,9 +20,9 @@
 	size_t *matches; /* size of strlen(key) */
 	ssize_t match_count;
 
+	unsigned int found:1;
 	unsigned int last_newline:1;
 	unsigned int submatch:1;
-	unsigned int eoh:1;
 	unsigned int key_ascii:1;
 	unsigned int unknown_charset:1;
 };
@@ -31,35 +32,39 @@
 			   int *unknown_charset)
 {
 	HeaderSearchContext *ctx;
+	Buffer *keybuf;
+	size_t key_len;
 	const char *p;
-	size_t size;
 
 	ctx = p_new(pool, HeaderSearchContext, 1);
 	ctx->pool = pool;
 
 	/* get the key uppercased */
-	size = strlen(key);
+	keybuf = buffer_create_const_data(data_stack_pool, key, strlen(key));
 	key = charset_to_ucase_utf8_string(charset, unknown_charset,
-					   (const unsigned char *) key, &size);
-	if (key == NULL)
-		return NULL;
+					   keybuf, &key_len);
 
-	i_assert(size <= SSIZE_T_MAX/sizeof(size_t));
+	if (key == NULL) {
+		/* invalid key */
+		t_pop();
+		return NULL;
+	}
 
 	ctx->key = p_strdup(pool, key);
-	ctx->key_len = size;
+	ctx->key_len = key_len;
 	ctx->key_charset = p_strdup(pool, charset);
 	ctx->unknown_charset = charset == NULL;
 
 	ctx->key_ascii = TRUE;
-	for (p = key; *p != '\0'; p++) {
+	for (p = ctx->key; *p != '\0'; p++) {
 		if ((*p & 0x80) != 0) {
 			ctx->key_ascii = FALSE;
 			break;
 		}
 	}
 
-	ctx->matches = p_malloc(pool, sizeof(size_t) * ctx->key_len);
+	i_assert(ctx->key_len <= SSIZE_T_MAX/sizeof(size_t));
+	ctx->matches = p_new(pool, size_t, ctx->key_len);
 	return ctx;
 }
 
@@ -74,9 +79,11 @@
 	p_free(pool, ctx);
 }
 
-static int match_data(const unsigned char *data, size_t size,
-		      const char *charset, HeaderSearchContext *ctx)
+static int match_data(const Buffer *buffer, const char *charset,
+		      HeaderSearchContext *ctx)
 {
+	const char *utf8_data;
+	size_t size;
 	int ret;
 
 	if (ctx->unknown_charset) {
@@ -89,174 +96,162 @@
 		charset = ctx->key_charset;
 	}
 
-	data = (const unsigned char *)
-		charset_to_ucase_utf8_string(charset, NULL, data, &size);
-	if (data == NULL) {
+	utf8_data = charset_to_ucase_utf8_string(charset, NULL, buffer, &size);
+	if (utf8_data == NULL) {
 		/* unknown character set, or invalid data */
 		return FALSE;
 	}
 
 	ctx->submatch = TRUE;
-	ret = message_header_search(data, &size, ctx);
+	ret = message_header_search(utf8_data, size, ctx);
 	ctx->submatch = FALSE;
 
 	return ret;
 }
 
-static int match_encoded(const unsigned char **start, const unsigned char *end,
-			 HeaderSearchContext *ctx)
+static int split_encoded(Buffer *buffer, size_t *last_pos,
+			 const char **charset, const char **encoding)
 {
-	const unsigned char *p, *encoding, *text, *new_end;
-	const char *charset;
-	unsigned char *buf;
-	ssize_t size;
-	size_t buf_size;
-	int ok, ret;
+	const char *p;
+	size_t size, pos, textpos;
 
-	/* first split the string =?charset?encoding?text?= */
-	ok = FALSE;
-	charset = (const char *) *start; encoding = NULL; text = NULL;
-	for (p = *start; p != end; p++) {
-		if (*p == '?') {
-			if (encoding == NULL) {
-				charset = t_strdup_until(charset, p);
-				encoding = p+1;
-			} else if (text == NULL) {
-				if (p != encoding+1)
-					encoding = "?";
-				else if (*encoding == 'Q' || *encoding == 'q')
-					encoding = "Q";
-				else if (*encoding == 'B' || *encoding == 'b')
-					encoding = "B";
-				else
-					encoding = "?";
+	p = buffer_get_data(buffer, &size);
 
-				text = p+1;
-			} else {
-				new_end = p;
+	/* get charset */
+	for (pos = 0; pos < size && p[pos] != '?'; pos++) ;
+	if (p[pos] != '?') return FALSE;
+	*charset = t_strndup(p, pos);
 
-				p++;
-				if (p != end && *p == '=')
-					p++;
+	/* get encoding */
+	pos++;
+	if (pos+2 >= size || p[pos+1] != '?')
+		return FALSE;
 
-				end = new_end;
-				*start = p-1;
-				ok = TRUE;
-				break;
-			}
-		}
-	}
+	if (p[pos] == 'Q' || p[pos] == 'q')
+		*encoding = "Q";
+	else if (p[pos] == 'B' || p[pos] == 'b')
+		*encoding = "B";
+	else
+		return FALSE;
 
-	if (ok && *encoding != '?') {
-		t_push();
+	/* get text */
+	pos += 2;
+	textpos = pos;
+	for (; pos < size && p[pos] != '?'; pos++) ;
+	if (p[pos] != '?' || pos+1 >= size || p[pos+1] != '=') return FALSE;
 
-		size = (ssize_t) (end - text);
+	buffer_set_limit(buffer, pos);
+	buffer_set_start_pos(buffer, textpos + buffer_get_start_pos(buffer));
+	*last_pos = pos+1;
 
-		buf_size = (size_t)size;
-		buf = t_malloc(buf_size);
+	return TRUE;
+}
 
-		if (*encoding == 'Q')
-			size = quoted_printable_decode(text, &buf_size, buf);
-		else
-			size = base64_decode(text, &buf_size, buf);
+static int match_encoded(Buffer *buffer, size_t *last_pos,
+			 HeaderSearchContext *ctx)
+{
+	const char *charset, *encoding, *text;
+	Buffer *decodebuf;
+	size_t textsize;
 
-		if (size >= 0) {
-			/* non-corrupted encoding */
-			ret = match_data(buf, (size_t)size, charset, ctx);
-			t_pop();
-			return ret;
-		}
+	/* first split the string charset?encoding?text?= */
+	if (!split_encoded(buffer, last_pos, &charset, &encoding)) {
+		ctx->match_count = 0;
+		return FALSE;
+	}
 
-		t_pop();
+	/* buffer is now limited to only the text portion */
+	text = buffer_get_data(buffer, &textsize);
+	decodebuf = buffer_create_static_hard(data_stack_pool, textsize);
+
+	if (*encoding == 'Q')
+		quoted_printable_decode(text, textsize, NULL, decodebuf);
+	else {
+		if (base64_decode(text, textsize, NULL, decodebuf) < 0) {
+			/* corrupted encoding */
+			ctx->match_count = 0;
+			return FALSE;
+		}
 	}
 
-	/* non-supported encoding, we can't match it */
-	ctx->match_count = 0;
-	return FALSE;
+	return match_data(decodebuf, charset, ctx);
 }
 
-int message_header_search(const unsigned char *header_block,
-			  size_t *header_size, HeaderSearchContext *ctx)
+int message_header_search(const unsigned char *header_block, size_t size,
+			  HeaderSearchContext *ctx)
 {
-	const unsigned char *p, *end;
-	unsigned char chr;
+	Buffer *buf;
 	ssize_t i;
-	int found;
+	size_t pos, subpos;
+	unsigned char chr;
+	int last_newline, ret;
 
-	if (ctx->eoh || *header_size == 0)
-		return FALSE;
+	if (ctx->found)
+		return TRUE;
 
-	end = header_block + *header_size;
+	t_push();
+	buf = buffer_create_const_data(data_stack_pool, header_block, size);
 
-	found = FALSE;
-	for (p = header_block; p != end; p++) {
-		if (p[0] == '=' && p+1 != end && p[1] == '?' &&
-		    !ctx->submatch) {
+	last_newline = ctx->last_newline;
+	for (pos = 0; pos < size; pos++) {
+		chr = header_block[pos];
+
+		if (chr == '=' && pos+1 < size &&
+		    header_block[pos+1] == '?' && !ctx->submatch) {
 			/* encoded string. read it. */
-			p += 2;
+                        buffer_set_start_pos(buf, pos+2);
+
 			t_push();
-			if (match_encoded(&p, end, ctx)) {
-				t_pop();
-				found = TRUE;
+			ret = match_encoded(buf, &subpos, ctx);
+			t_pop();
+
+			if (ret) {
+				ctx->found = TRUE;
 				break;
 			}
-			t_pop();
 
-			i_assert(p != end);
+			buffer_set_start_pos(buf, 0);
+			buffer_set_limit(buf, (size_t)-1);
+
+			pos += subpos - 1;
+			last_newline = FALSE;
 			continue;
 		}
 
-		if (ctx->submatch)
-			chr = *p;
-		else if ((*p & 0x80) == 0)
-			chr = i_toupper(*p);
-		else if (ctx->key_ascii || ctx->unknown_charset)
-			chr = *p;
-		else {
-			/* we have non-ascii in header. treat the rest of the
-			   header as encoded with the key's charset */
-			t_push();
-			found = match_data(p, (size_t) (end-p),
-					   ctx->key_charset, ctx);
-			t_pop();
-			break;
+		if (!ctx->submatch) {
+			if ((chr & 0x80) == 0)
+				chr = i_toupper(chr);
+			else if (!ctx->key_ascii && !ctx->unknown_charset) {
+				/* we have non-ascii in header and key contains
+				   non-ascii characters. treat the rest of the
+				   header as encoded with the key's charset */
+				t_push();
+				ctx->found = match_data(buf, ctx->key_charset,
+							ctx);
+				t_pop();
+				break;
+			}
 		}
 
-		chr = ctx->submatch || (*p & 0x80) != 0 ? *p : i_toupper(*p);
-
-		if (((p == header_block && ctx->last_newline) ||
-		     (p != header_block && p[-1] == '\n')) && !ctx->submatch) {
-			/* newline */
-			if (!IS_LWSP(*p)) {
+		if (last_newline && !ctx->submatch) {
+			if (!IS_LWSP(chr)) {
 				/* not a long header, reset matches */
 				ctx->match_count = 0;
-
-				/* and see if we're at end of header */
-				if (*p == '\n') {
-					p++;
-					ctx->eoh = TRUE;
-					break;
-				}
-
-				if (*p == '\r' && p[1] == '\n') {
-					p += 2;
-					ctx->eoh = TRUE;
-					break;
-				}
 			}
 			chr = ' ';
 		}
+		last_newline = chr == '\n';
 
-		if (*p == '\r' || *p == '\n')
+		if (chr == '\r' || chr == '\n')
 			continue;
 
 		for (i = ctx->match_count-1; i >= 0; i--) {
 			if (ctx->key[ctx->matches[i]] == chr) {
 				if (++ctx->matches[i] == ctx->key_len) {
 					/* full match */
-					p++;
-					found = TRUE;
-					break;
+					ctx->found = TRUE;
+					t_pop();
+					return TRUE;
 				}
 			} else {
 				/* non-match */
@@ -269,29 +264,24 @@
 			}
 		}
 
-		if (found)
-			break;
-
 		if (chr == ctx->key[0]) {
 			if (ctx->key_len == 1) {
 				/* only one character in search key */
-				p++;
-				found = TRUE;
+				ctx->found = TRUE;
 				break;
 			}
 			i_assert((size_t)ctx->match_count < ctx->key_len);
 			ctx->matches[ctx->match_count++] = 1;
 		}
 	}
+	t_pop();
 
-	*header_size = (size_t) (p - header_block);
-
-	ctx->last_newline = end[-1] == '\n';
-	return found;
+	ctx->last_newline = last_newline;
+	return ctx->found;
 }
 
 void message_header_search_reset(HeaderSearchContext *ctx)
 {
-	ctx->eoh = FALSE;
 	ctx->match_count = 0;
+	ctx->found = FALSE;
 }

Index: message-header-search.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-header-search.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- message-header-search.h	13 Nov 2002 11:08:18 -0000	1.2
+++ message-header-search.h	8 Dec 2002 05:23:08 -0000	1.3
@@ -14,11 +14,9 @@
 
 /* Returns TRUE if key is found from header. This function may be called
    multiple times with partial header blocks, but the blocks must contain only
-   full lines so RFC2047 parsing can be done. *header_size is updated to
-   contain the number of bytes we didn't access (either because we got a match,
-   or because end of headers). */
-int message_header_search(const unsigned char *header_block,
-			  size_t *header_size, HeaderSearchContext *ctx);
+   full lines so RFC2047 parsing can be done. */
+int message_header_search(const unsigned char *header_block, size_t size,
+			  HeaderSearchContext *ctx);
 
 /* Next call to message_header_search() will begin a new header. */
 void message_header_search_reset(HeaderSearchContext *ctx);

Index: message-parser.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-parser.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- message-parser.c	6 Dec 2002 01:09:23 -0000	1.26
+++ message-parser.c	8 Dec 2002 05:23:08 -0000	1.27
@@ -253,9 +253,7 @@
 	parse_ctx.context = context;
 	parse_ctx.part = part = p_new(pool, MessagePart, 1);
 
-	t_push();
 	message_parse_part(input, &parse_ctx);
-	t_pop();
 	return part;
 }
 

Index: message-part-serialize.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-part-serialize.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- message-part-serialize.c	30 Sep 2002 20:02:11 -0000	1.6
+++ message-part-serialize.c	8 Dec 2002 05:23:08 -0000	1.7
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
+#include "buffer.h"
 #include "message-parser.h"
 #include "message-part-serialize.h"
 
@@ -32,25 +33,14 @@
 	unsigned int flags;
 } SerializedMessagePart;
 
-static void message_part_serialize_part(MessagePart *part,
-					unsigned int *children_count,
-					SerializedMessagePart **spart_base,
-					size_t *pos, size_t *size)
+void message_part_serialize(MessagePart *part, Buffer *dest)
 {
 	SerializedMessagePart *spart;
-	size_t buf_size;
 
 	while (part != NULL) {
-		/* make sure we have space */
-		if (*pos == *size) {
-			*size *= 2;
-			buf_size = sizeof(SerializedMessagePart) * (*size);
-
-			*spart_base = t_buffer_reget(*spart_base, buf_size);
-		}
-
 		/* create serialized part */
-		spart = (*spart_base) + (*pos);
+		spart = buffer_append_space(dest,
+					    sizeof(SerializedMessagePart));
 		memset(spart, 0, sizeof(SerializedMessagePart));
 
 		spart->physical_pos = part->physical_pos;
@@ -66,33 +56,10 @@
 		spart->children_count = 0;
 		spart->flags = part->flags;
 
-		if (children_count != NULL)
-			(*children_count)++;
-		(*pos)++;
-
-		if (part->children != NULL) {
-			message_part_serialize_part(part->children,
-						    &spart->children_count,
-						    spart_base, pos, size);
-		}
+		if (part->children != NULL)
+			message_part_serialize(part, dest);
 		part = part->next;
 	}
-}
-
-const void *message_part_serialize(MessagePart *part, size_t *size)
-{
-        SerializedMessagePart *spart_base;
-	size_t pos, buf_size;
-
-	buf_size = 32;
-	spart_base = t_buffer_get(sizeof(SerializedMessagePart) * buf_size);
-
-	pos = 0;
-	message_part_serialize_part(part, NULL, &spart_base, &pos, &buf_size);
-
-	*size = sizeof(SerializedMessagePart) * pos;
-	t_buffer_alloc(*size);
-	return spart_base;
 }
 
 static MessagePart *

Index: message-part-serialize.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-part-serialize.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- message-part-serialize.h	9 Oct 2002 17:49:41 -0000	1.4
+++ message-part-serialize.h	8 Dec 2002 05:23:08 -0000	1.5
@@ -1,9 +1,8 @@
 #ifndef __MESSAGE_PART_SERIALIZE_H
 #define __MESSAGE_PART_SERIALIZE_H
 
-/* Serialize message part, allocating memory from data stack.
-   size is updated to contain the size of returned data. */
-const void *message_part_serialize(MessagePart *part, size_t *size);
+/* Serialize message part. */
+void message_part_serialize(MessagePart *part, Buffer *dest);
 
 /* Generate MessagePart from serialized data. */
 MessagePart *message_part_deserialize(Pool pool, const void *data, size_t size);

Index: quoted-printable.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/quoted-printable.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- quoted-printable.c	13 Nov 2002 11:08:18 -0000	1.1
+++ quoted-printable.c	8 Dec 2002 05:23:08 -0000	1.2
@@ -1,44 +1,46 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
+#include "buffer.h"
 #include "hex-binary.h"
 #include "quoted-printable.h"
 
-size_t quoted_printable_decode(const unsigned char *src, size_t *size,
-			       unsigned char *dest)
+void quoted_printable_decode(const unsigned char *src, size_t src_size,
+			     size_t *src_pos_r, Buffer *dest)
 {
-	const unsigned char *end;
-	unsigned char *dest_start;
 	char hexbuf[3];
+	size_t src_pos, next;
 
 	hexbuf[2] = '\0';
 
-	dest_start = dest;
-	end = src + *size;
-
-	for (; src != end; src++) {
-		if (*src == '_') {
-			*dest++ = ' ';
+	next = 0;
+	for (src_pos = 0; src_pos < src_size; src_pos++) {
+		if (src[src_pos] != '_' && src[src_pos] != '=')
 			continue;
-		}
 
-		if (*src == '=') {
-			if (src+2 >= end)
+		buffer_append(dest, src, src_pos - next);
+
+		if (src[src_pos] == '_') {
+			buffer_append(dest, " ", 1);
+			next = src_pos+1;
+		} else {
+			/* =<hex> */
+			if (src_pos+2 >= src_size)
 				break;
 
-			hexbuf[0] = src[1];
-			hexbuf[1] = src[2];
+			hexbuf[0] = src[src_pos+1];
+			hexbuf[1] = src[src_pos+2];
 
 			if (hex_to_binary(hexbuf, dest) == 1) {
-				dest++;
-				src += 2;
-				continue;
+				src_pos += 2;
+				next = src_pos+1;
+			} else {
+				/* non-hex data */
+				next = src_pos;
 			}
 		}
-
-		*dest++ = *src;
 	}
 
-	*size -= (end-src);
-	return (size_t) (dest - dest_start);
+	if (src_pos_r != NULL)
+		*src_pos_r = src_pos;
 }

Index: quoted-printable.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/quoted-printable.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- quoted-printable.h	13 Nov 2002 11:08:18 -0000	1.1
+++ quoted-printable.h	8 Dec 2002 05:23:08 -0000	1.2
@@ -2,13 +2,12 @@
 #define __QUOTED_PRINTABLE_H
 
 /* Translates quoted printable data into binary. dest must be at least the
-   size of src, and may be same as src. Returns size of the binary data.
-   Decoding errors are ignored.
+   size of src, and may be same as src. Decoding errors are ignored.
 
-   This function may be called multiple times for parsing same stream.
-   The *size is updated at return to contain the amount of data actually
-   parsed - the rest of the data should be passed again to this function. */
-size_t quoted_printable_decode(const unsigned char *src, size_t *size,
-			       unsigned char *dest);
+   This function may be called multiple times for parsing the same stream.
+   If src_pos is non-NULL, it's updated to first non-translated character in
+   src. */
+void quoted_printable_decode(const unsigned char *src, size_t src_size,
+			     size_t *src_pos_r, Buffer *dest);
 
 #endif




More information about the dovecot-cvs mailing list