dovecot-2.2: lib-mail: Added message_header_encode_data() to sup...

dovecot at dovecot.org dovecot at dovecot.org
Mon May 5 12:40:29 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/cc622a9a2f3c
changeset: 17319:cc622a9a2f3c
user:      Timo Sirainen <tss at iki.fi>
date:      Mon May 05 15:39:58 2014 +0300
description:
lib-mail: Added message_header_encode_data() to support encoding also NUL characters.

diffstat:

 src/lib-mail/Makefile.am                  |   2 +-
 src/lib-mail/message-header-encode.c      |  32 +++++++++++++++++-----------
 src/lib-mail/message-header-encode.h      |   2 +
 src/lib-mail/test-message-header-decode.c |  34 +++++++++++++++++++++++++++++++
 src/lib-mail/test-message-header-encode.c |  16 ++++++++++++++
 5 files changed, 72 insertions(+), 14 deletions(-)

diffs (206 lines):

diff -r 841d31e6c647 -r cc622a9a2f3c src/lib-mail/Makefile.am
--- a/src/lib-mail/Makefile.am	Mon May 05 15:05:20 2014 +0300
+++ b/src/lib-mail/Makefile.am	Mon May 05 15:39:58 2014 +0300
@@ -134,7 +134,7 @@
 test_message_decoder_DEPENDENCIES = $(test_deps)
 
 test_message_header_decode_SOURCES = test-message-header-decode.c
-test_message_header_decode_LDADD = message-header-decode.lo quoted-printable.lo $(test_libs)
+test_message_header_decode_LDADD = message-header-decode.lo quoted-printable.lo message-header-encode.lo $(test_libs)
 test_message_header_decode_DEPENDENCIES = $(test_deps)
 
 test_message_header_encode_SOURCES = test-message-header-encode.c
diff -r 841d31e6c647 -r cc622a9a2f3c src/lib-mail/message-header-encode.c
--- a/src/lib-mail/message-header-encode.c	Mon May 05 15:05:20 2014 +0300
+++ b/src/lib-mail/message-header-encode.c	Mon May 05 15:39:58 2014 +0300
@@ -11,7 +11,8 @@
 #define IS_LWSP(c) \
 	((c) == ' ' || (c) == '\t' || (c) == '\n')
 
-static bool input_idx_need_encoding(const unsigned char *input, unsigned int i)
+static bool input_idx_need_encoding(const unsigned char *input,
+				    unsigned int i, unsigned int len)
 {
 	/* 8bit chars */
 	if ((input[i] & 0x80) != 0)
@@ -21,7 +22,7 @@
 		return TRUE;
 
 	/* <LWSP>=? */
-	if (input[i] == '=' && input[i+1] == '?' &&
+	if (input[i] == '=' && i+1 < len && input[i+1] == '?' &&
 	    (i == 0 || IS_LWSP(input[i-1])))
 		return TRUE;
 	return FALSE;
@@ -130,21 +131,26 @@
 	}
 }
 
