From ea03e17621b0e35cf15cbe11cd85ed218bdbff02 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 23 Jun 2017 11:00:37 +0300 Subject: [PATCH] lib-mail: message_header_hash_more() - add v3 that strips spaces This helps with Zimbra, which strips away trailing whitespaces in BODY[HEADER]. --- src/lib-mail/message-header-hash.c | 21 ++++++++++++++++++--- src/lib-mail/message-header-hash.h | 2 ++ src/lib-mail/test-message-header-hash.c | 12 ++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/lib-mail/message-header-hash.c b/src/lib-mail/message-header-hash.c index 80dfea4746..d4265d5ba9 100644 --- a/src/lib-mail/message-header-hash.c +++ b/src/lib-mail/message-header-hash.c @@ -11,7 +11,7 @@ void message_header_hash_more(struct message_header_hash_context *ctx, { size_t i, start; - i_assert(version == 1 || version == 2); + i_assert(version >= 1 && version <= MESSAGE_HEADER_HASH_MAX_VERSION); if (version == 1) { method->loop(context, data, size); @@ -28,24 +28,39 @@ void message_header_hash_more(struct message_header_hash_context *ctx, So we'll just replace all control and 8bit chars with '?' and remove any repeated '?', which hopefully will satisfy everybody. + + Also: + - Zimbra removes trailing spaces from IMAP BODY[HEADER], but not + IMAP BODY[] or POP3 TOP. Just strip away all spaces with version 3. + */ for (i = start = 0; i < size; i++) { + bool cur_is_questionmark = FALSE; + switch (data[i]) { + case ' ': + if (version == 3) { + /* strip away spaces */ + method->loop(context, data + start, i-start); + start = i+1; + } + break; case '\t': case '\n': break; default: if (data[i] < 0x20 || data[i] >= 0x7f || data[i] == '?') { /* remove repeated '?' */ - if (start < i || (i == 0 && !ctx->prev_was_questionmark)) { + if (start < i || !ctx->prev_was_questionmark) { method->loop(context, data + start, i-start); method->loop(context, "?", 1); } start = i+1; + cur_is_questionmark = TRUE; } break; } + ctx->prev_was_questionmark = cur_is_questionmark; } - ctx->prev_was_questionmark = start == i; method->loop(context, data + start, i-start); } diff --git a/src/lib-mail/message-header-hash.h b/src/lib-mail/message-header-hash.h index cfedd83fda..4183ed2f9e 100644 --- a/src/lib-mail/message-header-hash.h +++ b/src/lib-mail/message-header-hash.h @@ -1,6 +1,8 @@ #ifndef MESSAGE_HEADER_HASH_H #define MESSAGE_HEADER_HASH_H +#define MESSAGE_HEADER_HASH_MAX_VERSION 3 + struct hash_method; struct message_header_hash_context { diff --git a/src/lib-mail/test-message-header-hash.c b/src/lib-mail/test-message-header-hash.c index 684f2c8fea..e895362ce0 100644 --- a/src/lib-mail/test-message-header-hash.c +++ b/src/lib-mail/test-message-header-hash.c @@ -25,6 +25,18 @@ static const struct { { "\x01?hi??\x01", 2, "?hi?" }, { "?\t?hi?\t?", 2, "?\t?hi?\t?" }, { "\n\nhi\n\n", 2, "\n\nhi\n\n" }, + { "", 2, "" }, + { " ", 2, " " }, + { " ", 2, " " }, + { "? ? ? hi \x01\x02 \x03 ", 2, "? ? ? hi ? ? " }, + + { test_input_with_nuls, 3, "?\t\n?!?x?yz?-plop?" }, + { "\n\nhi\n\n", 2, "\n\nhi\n\n" }, + { "", 3, "" }, + { " ", 3, "" }, + { " ", 3, "" }, + { " ? ", 3, "?" }, + { "? ? ? hi \x01\x02 \x03 ", 3, "???hi??" }, }; static void test_message_header_hash_more(void)