diff --git a/src/doveadm/dsync/dsync-mail.c b/src/doveadm/dsync/dsync-mail.c index 7e93684c05..9d52d99df7 100644 --- a/src/doveadm/dsync/dsync-mail.c +++ b/src/doveadm/dsync/dsync-mail.c @@ -30,6 +30,7 @@ int dsync_mail_get_hdr_hash(struct mail *mail, unsigned int version, { struct istream *hdr_input, *input; struct mailbox_header_lookup_ctx *hdr_ctx; + struct message_header_hash_context hash_ctx; struct md5_context md5_ctx; unsigned char md5_result[MD5_RESULTLEN]; const unsigned char *data; @@ -45,13 +46,14 @@ int dsync_mail_get_hdr_hash(struct mail *mail, unsigned int version, input = i_stream_create_lf(hdr_input); md5_init(&md5_ctx); + memset(&hash_ctx, 0, sizeof(hash_ctx)); while (!i_stream_is_eof(input)) { if (i_stream_read_data(input, &data, &size, 0) == -1) break; if (size == 0) break; - message_header_hash_more(&hash_method_md5, &md5_ctx, version, - data, size); + message_header_hash_more(&hash_ctx, &hash_method_md5, &md5_ctx, + version, data, size); i_stream_skip(input, size); } if (input->stream_errno != 0) diff --git a/src/lib-mail/message-header-hash.c b/src/lib-mail/message-header-hash.c index c1f6d21426..62db3fa388 100644 --- a/src/lib-mail/message-header-hash.c +++ b/src/lib-mail/message-header-hash.c @@ -4,7 +4,8 @@ #include "hash-method.h" #include "message-header-hash.h" -void message_header_hash_more(const struct hash_method *method, void *context, +void message_header_hash_more(struct message_header_hash_context *ctx, + const struct hash_method *method, void *context, unsigned int version, const unsigned char *data, size_t size) { @@ -32,12 +33,13 @@ void message_header_hash_more(const struct hash_method *method, void *context, if ((data[i] < 0x20 || data[i] >= 0x7f || data[i] == '?') && (data[i] != '\t' && data[i] != '\n')) { /* remove repeated '?' */ - if (start < i || i == 0) { + if (start < i || (i == 0 && !ctx->prev_was_questionmark)) { method->loop(context, data + start, i-start); method->loop(context, "?", 1); } start = i+1; } } + 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 be6d449972..cfedd83fda 100644 --- a/src/lib-mail/message-header-hash.h +++ b/src/lib-mail/message-header-hash.h @@ -3,7 +3,13 @@ struct hash_method; -void message_header_hash_more(const struct hash_method *method, void *context, +struct message_header_hash_context { + bool prev_was_questionmark; +}; + +/* Initialize ctx with zeros. */ +void message_header_hash_more(struct message_header_hash_context *ctx, + const struct hash_method *method, void *context, unsigned int version, const unsigned char *data, size_t size); diff --git a/src/lib-mail/test-message-header-hash.c b/src/lib-mail/test-message-header-hash.c index 5a32328ccb..39fbfe99bd 100644 --- a/src/lib-mail/test-message-header-hash.c +++ b/src/lib-mail/test-message-header-hash.c @@ -14,12 +14,14 @@ static const unsigned char test_output[] = static void test_dsync_mail_hash_more(void) { + struct message_header_hash_context ctx; struct md5_context md5_ctx; unsigned char md5_input[MD5_RESULTLEN], md5_output[MD5_RESULTLEN]; test_begin("dsync_mail_hash_more v2"); md5_init(&md5_ctx); - message_header_hash_more(&hash_method_md5, &md5_ctx, 2, + memset(&ctx, 0, sizeof(ctx)); + message_header_hash_more(&ctx, &hash_method_md5, &md5_ctx, 2, test_input, sizeof(test_input)-1); md5_final(&md5_ctx, md5_input); @@ -28,6 +30,17 @@ static void test_dsync_mail_hash_more(void) md5_final(&md5_ctx, md5_output); test_assert(memcmp(md5_input, md5_output, MD5_RESULTLEN) == 0); + + /* single byte at a time */ + md5_init(&md5_ctx); + memset(&ctx, 0, sizeof(ctx)); + for (unsigned int i = 0; i < sizeof(test_input)-1; i++) { + message_header_hash_more(&ctx, &hash_method_md5, &md5_ctx, 2, + test_input + i, 1); + } + md5_final(&md5_ctx, md5_input); + test_assert(memcmp(md5_input, md5_output, MD5_RESULTLEN) == 0); + test_end(); } diff --git a/src/plugins/pop3-migration/pop3-migration-plugin.c b/src/plugins/pop3-migration/pop3-migration-plugin.c index 05138bf318..8b773ba57d 100644 --- a/src/plugins/pop3-migration/pop3-migration-plugin.c +++ b/src/plugins/pop3-migration/pop3-migration-plugin.c @@ -181,6 +181,7 @@ int pop3_migration_get_hdr_sha1(uint32_t mail_seq, struct istream *input, { const unsigned char *data; size_t size; + struct message_header_hash_context hash_ctx; struct sha1_ctxt sha1_ctx; struct pop3_hdr_context hdr_ctx; @@ -194,7 +195,7 @@ int pop3_migration_get_hdr_sha1(uint32_t mail_seq, struct istream *input, sha1_init(&sha1_ctx); while (i_stream_read_data(input, &data, &size, 0) > 0) { - message_header_hash_more(&hash_method_sha1, &sha1_ctx, 2, + message_header_hash_more(&hash_ctx, &hash_method_sha1, &sha1_ctx, 2, data, size); i_stream_skip(input, size); }