Mercurial > dovecot > core-2.2
changeset 5506:6cd889c652b0 HEAD
Removed message_parse_from_parts(). Added message_parser_init_from_parts()
instead. Searching code now uses it whenever possible.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 03 Apr 2007 19:22:40 +0300 |
parents | d0caa9a44d1c |
children | 65250cfebd74 |
files | src/lib-mail/message-parser.c src/lib-mail/message-parser.h src/lib-storage/index/index-mail-headers.c src/lib-storage/index/index-mail.c |
diffstat | 4 files changed, 161 insertions(+), 83 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-mail/message-parser.c Tue Apr 03 18:02:36 2007 +0300 +++ b/src/lib-mail/message-parser.c Tue Apr 03 19:22:40 2007 +0300 @@ -37,6 +37,7 @@ int (*parse_next_block)(struct message_parser_ctx *ctx, struct message_block *block_r); + unsigned int return_body_blocks:1; unsigned int part_seen_content_type:1; }; @@ -48,6 +49,8 @@ struct message_block *block_r); static int parse_next_body_to_eof(struct message_parser_ctx *ctx, struct message_block *block_r); +static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, + struct message_block *block_r); static struct message_boundary * boundary_find(struct message_boundary *boundaries, @@ -538,6 +541,123 @@ return parse_next_header(ctx, block_r); } +static int preparsed_parse_eof(struct message_parser_ctx *ctx __attr_unused__, + struct message_block *block_r __attr_unused__) +{ + return -1; +} + +static void preparsed_skip_to_next(struct message_parser_ctx *ctx) +{ + ctx->parse_next_block = preparsed_parse_next_header_init; + while (ctx->part != NULL) { + if (ctx->part->next != NULL) { + ctx->part = ctx->part->next; + break; + } + ctx->part = ctx->part->parent; + } + if (ctx->part == NULL) + ctx->parse_next_block = preparsed_parse_eof; +} + +static int preparsed_parse_body_finish(struct message_parser_ctx *ctx, + struct message_block *block_r) +{ + i_stream_skip(ctx->input, ctx->skip); + ctx->skip = 0; + + preparsed_skip_to_next(ctx); + return ctx->parse_next_block(ctx, block_r); +} + +static int preparsed_parse_body_more(struct message_parser_ctx *ctx, + struct message_block *block_r) +{ + uoff_t end_offset = ctx->part->physical_pos + + ctx->part->header_size.physical_size + + ctx->part->body_size.physical_size; + int ret; + + ret = message_parser_read_more(ctx, block_r); + if (ret <= 0) + return ret; + + if (ctx->input->v_offset + block_r->size >= end_offset) { + block_r->size = end_offset - ctx->input->v_offset; + ctx->parse_next_block = preparsed_parse_body_finish; + } + ctx->skip = block_r->size; + return 1; +} + +static int preparsed_parse_body_init(struct message_parser_ctx *ctx, + struct message_block *block_r) +{ + uoff_t offset = ctx->part->physical_pos + + ctx->part->header_size.physical_size; + + i_assert(offset >= ctx->input->v_offset); + i_stream_skip(ctx->input, offset - ctx->input->v_offset); + + ctx->parse_next_block = preparsed_parse_body_more; + return preparsed_parse_body_more(ctx, block_r); +} + +static int preparsed_parse_finish_header(struct message_parser_ctx *ctx, + struct message_block *block_r) +{ + if (ctx->part->children != NULL) { + ctx->parse_next_block = preparsed_parse_next_header_init; + ctx->part = ctx->part->children; + } else if (ctx->return_body_blocks) { + ctx->parse_next_block = preparsed_parse_body_init; + } else { + preparsed_skip_to_next(ctx); + } + return ctx->parse_next_block(ctx, block_r); +} + +static int preparsed_parse_next_header(struct message_parser_ctx *ctx, + struct message_block *block_r) +{ + struct message_header_line *hdr; + int ret; + + ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr); + if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0)) + return ret; + + if (hdr != NULL) { + block_r->hdr = hdr; + block_r->size = 0; + return 1; + } + message_parse_header_deinit(&ctx->hdr_parser_ctx); + + ctx->parse_next_block = preparsed_parse_finish_header; + + /* return empty block as end of headers */ + block_r->hdr = NULL; + block_r->size = 0; + return 1; +} + +static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, + struct message_block *block_r) +{ + i_assert(ctx->hdr_parser_ctx == NULL); + + i_assert(ctx->part->physical_pos >= ctx->input->v_offset); + i_stream_skip(ctx->input, ctx->part->physical_pos - + ctx->input->v_offset); + + ctx->hdr_parser_ctx = message_parse_header_init(ctx->input, NULL, TRUE); + + ctx->parse_next_block = preparsed_parse_next_header; + return preparsed_parse_next_header(ctx, block_r); +} + struct message_parser_ctx * message_parser_init(pool_t part_pool, struct istream *input) { @@ -549,11 +669,25 @@ ctx->parser_pool = pool; ctx->part_pool = part_pool; ctx->input = input; - ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1); + ctx->parts = ctx->part = part_pool == NULL ? NULL : + p_new(part_pool, struct message_part, 1); ctx->parse_next_block = parse_next_header_init; return ctx; } +struct message_parser_ctx * +message_parser_init_from_parts(struct message_part *parts, + struct istream *input, bool return_body_blocks) +{ + struct message_parser_ctx *ctx; + + ctx = message_parser_init(NULL, input); + ctx->return_body_blocks = return_body_blocks; + ctx->parts = ctx->part = parts; + ctx->parse_next_block = preparsed_parse_next_header_init; + return ctx; +} + struct message_part *message_parser_deinit(struct message_parser_ctx **_ctx) { struct message_parser_ctx *ctx = *_ctx; @@ -588,7 +722,7 @@ block_r->part = ctx->part; - if (ret < 0) { + if (ret < 0 && ctx->part != NULL) { i_assert(ctx->input->eof); while (ctx->part->parent != NULL) { message_size_add(&ctx->part->parent->body_size, @@ -642,46 +776,6 @@ i_assert(ret != 0); } -static void part_parse_headers(struct message_part *part, struct istream *input, - message_part_header_callback_t *callback, - void *context) -{ - struct message_header_parser_ctx *hdr_ctx; - struct message_header_line *hdr; - int ret; - - while (part != NULL) { - /* note that we want to parse the header of all - the message parts, multiparts too. */ - i_assert(part->physical_pos >= input->v_offset); - i_stream_skip(input, part->physical_pos - input->v_offset); - - hdr_ctx = message_parse_header_init(input, NULL, TRUE); - while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0) - callback(part, hdr, context); - i_assert(ret != 0); - message_parse_header_deinit(&hdr_ctx); - - /* call after the final skipping */ - callback(part, NULL, context); - - if (part->children != NULL) { - part_parse_headers(part->children, input, - callback, context); - } - - part = part->next; - } -} - -#undef message_parse_from_parts -void message_parse_from_parts(struct message_part *part, struct istream *input, - message_part_header_callback_t *callback, - void *context) -{ - part_parse_headers(part, input, callback, context); -} - static void message_parser_set_crlfs_diff(struct message_part *parts, bool use_crlf, off_t diff)
--- a/src/lib-mail/message-parser.h Tue Apr 03 18:02:36 2007 +0300 +++ b/src/lib-mail/message-parser.h Tue Apr 03 19:22:40 2007 +0300 @@ -61,6 +61,10 @@ are allocated from. */ struct message_parser_ctx * message_parser_init(pool_t part_pool, struct istream *input); +/* Use preparsed parts to speed up parsing. */ +struct message_parser_ctx * +message_parser_init_from_parts(struct message_part *parts, + struct istream *input, bool return_body_blocks); struct message_part *message_parser_deinit(struct message_parser_ctx **ctx); /* Read the next block of a message. Returns 1 if block is returned, 0 if @@ -104,22 +108,6 @@ (message_part_header_callback_t *)callback, context) #endif -/* callback is called for each field in message header. */ -void message_parse_from_parts(struct message_part *part, struct istream *input, - message_part_header_callback_t *callback, - void *context); -#ifdef CONTEXT_TYPE_SAFETY -# define message_parse_from_parts(part, input, callback, context) \ - ({(void)(1 ? 0 : callback((struct message_part *)0, \ - (struct message_header_line *)0, context)); \ - message_parse_from_parts(part, input, \ - (message_part_header_callback_t *)callback, context); }) -#else -# define message_parse_from_parts(part, input, callback, context) \ - message_parse_from_parts(part, input, \ - (message_part_header_callback_t *)callback, context) -#endif - /* Update the physical_size of all parts. If use_crlf is TRUE, they're set to same as virtual_size. If use_crlf is FALSE, they're set to virtual_size - lines. physical_pos fields are also updated. */
--- a/src/lib-storage/index/index-mail-headers.c Tue Apr 03 18:02:36 2007 +0300 +++ b/src/lib-storage/index/index-mail-headers.c Tue Apr 03 19:22:40 2007 +0300 @@ -340,6 +340,23 @@ index_mail_parse_header(mail->data.parts, hdr, mail); } +static void index_mail_init_parser(struct index_mail *mail) +{ + struct index_mail_data *data = &mail->data; + + if (data->parser_ctx != NULL) + (void)message_parser_deinit(&data->parser_ctx); + + if (data->parts == NULL) { + data->parser_ctx = + message_parser_init(mail->data_pool, data->stream); + } else { + data->parser_ctx = + message_parser_init_from_parts(data->parts, + data->stream, FALSE); + } +} + int index_mail_parse_headers(struct index_mail *mail, struct mailbox_header_lookup_ctx *headers) { @@ -357,10 +374,7 @@ data->save_bodystructure_header)) { /* initialize bodystructure parsing in case we read the whole message. */ - if (data->parser_ctx != NULL) - (void)message_parser_deinit(&mail->data.parser_ctx); - data->parser_ctx = - message_parser_init(mail->data_pool, data->stream); + index_mail_init_parser(mail); message_parser_parse_header(data->parser_ctx, &data->hdr_size, index_mail_parse_part_header_cb, mail);
--- a/src/lib-storage/index/index-mail.c Tue Apr 03 18:02:36 2007 +0300 +++ b/src/lib-storage/index/index-mail.c Tue Apr 03 19:22:40 2007 +0300 @@ -581,7 +581,6 @@ struct index_mail_data *data = &mail->data; uoff_t old_offset; - i_assert(data->parts == NULL); i_assert(data->parser_ctx != NULL); old_offset = data->stream->v_offset; @@ -619,6 +618,7 @@ i_stream_seek(data->stream, 0); if (!data->hdr_size_set) { if ((data->access_part & PARSE_HDR) != 0) { + (void)get_cached_parts(mail); if (index_mail_parse_headers(mail, NULL) < 0) return NULL; } else { @@ -675,30 +675,12 @@ /* we haven't parsed the header yet */ data->save_bodystructure_header = TRUE; data->save_bodystructure_body = TRUE; + (void)get_cached_parts(mail); if (index_mail_parse_headers(mail, NULL) < 0) return; } - if (data->parts == NULL) - index_mail_parse_body(mail, field); - else { - /* body structure is known already, so use it to parse only - the MIME headers */ - uoff_t old_offset; - - i_assert(data->parts->next == NULL); - - old_offset = data->stream->v_offset; - i_stream_seek(data->stream, - data->hdr_size.physical_size); - - message_parse_from_parts(data->parts->children, - data->stream, - parse_bodystructure_part_header, - mail->data_pool); - data->parsed_bodystructure = TRUE; - i_stream_seek(data->stream, old_offset); - } + index_mail_parse_body(mail, field); } static void