From: Timo Sirainen Date: Wed, 4 Jun 2003 15:57:58 +0000 (+0300) Subject: IMAP protocol doesn't allow server to send NULs to client. Send ascii #128 X-Git-Tag: 1.1.alpha1~4572 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e0054c2e5efc526df6287da368335680a856714;p=thirdparty%2Fdovecot%2Fcore.git IMAP protocol doesn't allow server to send NULs to client. Send ascii #128 instead. --HG-- branch : HEAD --- diff --git a/src/imap/imap-fetch-body-section.c b/src/imap/imap-fetch-body-section.c index ba49ec2aa6..b4be84e928 100644 --- a/src/imap/imap-fetch-body-section.c +++ b/src/imap/imap-fetch-body-section.c @@ -27,6 +27,8 @@ struct fetch_header_field_context { uoff_t skip, max_size; const char *const *fields; int (*match_func) (const char *const *, const char *, size_t); + + unsigned int fix_nuls:1; }; struct partial_cache { @@ -103,7 +105,8 @@ static int fetch_body(struct imap_fetch_context *ctx, body->skip); ret = message_send(ctx->output, stream, &body_size, - skip_cr, body->max_size, &last_cr); + skip_cr, body->max_size, &last_cr, + !mail->has_no_nuls); if (ret > 0) { partial.cr_skipped = last_cr != 0; partial.pos.physical_size = @@ -189,6 +192,7 @@ static int fetch_header_append(struct fetch_header_field_context *ctx, const void *data, size_t size) { const unsigned char *str = data; + size_t i; if (ctx->skip > 0) { if (ctx->skip >= size) { @@ -206,14 +210,38 @@ static int fetch_header_append(struct fetch_header_field_context *ctx, size = ctx->max_size - ctx->dest_size; } - if (ctx->dest != NULL) - buffer_append(ctx->dest, str, size); ctx->dest_size += size; + if (ctx->fix_nuls && (ctx->dest != NULL || ctx->output != NULL)) { + for (i = 0; i < size; ) { + if (str[i] != 0) { + i++; + continue; + } + + /* NUL found, change it to #128 */ + if (ctx->dest != NULL) { + buffer_append(ctx->dest, str, i); + buffer_append(ctx->dest, "\x80", 1); + } else { + if (o_stream_send(ctx->output, str, i) < 0 || + o_stream_send(ctx->output, "\x80", 1) < 0) + return FALSE; + } + + str += i+1; + size -= i+1; + i = 0; + } + } + + if (ctx->dest != NULL) + buffer_append(ctx->dest, str, size); if (ctx->output != NULL) { if (o_stream_send(ctx->output, str, size) < 0) return FALSE; } + return ctx->dest_size < ctx->max_size; } @@ -272,7 +300,7 @@ static int fetch_header_fields(struct istream *input, const char *section, /* fetch wanted headers from given data */ static int fetch_header_from(struct imap_fetch_context *ctx, struct istream *input, - const struct message_size *size, + const struct message_size *size, struct mail *mail, const struct imap_fetch_body_data *body, const char *header_section) { @@ -292,7 +320,8 @@ static int fetch_header_from(struct imap_fetch_context *ctx, if (o_stream_send_str(ctx->output, str) < 0) return FALSE; return message_send(ctx->output, input, size, - body->skip, body->max_size, NULL) >= 0; + body->skip, body->max_size, NULL, + !mail->has_no_nuls) >= 0; } /* partial headers - copy the wanted fields into memory, inserting @@ -302,6 +331,7 @@ static int fetch_header_from(struct imap_fetch_context *ctx, memset(&hdr_ctx, 0, sizeof(hdr_ctx)); hdr_ctx.skip = body->skip; hdr_ctx.max_size = body->max_size; + hdr_ctx.fix_nuls = !mail->has_no_nuls; failed = FALSE; start_offset = input->v_offset; @@ -366,7 +396,8 @@ static int fetch_header(struct imap_fetch_context *ctx, struct mail *mail, if (stream == NULL) return FALSE; - return fetch_header_from(ctx, stream, &hdr_size, body, body->section); + return fetch_header_from(ctx, stream, &hdr_size, + mail, body, body->section); } /* Find message_part for section (eg. 1.3.4) */ @@ -443,7 +474,8 @@ static int fetch_part_body(struct imap_fetch_context *ctx, &partial, stream, part->physical_pos + part->header_size.physical_size, body->skip); ret = message_send(ctx->output, stream, &part->body_size, - skip_cr, body->max_size, &last_cr); + skip_cr, body->max_size, &last_cr, + !mail->has_no_nuls); if (ret > 0) { partial.cr_skipped = last_cr != 0; partial.pos.physical_size = @@ -475,7 +507,7 @@ static int fetch_part(struct imap_fetch_context *ctx, struct mail *mail, strcmp(section, "MIME") == 0) { i_stream_seek(stream, part->physical_pos); return fetch_header_from(ctx, stream, &part->header_size, - body, section); + mail, body, section); } i_warning("BUG: Accepted invalid section from user: '%s'", diff --git a/src/imap/imap-fetch.c b/src/imap/imap-fetch.c index 66e61a656f..b7c0140538 100644 --- a/src/imap/imap-fetch.c +++ b/src/imap/imap-fetch.c @@ -113,7 +113,7 @@ static int fetch_send_rfc822(struct imap_fetch_context *ctx, struct mail *mail) return FALSE; return message_send(ctx->output, stream, &body_size, - 0, (uoff_t)-1, NULL) >= 0; + 0, (uoff_t)-1, NULL, !mail->has_no_nuls) >= 0; } static int fetch_send_rfc822_header(struct imap_fetch_context *ctx, @@ -136,7 +136,7 @@ static int fetch_send_rfc822_header(struct imap_fetch_context *ctx, return FALSE; return message_send(ctx->output, stream, &hdr_size, - 0, (uoff_t)-1, NULL) >= 0; + 0, (uoff_t)-1, NULL, !mail->has_no_nuls) >= 0; } static int fetch_send_rfc822_text(struct imap_fetch_context *ctx, @@ -160,7 +160,7 @@ static int fetch_send_rfc822_text(struct imap_fetch_context *ctx, i_stream_seek(stream, hdr_size.physical_size); return message_send(ctx->output, stream, &body_size, - 0, (uoff_t)-1, NULL) >= 0; + 0, (uoff_t)-1, NULL, !mail->has_no_nuls) >= 0; } static int fetch_mail(struct imap_fetch_context *ctx, struct mail *mail) diff --git a/src/lib-index/mail-index-update.c b/src/lib-index/mail-index-update.c index 0f493c6695..db680a5c8d 100644 --- a/src/lib-index/mail-index-update.c +++ b/src/lib-index/mail-index-update.c @@ -459,6 +459,13 @@ void mail_index_update_headers(struct mail_index_update *update, if (part == NULL) { part = message_parse(pool, input, update_header_cb, &ctx); + if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) { + update->rec->index_flags |= + INDEX_MAIL_FLAG_HAS_NULS; + } else { + update->rec->index_flags |= + INDEX_MAIL_FLAG_HAS_NO_NULS; + } } else { /* cached, construct the bodystructure using it. also we need to parse the header.. */ diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index 0915c228f6..36b5abf40e 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -75,7 +75,12 @@ enum mail_index_mail_flag { INDEX_MAIL_FLAG_DIRTY = 0x0004, /* Maildir: Mail file is in new/ dir instead of cur/ */ - INDEX_MAIL_FLAG_MAILDIR_NEW = 0x0008 + INDEX_MAIL_FLAG_MAILDIR_NEW = 0x0008, + + /* Mail header or body is known to contain NUL characters. */ + INDEX_MAIL_FLAG_HAS_NULS = 0x0010, + /* Mail header or body is known to not contain NUL characters. */ + INDEX_MAIL_FLAG_HAS_NO_NULS = 0x0020 }; enum mail_lock_type { diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c index d1f7f51dff..90e5bb0b8c 100644 --- a/src/lib-mail/message-parser.c +++ b/src/lib-mail/message-parser.c @@ -38,6 +38,8 @@ struct message_header_parser_ctx { string_t *name; buffer_t *value_buf; size_t skip; + + int has_nuls; }; static struct message_part * @@ -46,12 +48,12 @@ message_parse_part(struct istream *input, static struct message_part * message_parse_body(struct istream *input, struct message_boundary *boundaries, - struct message_size *body_size); + struct message_size *body_size, int *has_nuls); static struct message_part * message_skip_boundary(struct istream *input, struct message_boundary *boundaries, - struct message_size *boundary_size); + struct message_size *boundary_size, int *has_nuls); static void message_size_add_part(struct message_size *dest, struct message_part *part) @@ -138,6 +140,7 @@ message_parse_multipart(struct istream *input, { struct message_part *parent_part, *next_part, *part; struct message_boundary *b; + int has_nuls; /* multipart message. add new boundary */ b = t_new(struct message_boundary, 1); @@ -155,7 +158,9 @@ message_parse_multipart(struct istream *input, /* skip the data before the first boundary */ parent_part = parser_ctx->part; next_part = message_skip_boundary(input, parser_ctx->boundaries, - &parent_part->body_size); + &parent_part->body_size, &has_nuls); + if (has_nuls) + parent_part->flags |= MESSAGE_PART_FLAG_HAS_NULS; /* now, parse the parts */ while (next_part == parent_part) { @@ -165,6 +170,11 @@ message_parse_multipart(struct istream *input, parser_ctx->part = part; next_part = message_parse_part(input, parser_ctx); + if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) { + /* it also belongs to parent */ + parent_part->flags |= MESSAGE_PART_FLAG_HAS_NULS; + } + /* update our size */ message_size_add_part(&parent_part->body_size, part); @@ -173,7 +183,10 @@ message_parse_multipart(struct istream *input, /* skip the boundary */ next_part = message_skip_boundary(input, parser_ctx->boundaries, - &parent_part->body_size); + &parent_part->body_size, + &has_nuls); + if (has_nuls) + parent_part->flags |= MESSAGE_PART_FLAG_HAS_NULS; } /* remove boundary */ @@ -192,6 +205,7 @@ message_parse_part(struct istream *input, struct parser_context *parser_ctx) struct message_header_line *hdr; struct message_part *next_part, *part; uoff_t hdr_size; + int has_nuls; hdr_ctx = message_parse_header_init(input, &parser_ctx->part->header_size); @@ -219,6 +233,8 @@ message_parse_part(struct istream *input, struct parser_context *parser_ctx) parser_ctx->callback(parser_ctx->part, NULL, parser_ctx->context); } + if (hdr_ctx->has_nuls) + parser_ctx->part->flags |= MESSAGE_PART_FLAG_HAS_NULS; message_parse_header_deinit(hdr_ctx); i_assert((parser_ctx->part->flags & MUTEX_FLAGS) != MUTEX_FLAGS); @@ -263,23 +279,35 @@ message_parse_part(struct istream *input, struct parser_context *parser_ctx) /* normal message, read until the next boundary */ part = parser_ctx->part; next_part = message_parse_body(input, parser_ctx->boundaries, - &part->body_size); + &part->body_size, &has_nuls); + if (has_nuls) + part->flags |= MESSAGE_PART_FLAG_HAS_NULS; + } + + if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0 && + part->parent != NULL) { + /* it also belongs to parent */ + part->parent->flags |= MESSAGE_PART_FLAG_HAS_NULS; } return next_part; } static void message_skip_line(struct istream *input, - struct message_size *msg_size, int skip_lf) + struct message_size *msg_size, int skip_lf, + int *has_nuls) { const unsigned char *msg; size_t i, size, startpos; startpos = 0; + *has_nuls = FALSE; while (i_stream_read_data(input, &msg, &size, startpos) > 0) { for (i = startpos; i < size; i++) { - if (msg[i] == '\n') { + if (msg[i] == '\0') + *has_nuls = TRUE; + else if (msg[i] == '\n') { if (!skip_lf) { if (i > 0 && msg[i-1] == '\r') i--; @@ -336,7 +364,8 @@ boundary_find(struct message_boundary *boundaries, static struct message_boundary * message_find_boundary(struct istream *input, struct message_boundary *boundaries, - struct message_size *msg_size, int skip_over) + struct message_size *msg_size, int skip_over, + int *has_nuls) { struct message_boundary *boundary; const unsigned char *msg; @@ -344,11 +373,15 @@ message_find_boundary(struct istream *input, boundary = NULL; missing_cr_count = startpos = line_start = 0; + *has_nuls = FALSE; while (i_stream_read_data(input, &msg, &size, startpos) > 0) { for (i = startpos; i < size; i++) { - if (msg[i] != '\n') + if (msg[i] != '\n') { + if (msg[i] == '\0') + *has_nuls = TRUE; continue; + } if (line_start != (size_t)-1 && i >= line_start+2 && msg[line_start] == '-' && @@ -447,20 +480,22 @@ message_find_boundary(struct istream *input, static struct message_part * message_parse_body(struct istream *input, struct message_boundary *boundaries, - struct message_size *msg_size) + struct message_size *msg_size, int *has_nuls) { struct message_boundary *boundary; struct message_size body_size; if (boundaries == NULL) { - message_get_body_size(input, &body_size, (uoff_t)-1, NULL); + message_get_body_size(input, &body_size, + (uoff_t)-1, NULL, has_nuls); message_size_add(msg_size, &body_size); - return NULL; + boundary = NULL; } else { boundary = message_find_boundary(input, boundaries, - msg_size, FALSE); - return boundary == NULL ? NULL : boundary->part; + msg_size, FALSE, has_nuls); } + + return boundary == NULL ? NULL : boundary->part; } /* skip data until next boundary is found. if it's end boundary, @@ -468,7 +503,7 @@ message_parse_body(struct istream *input, struct message_boundary *boundaries, static struct message_part * message_skip_boundary(struct istream *input, struct message_boundary *boundaries, - struct message_size *boundary_size) + struct message_size *boundary_size, int *has_nuls) { struct message_boundary *boundary; const unsigned char *msg; @@ -476,7 +511,7 @@ message_skip_boundary(struct istream *input, int end_boundary; boundary = message_find_boundary(input, boundaries, - boundary_size, TRUE); + boundary_size, TRUE, has_nuls); if (boundary == NULL) return NULL; @@ -486,11 +521,12 @@ message_skip_boundary(struct istream *input, end_boundary = msg[0] == '-' && msg[1] == '-'; /* skip the rest of the line */ - message_skip_line(input, boundary_size, !end_boundary); + message_skip_line(input, boundary_size, !end_boundary, has_nuls); if (end_boundary) { /* skip the footer */ - return message_parse_body(input, boundary->next, boundary_size); + return message_parse_body(input, boundary->next, + boundary_size, has_nuls); } return boundary == NULL ? NULL : boundary->part; @@ -615,7 +651,7 @@ message_parse_header_next(struct message_header_parser_ctx *ctx) if (colon_pos == UINT_MAX) { /* header name is huge. just skip it. */ message_skip_line(ctx->input, ctx->hdr_size, - TRUE); + TRUE, &ctx->has_nuls); continue; } @@ -645,14 +681,21 @@ message_parse_header_next(struct message_header_parser_ctx *ctx) /* end of headers, or error */ break; } + + if (msg[i] == '\0') + ctx->has_nuls = TRUE; } } } /* find '\n' */ for (i = startpos; i < parse_size; i++) { - if (msg[i] == '\n') - break; + if (msg[i] <= '\n') { + if (msg[i] == '\n') + break; + if (msg[i] == '\0') + ctx->has_nuls = TRUE; + } } if (i < parse_size) { diff --git a/src/lib-mail/message-parser.h b/src/lib-mail/message-parser.h index d68e0fc745..3ccfa9becb 100644 --- a/src/lib-mail/message-parser.h +++ b/src/lib-mail/message-parser.h @@ -15,7 +15,10 @@ enum message_part_flags { MESSAGE_PART_FLAG_TEXT = 0x08, /* content-transfer-encoding: binary */ - MESSAGE_PART_FLAG_BINARY = 0x10 + MESSAGE_PART_FLAG_BINARY = 0x10, + + /* message part header or body contains NULs */ + MESSAGE_PART_FLAG_HAS_NULS = 0x20 }; struct message_part { diff --git a/src/lib-mail/message-send.c b/src/lib-mail/message-send.c index 2723ed1e9d..95cfec2d0c 100644 --- a/src/lib-mail/message-send.c +++ b/src/lib-mail/message-send.c @@ -9,13 +9,14 @@ off_t message_send(struct ostream *output, struct istream *input, const struct message_size *msg_size, - uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr) + uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr, + int fix_nuls) { const unsigned char *msg; uoff_t old_limit, limit; size_t i, size; off_t ret; - int cr_skipped, add_cr; + int cr_skipped, add; if (last_cr != NULL) *last_cr = -1; @@ -27,7 +28,7 @@ off_t message_send(struct ostream *output, struct istream *input, if (max_virtual_size > msg_size->virtual_size - virtual_skip) max_virtual_size = msg_size->virtual_size - virtual_skip; - if (msg_size->physical_size == msg_size->virtual_size) { + if (msg_size->physical_size == msg_size->virtual_size && !fix_nuls) { /* no need to kludge with CRs, we can use sendfile() */ i_stream_skip(input, virtual_skip); @@ -46,7 +47,7 @@ off_t message_send(struct ostream *output, struct istream *input, ret = 0; while (max_virtual_size > 0 && i_stream_read_data(input, &msg, &size, 0) > 0) { - add_cr = FALSE; + add = '\0'; for (i = 0; i < size && max_virtual_size > 0; i++) { max_virtual_size--; @@ -54,9 +55,12 @@ off_t message_send(struct ostream *output, struct istream *input, if ((i == 0 && !cr_skipped) || (i > 0 && msg[i-1] != '\r')) { /* missing CR */ - add_cr = TRUE; + add = '\r'; break; } + } else if (msg[i] == '\0') { + add = 128; + break; } } @@ -64,11 +68,12 @@ off_t message_send(struct ostream *output, struct istream *input, if (o_stream_send(output, msg, i) < 0) return -1; - if (add_cr) { + if (add != '\0') { ret++; - if (o_stream_send(output, "\r", 1) < 0) + if (o_stream_send(output, &add, 1) < 0) return -1; - cr_skipped = TRUE; + cr_skipped = add == '\r'; + if (add == 128) i++; } else { cr_skipped = i > 0 && msg[i-1] == '\r'; } diff --git a/src/lib-mail/message-send.h b/src/lib-mail/message-send.h index 1aec82bb18..dc17f38a85 100644 --- a/src/lib-mail/message-send.h +++ b/src/lib-mail/message-send.h @@ -10,7 +10,8 @@ struct message_size; known. Returns number of bytes sent, or -1 if error. */ off_t message_send(struct ostream *output, struct istream *input, const struct message_size *msg_size, - uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr); + uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr, + int fix_nuls); /* Skip number of virtual bytes from putfer. msg_size is updated if it's not NULL. If cr_skipped is TRUE and first character is \n, it's not treated as diff --git a/src/lib-mail/message-size.c b/src/lib-mail/message-size.c index 09229933c7..00c2766f74 100644 --- a/src/lib-mail/message-size.c +++ b/src/lib-mail/message-size.c @@ -5,18 +5,24 @@ #include "message-parser.h" #include "message-size.h" -void message_get_header_size(struct istream *input, struct message_size *hdr) +void message_get_header_size(struct istream *input, struct message_size *hdr, + int *has_nuls) { const unsigned char *msg; size_t i, size, startpos, missing_cr_count; memset(hdr, 0, sizeof(struct message_size)); + if (has_nuls != NULL) + *has_nuls = FALSE; missing_cr_count = 0; startpos = 0; while (i_stream_read_data(input, &msg, &size, startpos) > 0) { for (i = startpos; i < size; i++) { - if (msg[i] != '\n') + if (msg[i] != '\n') { + if (msg[i] == '\0' && has_nuls != NULL) + *has_nuls = TRUE; continue; + } hdr->lines++; if (i == 0 || msg[i-1] != '\r') { @@ -56,13 +62,15 @@ void message_get_header_size(struct istream *input, struct message_size *hdr) } void message_get_body_size(struct istream *input, struct message_size *body, - uoff_t max_virtual_size, int *last_cr) + uoff_t max_virtual_size, int *last_cr, int *has_nuls) { const unsigned char *msg; size_t i, size, startpos, missing_cr_count; int cr; memset(body, 0, sizeof(struct message_size)); + if (has_nuls != NULL) + *has_nuls = FALSE; cr = 0; missing_cr_count = 0; startpos = 0; @@ -72,7 +80,10 @@ void message_get_body_size(struct istream *input, struct message_size *body, for (i = startpos; i < size && max_virtual_size > 0; i++) { max_virtual_size--; - if (msg[i] == '\n') { + if (msg[i] == '\0') { + if (has_nuls != NULL) + *has_nuls = TRUE; + } else if (msg[i] == '\n') { if (i == 0 || msg[i-1] != '\r') { /* missing CR */ missing_cr_count++; diff --git a/src/lib-mail/message-size.h b/src/lib-mail/message-size.h index 0c180fb3e3..8b559a65ec 100644 --- a/src/lib-mail/message-size.h +++ b/src/lib-mail/message-size.h @@ -9,12 +9,14 @@ struct message_size { /* Calculate size of message header. Leave the input point to first character in body. */ -void message_get_header_size(struct istream *input, struct message_size *hdr); +void message_get_header_size(struct istream *input, struct message_size *hdr, + int *has_nuls); /* Calculate size of message body. Read only max_virtual_size virtual bytes, if you want it unlimited, use (uoff_t)-1. If last_cr is not NULL, it's set to 1 if last character is CR, 2 if it's virtual CR. */ void message_get_body_size(struct istream *input, struct message_size *body, - uoff_t max_virtual_size, int *last_cr); + uoff_t max_virtual_size, int *last_cr, + int *has_nuls); /* Sum contents of src into dest. */ void message_size_add(struct message_size *dest, diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index b23a00e905..3b56fd5908 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -40,6 +40,15 @@ static struct message_part *get_cached_parts(struct index_mail *mail) return NULL; } + /* we know the NULs now, update them */ + if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) { + mail->mail.has_nuls = TRUE; + mail->mail.has_no_nuls = FALSE; + } else { + mail->mail.has_nuls = FALSE; + mail->mail.has_no_nuls = TRUE; + } + return part; } @@ -261,6 +270,16 @@ static const struct message_part *get_parts(struct mail *_mail) index_mail_init_parse_header(mail); data->parts = message_parse(mail->pool, data->stream, index_mail_parse_header, mail); + + /* we know the NULs now, update them */ + if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) { + _mail->has_nuls = TRUE; + _mail->has_no_nuls = FALSE; + } else { + _mail->has_nuls = FALSE; + _mail->has_no_nuls = TRUE; + } + return data->parts; } @@ -411,13 +430,13 @@ static uoff_t get_size(struct mail *_mail) return (uoff_t)-1; if (hdr_phys_size == (uoff_t)-1) { - message_get_header_size(data->stream, &data->hdr_size); + message_get_header_size(data->stream, &data->hdr_size, NULL); hdr_size = data->hdr_size.virtual_size; data->hdr_size_set = TRUE; } if (body_size == (uoff_t)-1) { message_get_body_size(data->stream, &data->body_size, - (uoff_t)-1, NULL); + (uoff_t)-1, NULL, NULL); body_size = data->body_size.virtual_size; data->body_size_set = TRUE; } @@ -534,7 +553,8 @@ static struct istream *get_stream(struct mail *_mail, if (hdr_size != NULL) { if (!data->hdr_size_set) { - message_get_header_size(data->stream, &data->hdr_size); + message_get_header_size(data->stream, &data->hdr_size, + NULL); data->hdr_size_set = TRUE; } @@ -547,7 +567,7 @@ static struct istream *get_stream(struct mail *_mail, data->hdr_size.physical_size); message_get_body_size(data->stream, &data->body_size, - (uoff_t)-1, NULL); + (uoff_t)-1, NULL, NULL); data->body_size_set = TRUE; } @@ -618,7 +638,7 @@ static const char *get_special(struct mail *_mail, enum mail_fetch_field field) } static struct mail index_mail = { - 0, 0, 0, + 0, 0, 0, 0, 0, get_flags, get_parts, @@ -658,6 +678,11 @@ int index_mail_next(struct index_mail *mail, struct mail_index_record *rec) memset(data, 0, sizeof(*data)); p_clear(mail->pool); + mail->mail.has_nuls = + (rec->index_flags & INDEX_MAIL_FLAG_HAS_NULS) != 0; + mail->mail.has_no_nuls = + (rec->index_flags & INDEX_MAIL_FLAG_HAS_NO_NULS) != 0; + data->rec = rec; data->size = (uoff_t)-1; data->received_date = data->sent_time = (time_t)-1; diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h index b816d53987..9c5382ba13 100644 --- a/src/lib-storage/mail-storage.h +++ b/src/lib-storage/mail-storage.h @@ -337,6 +337,8 @@ struct mail { unsigned int uid; unsigned int seen_updated:1; /* if update_seen was TRUE */ + unsigned int has_nuls:1; /* message data is known to contain NULs */ + unsigned int has_no_nuls:1; /* -''- known to not contain NULs */ const struct mail_full_flags *(*get_flags)(struct mail *mail); const struct message_part *(*get_parts)(struct mail *mail);