Ejemplo n.º 1
0
static int parse_next_body_to_eof(struct message_parser_ctx *ctx,
				  struct message_block *block_r)
{
	bool full;
	int ret;

	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
		return ret;

	parse_body_add_block(ctx, block_r);
	return 1;
}
Ejemplo n.º 2
0
static int parse_part_finish(struct message_parser_ctx *ctx,
			     struct message_boundary *boundary,
			     struct message_block *block_r, bool first_line)
{
	struct message_part *part;
	size_t line_size;

	i_assert(ctx->last_boundary == NULL);

	/* get back to parent MIME part, summing the child MIME part sizes
	   into parent's body sizes */
	for (part = ctx->part; part != boundary->part; part = part->parent) {
		message_size_add(&part->parent->body_size, &part->body_size);
		message_size_add(&part->parent->body_size, &part->header_size);
	}
	i_assert(part != NULL);
	ctx->part = part;

	if (boundary->epilogue_found) {
		/* this boundary isn't needed anymore */
		ctx->boundaries = boundary->next;
	} else {
		/* forget about the boundaries we possibly skipped */
		ctx->boundaries = boundary;
	}

	/* the boundary itself should already be in buffer. add that. */
	block_r->data = i_stream_get_data(ctx->input, &block_r->size);
	i_assert(block_r->size >= ctx->skip);
	block_r->data += ctx->skip;
	/* [[\r]\n]--<boundary>[--] */
	if (first_line)
		line_size = 0;
	else if (block_r->data[0] == '\r') {
		i_assert(block_r->data[1] == '\n');
		line_size = 2;
	} else {
		i_assert(block_r->data[0] == '\n');
		line_size = 1;
	}
	line_size += 2 + boundary->len + (boundary->epilogue_found ? 2 : 0);
	i_assert(block_r->size >= ctx->skip + line_size);
	block_r->size = line_size;
	parse_body_add_block(ctx, block_r);

	ctx->parse_next_block = parse_next_body_skip_boundary_line;

	if ((ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES) != 0)
		return 1;
	return ctx->parse_next_block(ctx, block_r);
}
Ejemplo n.º 3
0
static int parse_next_body_skip_boundary_line(struct message_parser_ctx *ctx,
					      struct message_block *block_r)
{
	const unsigned char *ptr;
	int ret;
	bool full;

	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
		return ret;

	ptr = memchr(block_r->data, '\n', block_r->size);
	if (ptr == NULL) {
		parse_body_add_block(ctx, block_r);
		if (block_r->size > 0 &&
		    (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES) != 0)
			return 1;
		return 0;
	}

	/* found the LF */
	block_r->size = (ptr - block_r->data) + 1;
	parse_body_add_block(ctx, block_r);

	if (ctx->boundaries == NULL || ctx->boundaries->part != ctx->part) {
		/* epilogue */
		if (ctx->boundaries != NULL)
			ctx->parse_next_block = parse_next_body_to_boundary;
		else
			ctx->parse_next_block = parse_next_body_to_eof;
	} else {
		/* a new MIME part begins */
		ctx->parse_next_block = parse_next_mime_header_init;
	}
	if (block_r->size > 0 &&
	    (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES) != 0)
		return 1;
	return ctx->parse_next_block(ctx, block_r);
}
Ejemplo n.º 4
0
static int parse_next_body_skip_boundary_line(struct message_parser_ctx *ctx,
					      struct message_block *block_r)
{
	const unsigned char *ptr;
	int ret;
	bool full;

	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
		return ret;

	ptr = memchr(block_r->data, '\n', block_r->size);
	if (ptr == NULL) {
		parse_body_add_block(ctx, block_r);
		return 1;
	}

	/* found the LF */
	block_r->size = (ptr - block_r->data) + 1;
	parse_body_add_block(ctx, block_r);

	/* a new MIME part begins */
	ctx->parse_next_block = parse_next_mime_header_init;
	return 1;
}
Ejemplo n.º 5
0
static int parse_next_body_to_eof(struct message_parser_ctx *ctx,
				  struct message_block *block_r)
{
	bool full;
	int ret;

	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
		return ret;

