Mercurial > dovecot > core-2.2
changeset 369:d037915978ca HEAD
message_parse_header() now calls the function with empty name/value at end
of headers. we use this feature with mbox to allow usage of Content-Length
header field.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 06 Oct 2002 12:20:20 +0300 |
parents | 44751b4d92e1 |
children | b0a62e264b22 |
files | src/lib-imap/imap-message-cache.c src/lib-index/mail-index-update.c src/lib-index/mbox/mbox-append.c src/lib-index/mbox/mbox-fsck.c src/lib-index/mbox/mbox-index.c src/lib-index/mbox/mbox-index.h src/lib-index/mbox/mbox-rewrite.c src/lib-mail/message-parser.c src/lib-mail/message-parser.h src/lib-storage/index/index-fetch-section.c src/lib-storage/index/index-search.c |
diffstat | 11 files changed, 141 insertions(+), 66 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-imap/imap-message-cache.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-imap/imap-message-cache.c Sun Oct 06 12:20:20 2002 +0300 @@ -242,12 +242,6 @@ msg); } - if (msg->envelope == NULL) { - imap_envelope_parse_header(msg->pool, - &msg->envelope, - "", "", 0); - } - value = imap_envelope_get_part_data(msg->envelope); }
--- a/src/lib-index/mail-index-update.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-index/mail-index-update.c Sun Oct 06 12:20:20 2002 +0300 @@ -343,11 +343,6 @@ if (part != NULL && part->parent != NULL) return; - if (ctx->header_func != NULL) { - ctx->header_func(part, name, name_len, - value, value_len, ctx->context); - } - if (name_len == 4 && strncasecmp(name, "Date", 4) == 0) { /* date is stored into index record itself */ str = field_get_value(value, value_len); @@ -376,6 +371,12 @@ t_strndup(name, name_len), value, value_len); } + + /* keep this last, it may break the parameter data by moving mmaping */ + if (ctx->header_func != NULL) { + ctx->header_func(part, name, name_len, + value, value_len, ctx->context); + } } void mail_index_update_headers(MailIndexUpdate *update, IOBuffer *inbuf,
--- a/src/lib-index/mbox/mbox-append.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-index/mbox/mbox-append.c Sun Oct 06 12:20:20 2002 +0300 @@ -29,7 +29,7 @@ MailIndexUpdate *update; MboxHeaderContext ctx; time_t internal_date; - uoff_t abs_start_offset, stop_offset; + uoff_t abs_start_offset, eoh_offset; unsigned char *data, md5_digest[16]; size_t size, pos; int failed; @@ -65,9 +65,10 @@ io_buffer_skip(inbuf, pos+1); abs_start_offset = inbuf->start_offset + inbuf->offset; - /* now, find the ending "[\r]\nFrom " */ - mbox_skip_message(inbuf); - stop_offset = inbuf->offset; + /* now, find the end of header. also stops at "\nFrom " if it's + found (broken messages) */ + mbox_skip_header(inbuf); + eoh_offset = inbuf->offset; /* add message to index */ rec = mail_index_record_append_begin(index, internal_date); @@ -82,18 +83,18 @@ /* parse the header and cache wanted fields. get the message flags from Status and X-Status fields. temporarily limit the buffer size - so the message body is parsed properly (FIXME: does this have - side effects?) */ - mbox_header_init_context(&ctx, index); + so the message body is parsed properly */ + mbox_header_init_context(&ctx, index, inbuf); + ctx.set_read_limit = TRUE; io_buffer_seek(inbuf, abs_start_offset - inbuf->start_offset); - io_buffer_set_read_limit(inbuf, stop_offset); + io_buffer_set_read_limit(inbuf, eoh_offset); mail_index_update_headers(update, inbuf, 0, mbox_header_func, &ctx); + + io_buffer_seek(inbuf, inbuf->limit); io_buffer_set_read_limit(inbuf, 0); - io_buffer_seek(inbuf, stop_offset); - /* save MD5 */ md5_final(&ctx.md5, md5_digest); index->update_field_raw(update, FIELD_TYPE_MD5,
--- a/src/lib-index/mbox/mbox-fsck.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-index/mbox/mbox-fsck.c Sun Oct 06 12:20:20 2002 +0300 @@ -41,41 +41,6 @@ memcmp(old_digest, current_digest, 16) == 0; } -static int verify_end_of_body(IOBuffer *inbuf, uoff_t end_offset) -{ - unsigned char *data; - size_t size; - - /* don't bother parsing the whole body, just make - sure it ends properly */ - io_buffer_seek(inbuf, end_offset); - - if (inbuf->offset == inbuf->size) { - /* end of file. a bit unexpected though, - since \n is missing. */ - return TRUE; - } - - /* read forward a bit */ - if (io_buffer_read_data_blocking(inbuf, &data, &size, 6) < 0) - return FALSE; - - /* either there should be the next From-line, - or [\r]\n at end of file */ - if (size > 0 && data[0] == '\r') { - data++; size--; - } - if (size > 0) { - if (data[0] != '\n') - return FALSE; - - data++; size--; - } - - return size == 0 || - (size >= 5 && strncmp((char *) data, "From ", 5) == 0); -} - static int mail_update_header_size(MailIndex *index, MailIndexRecord *rec, MailIndexUpdate *update, MessageSize *hdr_size) @@ -137,14 +102,14 @@ if (rec->body_size == 0) { /* possibly broken message, find the From-line to make sure header parser won't pass it. */ - mbox_skip_message(inbuf); + mbox_skip_header(inbuf); io_buffer_set_read_limit(inbuf, inbuf->offset); io_buffer_seek(inbuf, header_offset); } /* get the MD5 sum of fixed headers and the current message flags in Status and X-Status fields */ - mbox_header_init_context(&ctx, index); + mbox_header_init_context(&ctx, index, inbuf); message_parse_header(NULL, inbuf, &hdr_size, mbox_header_func, &ctx); md5_final(&ctx.md5, current_digest); @@ -154,7 +119,8 @@ body_offset = inbuf->offset; do { if (verify_header_md5sum(index, rec, current_digest) && - verify_end_of_body(inbuf, body_offset + rec->body_size)) { + mbox_verify_end_of_body(inbuf, + body_offset + rec->body_size)) { /* valid message */ update = index->update_begin(index, rec);
--- a/src/lib-index/mbox/mbox-index.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-index/mbox/mbox-index.c Sun Oct 06 12:20:20 2002 +0300 @@ -54,12 +54,14 @@ } } -void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index) +void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index, + IOBuffer *inbuf) { memset(ctx, 0, sizeof(MboxHeaderContext)); md5_init(&ctx->md5); ctx->index = index; + ctx->inbuf = inbuf; ctx->custom_flags = mail_custom_flags_list_get(index->custom_flags); } @@ -188,10 +190,33 @@ void *context) { MboxHeaderContext *ctx = context; + uoff_t start_offset, end_offset; + size_t i; int fixed = FALSE; /* Pretty much copy&pasted from popa3d by Solar Designer */ switch (*name) { + case '\0': + /* End of headers */ + if (!ctx->set_read_limit) + break; + + /* a) use Content-Length, b) search for "From "-line */ + start_offset = ctx->inbuf->offset; + io_buffer_set_read_limit(ctx->inbuf, 0); + + end_offset = start_offset + ctx->content_length; + if (ctx->content_length == 0 || + !mbox_verify_end_of_body(ctx->inbuf, end_offset)) { + mbox_skip_message(ctx->inbuf); + end_offset = ctx->inbuf->offset; + ctx->content_length = end_offset - start_offset; + } + + io_buffer_seek(ctx->inbuf, start_offset); + io_buffer_set_read_limit(ctx->inbuf, end_offset); + break; + case 'R': case 'r': if (!ctx->received && name_len == 8 && @@ -201,6 +226,25 @@ } break; + case 'C': + case 'c': + if (name_len == 14 && + strncasecmp(name, "Content-Length", 14) == 0) { + /* manual parsing, so we can deal with uoff_t */ + ctx->content_length = 0; + for (i = 0; i < value_len; i++) { + if (value[i] < '0' || value[i] > '9') { + /* invalid */ + ctx->content_length = 0; + break; + } + + ctx->content_length = ctx->content_length * 10 + + (value[i] - '0'); + } + } + break; + case 'D': case 'd': if (name_len == 12) @@ -369,7 +413,7 @@ return FALSE; } -void mbox_skip_message(IOBuffer *inbuf) +static void mbox_skip_forward(IOBuffer *inbuf, int header) { unsigned char *msg; size_t i, size, startpos; @@ -379,6 +423,16 @@ startpos = i = 0; lastmsg = TRUE; while (io_buffer_read_data_blocking(inbuf, &msg, &size, startpos) > 0) { for (i = startpos; i < size; i++) { + if (msg[i] == '\n' && header && i >= 1) { + /* \n[\r]\n - end of header? */ + if (msg[i-1] == '\n' || + (msg[i-1] == '\r' && i >= 2 && + msg[i-2] == '\r')) { + i++; + break; + } + } + if (msg[i] == ' ' && i >= 5) { /* See if it's space after "From" */ if (msg[i-5] == '\n' && msg[i-4] == 'F' && @@ -425,6 +479,51 @@ io_buffer_skip(inbuf, startpos); } +void mbox_skip_header(IOBuffer *inbuf) +{ + mbox_skip_forward(inbuf, TRUE); +} + +void mbox_skip_message(IOBuffer *inbuf) +{ + mbox_skip_forward(inbuf, FALSE); +} + +int mbox_verify_end_of_body(IOBuffer *inbuf, uoff_t end_offset) +{ + unsigned char *data; + size_t size; + + /* don't bother parsing the whole body, just make + sure it ends properly */ + io_buffer_seek(inbuf, end_offset); + + if (inbuf->offset == inbuf->size) { + /* end of file. a bit unexpected though, + since \n is missing. */ + return TRUE; + } + + /* read forward a bit */ + if (io_buffer_read_data_blocking(inbuf, &data, &size, 6) < 0) + return FALSE; + + /* either there should be the next From-line, + or [\r]\n at end of file */ + if (size > 0 && data[0] == '\r') { + data++; size--; + } + if (size > 0) { + if (data[0] != '\n') + return FALSE; + + data++; size--; + } + + return size == 0 || + (size >= 5 && strncmp((char *) data, "From ", 5) == 0); +} + int mbox_mail_get_start_offset(MailIndex *index, MailIndexRecord *rec, uoff_t *offset) {
--- a/src/lib-index/mbox/mbox-index.h Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-index/mbox/mbox-index.h Sun Oct 06 12:20:20 2002 +0300 @@ -10,6 +10,10 @@ const char **custom_flags; MD5Context md5; int received; + + IOBuffer *inbuf; + uoff_t content_length; + int set_read_limit; } MboxHeaderContext; int mbox_set_syscall_error(MailIndex *index, const char *function); @@ -20,7 +24,8 @@ IOBuffer *mbox_file_open(MailIndex *index, uoff_t offset, int reopen); void mbox_file_close(MailIndex *index); -void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index); +void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index, + IOBuffer *inbuf); void mbox_header_free_context(MboxHeaderContext *ctx); void mbox_header_func(MessagePart *part __attr_unused__, const char *name, size_t name_len, @@ -32,7 +37,9 @@ void *context); int mbox_skip_crlf(IOBuffer *inbuf); void mbox_skip_empty_lines(IOBuffer *inbuf); +void mbox_skip_header(IOBuffer *inbuf); void mbox_skip_message(IOBuffer *inbuf); +int mbox_verify_end_of_body(IOBuffer *inbuf, uoff_t end_offset); int mbox_mail_get_start_offset(MailIndex *index, MailIndexRecord *rec, uoff_t *offset);
--- a/src/lib-index/mbox/mbox-rewrite.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-index/mbox/mbox-rewrite.c Sun Oct 06 12:20:20 2002 +0300 @@ -254,7 +254,7 @@ ctx->ximapbase_found = TRUE; (void)mbox_write_ximapbase(ctx); } - } else { + } else if (name_len > 0) { /* save this header */ (void)io_buffer_send(ctx->outbuf, name, name_len); (void)io_buffer_send(ctx->outbuf, ": ", 2);
--- a/src/lib-mail/message-parser.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-mail/message-parser.c Sun Oct 06 12:20:20 2002 +0300 @@ -425,6 +425,11 @@ hdr_size->physical_size + missing_cr_count; i_assert(hdr_size->virtual_size >= hdr_size->physical_size); } + + if (func != NULL) { + /* "end of headers" notify */ + func(part, "", 0, "", 0, context); + } } static MessageBoundary *boundary_find(MessageBoundary *boundaries,
--- a/src/lib-mail/message-parser.h Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-mail/message-parser.h Sun Oct 06 12:20:20 2002 +0300 @@ -36,7 +36,8 @@ void *context; }; -/* NOTE: name and value aren't \0-terminated */ +/* NOTE: name and value aren't \0-terminated. Also called once at end of + headers with name_len = value_len = 0. */ typedef void (*MessageHeaderFunc)(MessagePart *part, const char *name, size_t name_len, const char *value, size_t value_len,
--- a/src/lib-storage/index/index-fetch-section.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-storage/index/index-fetch-section.c Sun Oct 06 12:20:20 2002 +0300 @@ -78,7 +78,8 @@ { const char *field, *name_start, *name_end; - i_assert(size > 0); + if (size == 0) + return FALSE; name_start = name; name_end = name + size;
--- a/src/lib-storage/index/index-search.c Sun Oct 06 10:41:06 2002 +0300 +++ b/src/lib-storage/index/index-search.c Sun Oct 06 12:20:20 2002 +0300 @@ -406,7 +406,7 @@ { SearchHeaderContext *ctx = context; - if (ctx->custom_header || + if ((name_len > 0 && ctx->custom_header) || (name_len == 4 && strncasecmp(name, "From", 4) == 0) || (name_len == 2 && strncasecmp(name, "To", 2) == 0) || (name_len == 2 && strncasecmp(name, "Cc", 2) == 0) ||