message-header-parser.c revision 51c331377beb4a2acb81aee4d12bc8ef6c496625
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2002-2006 Timo Sirainen */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch#include "lib.h"
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch#include "buffer.h"
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch#include "istream.h"
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch#include "str.h"
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch#include "message-size.h"
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch#include "message-header-parser.h"
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Boschstruct message_header_parser_ctx {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_header_line line;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct istream *input;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_size *hdr_size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch string_t *name;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch buffer_t *value_buf;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size_t skip;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch unsigned int skip_initial_lwsp:1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch unsigned int skip_line:1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch unsigned int has_nuls:1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch};
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Boschstruct message_header_parser_ctx *
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Boschmessage_parse_header_init(struct istream *input, struct message_size *hdr_size,
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch bool skip_initial_lwsp)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch{
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_header_parser_ctx *ctx;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx = i_new(struct message_header_parser_ctx, 1);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->input = input;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size = hdr_size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->name = str_new(default_pool, 128);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip_initial_lwsp = skip_initial_lwsp;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (hdr_size != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch memset(hdr_size, 0, sizeof(*hdr_size));
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch return ctx;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch}
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Boschvoid message_parse_header_deinit(struct message_header_parser_ctx **_ctx)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch{
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_header_parser_ctx *ctx = *_ctx;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch i_stream_skip(ctx->input, ctx->skip);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->value_buf != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch buffer_free(ctx->value_buf);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch str_free(&ctx->name);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch i_free(ctx);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch *_ctx = NULL;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch}
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Boschint message_parse_header_next(struct message_header_parser_ctx *ctx,
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_header_line **hdr_r)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch{
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_header_line *line = &ctx->line;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch const unsigned char *msg;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size_t i, size, startpos, colon_pos, parse_size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch int ret;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch bool last_no_newline;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch *hdr_r = NULL;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (line->eoh)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch return -1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->skip > 0) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch i_stream_skip(ctx->input, ctx->skip);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch startpos = 0; colon_pos = UINT_MAX;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch last_no_newline = line->no_newline;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->no_newline = FALSE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->crlf_newline = FALSE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (line->continues) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (line->use_full_value && !line->continued) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* save the first line */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->value_buf != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch buffer_set_used_size(ctx->value_buf, 0);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->value_buf =
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch buffer_create_dynamic(default_pool,
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch 4096);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch buffer_append(ctx->value_buf,
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value, line->value_len);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->continued = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->continues = FALSE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch colon_pos = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* new header line */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->continued = FALSE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->name_offset = ctx->input->v_offset;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch for (;;) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ret = i_stream_read_data(ctx->input, &msg, &size, startpos+1);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ret > 0) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* we want to know one byte in advance to find out
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if it's multiline header */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch parse_size = size-1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch parse_size = size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ret <= 0 && startpos == size) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ret == -1) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (startpos > 0) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* header ended unexpectedly. */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->no_newline = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip = startpos;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* error / EOF with no bytes */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch return -1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ret == 0 && !ctx->input->eof) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* stream is nonblocking - need more data */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch return 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[0] == '\n' ||
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch (msg[0] == '\r' && size > 1 && msg[1] == '\n')) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* end of headers - this mostly happens just
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch with mbox where headers are read separately
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch from body */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->lines++;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[0] == '\r') {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip = 2;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->crlf_newline = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip = 1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->virtual_size++;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* a) line is larger than input buffer
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch b) header ended unexpectedly */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (colon_pos == UINT_MAX && ret == -2 &&
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch !line->continued) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* header name is huge. just skip it. */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[size-1] == '\r')
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size--;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->physical_size += size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->virtual_size += size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch i_stream_skip(ctx->input, size);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip_line = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch startpos = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch continue;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ret == -2) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* go back to last LWSP if found. */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size_t min_pos =
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch !line->continued ? colon_pos : 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch for (i = size-1; i > min_pos; i--) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (IS_LWSP(msg[i])) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size = i;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->continues = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->no_newline = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip = size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* find ':' */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (colon_pos == UINT_MAX) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch for (i = startpos; i < parse_size; i++) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[i] <= ':') {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[i] == ':') {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch colon_pos = i;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->full_value_offset =
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->input->v_offset +
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch i + 1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[i] == '\n') {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* end of headers, or error */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[i] == '\0')
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->has_nuls = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* find '\n' */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch for (i = startpos; i < parse_size; i++) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[i] <= '\n') {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[i] == '\n')
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (msg[i] == '\0')
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->has_nuls = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (i < parse_size) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* got a line */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->skip_line) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* skipping a huge line */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->physical_size += i;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->virtual_size += i;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (i == 0 || msg[i-1] != '\r') {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* missing CR */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->virtual_size++;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->crlf_newline = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch i_stream_skip(ctx->input, i);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch startpos = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip_line = FALSE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch continue;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->continues = i+1 < size && IS_LWSP(msg[i+1]);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->lines++;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (i == 0 || msg[i-1] != '\r') {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* missing CR */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->virtual_size++;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size = i;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size = i-1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->crlf_newline = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->skip = i+1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch startpos = i;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (size == 0) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* end of headers */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->eoh = TRUE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->name_len = line->value_len = line->full_value_len = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->name = ""; line->value = line->full_value = NULL;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->middle = NULL; line->middle_len = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else if (line->continued) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value = msg;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value_len = size;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->middle = NULL;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->middle_len = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else if (colon_pos == UINT_MAX) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* missing ':', assume the whole line is name */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value = NULL;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value_len = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch str_truncate(ctx->name, 0);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch str_append_n(ctx->name, msg, size);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->name = str_c(ctx->name);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->name_len = str_len(ctx->name);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->middle = NULL;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->middle_len = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch size_t pos;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value = msg + colon_pos+1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value_len = size - colon_pos - 1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->skip_initial_lwsp) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* get value. skip all LWSP after ':'. Note that
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch RFC2822 doesn't say we should, but history behind
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch it..
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch Exception to this is if the value consists only of
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch LWSP, then skip only the one LWSP after ':'. */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch for (pos = 0; pos < line->value_len; pos++) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (!IS_LWSP(line->value[0]))
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch break;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (pos == line->value_len) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* everything was LWSP */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (line->value_len > 0 &&
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch IS_LWSP(line->value[0]))
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch pos = 1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch pos = line->value_len > 0 &&
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch IS_LWSP(line->value[0]) ? 1 : 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value += pos;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->value_len -= pos;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->full_value_offset += pos;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* get name, skip LWSP before ':' */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch while (colon_pos > 0 && IS_LWSP(msg[colon_pos-1]))
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch colon_pos--;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->middle = msg + colon_pos;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->middle_len = (size_t)(line->value - line->middle);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch str_truncate(ctx->name, 0);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch str_append_n(ctx->name, msg, colon_pos);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->name = str_c(ctx->name);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->name_len = str_len(ctx->name);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (!line->continued) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* first header line, set full_value = value */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->full_value = line->value;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->full_value_len = line->value_len;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else if (line->use_full_value) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* continue saving the full value */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (!last_no_newline)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch buffer_append_c(ctx->value_buf, '\n');
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch buffer_append(ctx->value_buf, line->value, line->value_len);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->full_value = buffer_get_data(ctx->value_buf,
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch &line->full_value_len);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch } else {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* we didn't want full_value, and this is a continued line. */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->full_value = NULL;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->full_value_len = 0;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* always reset it */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch line->use_full_value = FALSE;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch if (ctx->hdr_size != NULL) {
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->physical_size += ctx->skip;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch ctx->hdr_size->virtual_size += ctx->skip;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch }
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch *hdr_r = line;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch return 1;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch}
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Boschbool message_parse_header_has_nuls(struct message_header_parser_ctx *ctx)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch{
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch return ctx->has_nuls;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch}
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Boschvoid message_parse_header(struct istream *input, struct message_size *hdr_size,
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch message_header_callback_t *callback, void *context)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch{
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_header_parser_ctx *hdr_ctx;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch struct message_header_line *hdr;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch int ret;
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch hdr_ctx = message_parse_header_init(input, hdr_size, TRUE);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0)
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch callback(hdr, context);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch i_assert(ret != 0);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch message_parse_header_deinit(&hdr_ctx);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch /* call after the final skipping */
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch callback(NULL, context);
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch}
03f08e4abef2afc782069bdfef305f84e98f0922Stephan Bosch