-void message_header_encode(const char *_input, string_t *output)
+void message_header_encode(const char *input, string_t *output)
 {
-	const unsigned char *input = (const unsigned char *)_input;
+	message_header_encode_data((const void *)input, strlen(input), output);
+}
+
+void message_header_encode_data(const unsigned char *input, unsigned int len,
+				string_t *output)
+{
 	unsigned int i, first_idx, last_idx;
 	unsigned int enc_chars, enc_len, base64_len, q_len;
 	bool use_q;
 
 	/* find the first word that needs encoding */
-	for (i = 0; input[i] != '\0'; i++) {
-		if (input_idx_need_encoding(input, i))
+	for (i = 0; i < len; i++) {
+		if (input_idx_need_encoding(input, i, len))
 			break;
 	}
-	if (input[i] == '\0') {
+	if (i == len) {
 		/* no encoding necessary */
-		str_append(output, _input);
+		str_append_data(output, input, len);
 		return;
 	}
 	first_idx = i;
@@ -153,13 +159,13 @@
 
 	/* find the last word that needs encoding */
 	last_idx = ++i; enc_chars = 1;
-	for (; input[i] != '\0'; i++) {
-		if (input_idx_need_encoding(input, i)) {
+	for (; i < len; i++) {
+		if (input_idx_need_encoding(input, i, len)) {
 			last_idx = i + 1;
 			enc_chars++;
 		}
 	}
-	while (input[last_idx] != '\0' && !IS_LWSP(input[last_idx]))
+	while (last_idx < len && !IS_LWSP(input[last_idx]))
 		last_idx++;
 
 	/* figure out if we should use Q or B encoding. Prefer Q if it's not
@@ -170,10 +176,10 @@
 	use_q = q_len*2/3 <= base64_len;
 
 	/* and do it */
-	str_append_n(output, input, first_idx);
+	str_append_data(output, input, first_idx);
 	if (use_q)
 		message_header_encode_q(input + first_idx, enc_len, output);
 	else
 		message_header_encode_b(input + first_idx, enc_len, output);
-	str_append(output, _input + last_idx);
+	str_append_data(output, input + last_idx, len - last_idx);
 }
diff -r 841d31e6c647 -r cc622a9a2f3c src/lib-mail/message-header-encode.h
--- a/src/lib-mail/message-header-encode.h	Mon May 05 15:05:20 2014 +0300
+++ b/src/lib-mail/message-header-encode.h	Mon May 05 15:39:58 2014 +0300
@@ -3,6 +3,8 @@
 
 /* Encode UTF-8 input into output wherever necessary. */
 void message_header_encode(const char *input, string_t *output);
+void message_header_encode_data(const unsigned char *input, unsigned int len,
+				string_t *output);
 
 /* Encode the whole UTF-8 input using "Q" or "B" encoding into output.
    The output is split into multiple lines if necessary. The first line length
diff -r 841d31e6c647 -r cc622a9a2f3c src/lib-mail/test-message-header-decode.c
--- a/src/lib-mail/test-message-header-decode.c	Mon May 05 15:05:20 2014 +0300
+++ b/src/lib-mail/test-message-header-decode.c	Mon May 05 15:39:58 2014 +0300
@@ -4,9 +4,12 @@
 #include "buffer.h"
 #include "str.h"
 #include "charset-utf8.h"
+#include "message-header-encode.h"
 #include "message-header-decode.h"
 #include "test-common.h"
 
+#include <stdlib.h>
+
 bool charset_is_utf8(const char *charset ATTR_UNUSED) { return TRUE; }
 
 int charset_to_utf8_begin(const char *charset ATTR_UNUSED,
@@ -25,6 +28,7 @@
 static void test_message_header_decode(void)
 {
 	static const char *data[] = {
+		" \t=?utf-8?q?=c3=a4?=  =?utf-8?q?=c3=a4?=  b  \t\r\n ", "ää  b  \t\r\n ",
 		"a =?utf-8?q?=c3=a4?= b", "a ä b",
 		"a =?utf-8?q?=c3=a4?= b", "a ä b",
 		"a =?utf-8?q?=c3=a4?=\t\t\r\n =?utf-8?q?=c3=a4?= b", "a ää b",
@@ -47,10 +51,40 @@
 	test_end();
 }
 
+static void test_message_header_decode_encode_random(void)
+{
+	string_t *encoded, *decoded;
+	unsigned char buf[1024];
+	unsigned int i, j, buflen;
+
+	test_begin("message header encode & decode randomly");
+
+	buf[0] = 'x';
+	encoded = t_str_new(256);
+	decoded = t_str_new(256);
+	for (i = 0; i < 1000; i++) {
+		/* fill only with 7bit data so we don't have to worry about
+		   the data being valid UTF-8 */
+		for (j = 1; j < sizeof(buf); j++)
+			buf[j] = rand() % 128;
+		buflen = rand() % sizeof(buf);
+
+		str_truncate(encoded, 0);
+		str_truncate(decoded, 0);
+		message_header_encode_data(buf, buflen, encoded);
+		message_header_decode_utf8(encoded->data, encoded->used,
+					   decoded, NULL);
+		test_assert(decoded->used == buflen &&
+			    memcmp(decoded->data, buf, buflen) == 0);
+	}
+	test_end();
+}
+
 int main(void)
 {
 	static void (*test_functions[])(void) = {
 		test_message_header_decode,
+		test_message_header_decode_encode_random,
 		NULL
 	};
 	return test_run(test_functions);
diff -r 841d31e6c647 -r cc622a9a2f3c src/lib-mail/test-message-header-encode.c
--- a/src/lib-mail/test-message-header-encode.c	Mon May 05 15:05:20 2014 +0300
+++ b/src/lib-mail/test-message-header-encode.c	Mon May 05 15:39:58 2014 +0300
@@ -183,12 +183,28 @@
 	test_end();
 }
 
+static void test_message_header_encode_data(void)
+{
+	string_t *str = t_str_new(128);
+	static unsigned char nuls[10] = { 0, };
+
+	test_begin("message header encode data");
+	message_header_encode_data(nuls, 1, str);
+	test_assert(strcmp(str_c(str), "=?utf-8?q?=00?=") == 0);
+
+	str_truncate(str, 0);
+	message_header_encode_data(nuls, sizeof(nuls), str);
+	test_assert(strcmp(str_c(str), "=?utf-8?b?AAAAAAAAAAAAAA==?=") == 0);
+	test_end();
+}
+
 int main(void)
 {
 	static void (*test_functions[])(void) = {
 		test_message_header_encode_q,
 		test_message_header_encode_b,
 		test_message_header_encode,
+		test_message_header_encode_data,
 		NULL
 	};
 	return test_run(test_functions);


More information about the dovecot-cvs mailing list