message-header-parser.c revision 01ca85e6e763cfa0d146166fdd60654f04f51199
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainenmessage_parse_header_init(struct istream *input, struct message_size *hdr_size,
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen ctx = i_new(struct message_header_parser_ctx, 1);
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen ctx->value_buf = buffer_create_dynamic(default_pool, 4096);
c14ceb2cabfd4934243d09ff2dfbc24791ef4eb2Timo Sirainenvoid message_parse_header_deinit(struct message_header_parser_ctx **_ctx)
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen struct message_header_parser_ctx *ctx = *_ctx;
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainenint message_parse_header_next(struct message_header_parser_ctx *ctx,
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen struct message_header_line *line = &ctx->line;
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen const unsigned char *msg;
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen size_t i, size, startpos, colon_pos, parse_size;
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen bool continued, continues, last_no_newline, last_crlf;
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen /* new header line */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen ret = i_stream_read_data(ctx->input, &msg, &size, startpos+1);
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen /* we want to know one byte in advance to find out
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen if it's multiline header */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen /* header ended unexpectedly. */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen /* error / EOF with no bytes */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen if (size > 0 && !ctx->skip_line && !continued &&
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen (msg[0] == '\r' && size > 1 && msg[1] == '\n'))) {
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen /* end of headers - this mostly happens just
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen with mbox where headers are read separately
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* stream is nonblocking - need more data */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* a) line is larger than input buffer
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen b) header ended unexpectedly */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* go back to last LWSP if found. */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen /* we may or may not have a full header,
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen but we don't know until we get the
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen next character. leave out the
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen linefeed and finish the header on
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen the next run. */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* the buffer really has to be more than 2 to
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen avoid CRLF looping forever */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen /* find ':' */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* end of headers, or error */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* find '\n' */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen for (; i < parse_size; i++) {
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen if (i < parse_size && i+1 == size && ret == -2) {
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* we don't know if the line continues. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else if (i < parse_size) {
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* got a line */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* skipping a line with a huge header name */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* missing CR */
9bd607718368ffb39bcfbc82010073364901c5a2Timo Sirainen /* missing CR */
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen (ctx->flags & MESSAGE_HEADER_PARSER_FLAG_DROP_CR) == 0;
a6e79dffa06db28bcfad9c1e5fc819c48172d5deTimo Sirainen (ctx->flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0;
colon_pos--;
if (last_no_newline) {
if (last_crlf)
int ret;