message-parser.c revision 17c29909503e866fe8aab2c4476fb9f34cc2c12e
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen/* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix.
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen We'll add a bit more just in case. */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct message_header_parser_ctx *hdr_parser_ctx;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen int (*parse_next_block)(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenmessage_part_header_callback_t *null_message_part_header_callback = NULL;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int parse_next_header_init(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int parse_next_body_to_boundary(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int parse_next_body_to_eof(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int preparsed_parse_next_header_init(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenboundary_find(struct message_boundary *boundaries,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* As MIME spec says: search from latest one to oldest one so that we
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen don't break if the same boundary is used in nested parts. Also the
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen full message line doesn't have to match the boundary, only the
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen beginning. */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen memcmp(boundaries->boundary, data, boundaries->len) == 0)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void parse_body_add_block(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen unsigned int missing_cr_count = 0;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen const unsigned char *cur, *next, *data = block->data;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* check if we have NULs */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ctx->part->flags |= MESSAGE_PART_FLAG_HAS_NULS;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* count number of lines and missing CRs */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen while ((next = memchr(cur, '\n', block->size - (cur - data))) != NULL) {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ctx->part->body_size.physical_size += block->size;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ctx->part->body_size.virtual_size += block->size + missing_cr_count;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int message_parser_read_more(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ret = i_stream_read_data(ctx->input, &block_r->data,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* EOF, but we still have some data.
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen return it. */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* reset number of wanted characters if we actually got them */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenmessage_part_append(pool_t pool, struct message_part *parent)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* set child position */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void parse_next_body_multipart_init(struct message_parser_ctx *ctx)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen b = p_new(ctx->parser_pool, struct message_boundary, 1);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int parse_next_body_message_rfc822_init(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ctx->part = message_part_append(ctx->part_pool, ctx->part);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenboundary_line_find(struct message_parser_ctx *ctx,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen const unsigned char *data, size_t size, bool full,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* not a boundary, just skip this line */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* need to find the end of line */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (memchr(data + 2, '\n', size - 2) == NULL &&
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* no LF found */
const unsigned char *ptr;
int ret;
bool full;
return ret;
if (first_line)
line_size = 0;
int ret;
bool full;
return ret;
if (ret >= 0) {
return ret == 0 ? 0 :
boundary_start = 0;
if (boundary_start != 0) {
if (ret >= 0) {
} else if (boundary_start == 0) {
ret = 0;
ret = 0;
bool full;
int ret;
return ret;
const char *const *results;
#define MUTEX_FLAGS \
int ret;
return ret;
else T_BEGIN {
} T_END;
MESSAGE_PART_FLAG_MULTIPART_DIGEST) != 0) {
bool full;
int ret;
return ret;
const unsigned char *cur;
bool full;
int ret;
return ret;
cur--;
boundary_min_start = 0;
bool full;
int ret;
return ret;
bool full;
int ret;
return ret;
int ret;
return ret;
static struct message_parser_ctx *
return ctx;
struct message_parser_ctx *
return ctx;
struct message_parser_ctx *
return ctx;
return ret;
int ret;
if (ret == 0) {
return ret;
void *context)
int ret;
if (ret < 0) {
void *context)
int ret;