	parse_body_add_block(ctx, block_r);

	if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 &&
	    (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) == 0)
		return 0;

	return 1;
}
Ejemplo n.º 6
0
static int parse_part_finish(struct message_parser_ctx *ctx,
			     struct message_boundary *boundary,
			     struct message_block *block_r, bool first_line)
{
	struct message_part *part;

	/* get back to parent MIME part, summing the child MIME part sizes
	   into parent's body sizes */
	for (part = ctx->part; part != boundary->part; part = part->parent) {
		message_size_add(&part->parent->body_size, &part->body_size);
		message_size_add(&part->parent->body_size, &part->header_size);
	}
	ctx->part = part;

	if (boundary->epilogue_found) {
		/* this boundary isn't needed anymore */
		ctx->boundaries = boundary->next;

		if (ctx->boundaries != NULL)
			ctx->parse_next_block = parse_next_body_to_boundary;
		else
			ctx->parse_next_block = parse_next_body_to_eof;
		return ctx->parse_next_block(ctx, block_r);
	}

	/* forget about the boundaries we possibly skipped */
	ctx->boundaries = boundary;

	/* the boundary itself should already be in buffer. add that. */
	block_r->data = i_stream_get_data(ctx->input, &block_r->size);
	i_assert(block_r->size >= ctx->skip + 2 + boundary->len +
		 (first_line ? 0 : 1));
	block_r->data += ctx->skip;
	/* [\n]--<boundary> */
	block_r->size = (first_line ? 0 : 1) + 2 + boundary->len;
	parse_body_add_block(ctx, block_r);

	ctx->parse_next_block = parse_next_body_skip_boundary_line;
	return 1;
}
Ejemplo n.º 7
0
static int parse_next_body_to_boundary(struct message_parser_ctx *ctx,
				       struct message_block *block_r)
{
	struct message_boundary *boundary = NULL;
	const unsigned char *data, *cur, *next, *end;
	size_t boundary_start;
	int ret;
	bool full;

	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
		return ret;

	data = block_r->data;
	if (ctx->last_chr == '\n') {
		/* handle boundary in first line of message. alternatively
		   it's an empty line. */
		ret = boundary_line_find(ctx, block_r->data,
					 block_r->size, full, &boundary);
		if (ret >= 0) {
			return ret == 0 ? 0 :
				parse_part_finish(ctx, boundary, block_r, TRUE);
		}
	}

	i_assert(block_r->size > 0);
	boundary_start = 0;

	/* skip to beginning of the next line. the first line was
	   handled already. */
	cur = data; end = data + block_r->size;
	while ((next = memchr(cur, '\n', end - cur)) != NULL) {
		cur = next + 1;

		boundary_start = next - data;
		if (next > data && next[-1] == '\r')
			boundary_start--;

		if (boundary_start != 0) {
			/* we can at least skip data until the first [CR]LF.
			   input buffer can't be full anymore. */
			full = FALSE;
		}

		ret = boundary_line_find(ctx, cur, end - cur, full, &boundary);
		if (ret >= 0) {
			/* found / need more data */
			if (ret == 0 && boundary_start == 0)
				ctx->want_count += cur - block_r->data;
			break;
		}
	}

	if (next != NULL) {
		/* found / need more data */
		i_assert(ret >= 0);
		i_assert(!(ret == 0 && full));
	} else if (boundary_start == 0) {
		/* no linefeeds in this block. we can just skip it. */
		ret = 0;
		boundary_start = block_r->size;
	} else {
		/* the boundary wasn't found from this data block,
		   we'll need more data. */
		ret = 0;
		ctx->want_count = (block_r->size - boundary_start) + 1;
	}

	if (ret > 0 || (ret == 0 && !ctx->eof)) {
		/* a) we found the boundary
		   b) we need more data and haven't reached EOF yet
		   so leave CR+LF + last line to buffer */
		block_r->size = boundary_start;
	}
	if (block_r->size != 0) {
		parse_body_add_block(ctx, block_r);
		return 1;
	}
	return ret <= 0 ? ret :
		parse_part_finish(ctx, boundary, block_r, FALSE);
}