static void test_message_parser_small_blocks(void)
{
	struct message_parser_ctx *parser;
	struct istream *input;
	struct message_part *parts, *parts2;
	struct message_block block;
	unsigned int i, end_of_headers_idx;
	pool_t pool;
	int ret;

	test_begin("message parser in small blocks");
	pool = pool_alloconly_create("message parser", 10240);
	input = test_istream_create(test_msg);

	/* full parsing */
	parser = message_parser_init(pool, input, 0, 0);
	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
	test_assert(ret < 0);
	test_assert(message_parser_deinit(&parser, &parts) == 0);

	/* parsing in small blocks */
	i_stream_seek(input, 0);
	test_istream_set_allow_eof(input, FALSE);

	parser = message_parser_init(pool, input, 0, 0);
	for (i = 1; i <= TEST_MSG_LEN*2+1; i++) {
		test_istream_set_size(input, i/2);
		if (i > TEST_MSG_LEN*2)
			test_istream_set_allow_eof(input, TRUE);
		while ((ret = message_parser_parse_next_block(parser,
							      &block)) > 0) ;
		test_assert((ret == 0 && i <= TEST_MSG_LEN*2) ||
			    (ret < 0 && i > TEST_MSG_LEN*2));
	}
	test_assert(message_parser_deinit(&parser, &parts2) == 0);
	test_assert(msg_parts_cmp(parts, parts2));

	/* parsing in small blocks from preparsed parts */
	i_stream_seek(input, 0);
	test_istream_set_allow_eof(input, FALSE);

	end_of_headers_idx = (strstr(test_msg, "\n-----") - test_msg);
	parser = message_parser_init_from_parts(parts, input, 0,
					MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK);
	for (i = 1; i <= TEST_MSG_LEN*2+1; i++) {
		test_istream_set_size(input, i/2);
		if (i > TEST_MSG_LEN*2)
			test_istream_set_allow_eof(input, TRUE);
		while ((ret = message_parser_parse_next_block(parser,
							      &block)) > 0) ;
		test_assert((ret == 0 && i/2 <= end_of_headers_idx) ||
			    (ret < 0 && i/2 > end_of_headers_idx));
	}
	test_assert(message_parser_deinit(&parser, &parts2) == 0);
	test_assert(msg_parts_cmp(parts, parts2));

	i_stream_unref(&input);
	pool_unref(&pool);
	test_end();
}
Ejemplo n.º 2
0
static struct message_part *msg_parse(pool_t pool, bool parse_bodystructure)
{
	struct message_parser_ctx *parser;
	struct istream *input;
	struct message_block block;
	struct message_part *parts;
	int ret;

	input = i_stream_create_from_data(testmsg, sizeof(testmsg)-1);
	parser = message_parser_init(pool, input,
			MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
			MESSAGE_HEADER_PARSER_FLAG_DROP_CR,
			MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK);
	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) {
		if (parse_bodystructure) {
			imap_bodystructure_parse_header(pool, block.part,
							block.hdr);
		}
	}
	test_assert(ret < 0);

	test_assert(message_parser_deinit(&parser, &parts) == 0);
	i_stream_unref(&input);
	return parts;
}
Ejemplo n.º 3
0
int message_snippet_generate(struct istream *input,
			     unsigned int max_snippet_chars,
			     string_t *snippet)
{
	struct message_parser_ctx *parser;
	struct message_part *parts;
	struct message_decoder_context *decoder;
	struct message_block raw_block, block;
	struct snippet_context ctx;
	pool_t pool;
	int ret;

	memset(&ctx, 0, sizeof(ctx));
	pool = pool_alloconly_create("message snippet", 1024);
	ctx.snippet = snippet;
	ctx.chars_left = max_snippet_chars;

	parser = message_parser_init(pool_datastack_create(), input, 0, 0);
	decoder = message_decoder_init(NULL, 0);
	while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) {
		if (!message_decoder_decode_next_block(decoder, &raw_block, &block))
			continue;
		if (block.size == 0) {
			const char *ct;

			if (block.hdr != NULL)
				continue;

			/* end of headers - verify that we can use this
			   Content-Type. we get here only once, because we
			   always handle only one non-multipart MIME part. */
			ct = message_decoder_current_content_type(decoder);
			if (ct == NULL)
				/* text/plain */ ;
			else if (mail_html2text_content_type_match(ct)) {
				ctx.html2text = mail_html2text_init(MAIL_HTML2TEXT_FLAG_SKIP_QUOTED);
				ctx.plain_output = buffer_create_dynamic(pool, 1024);
			} else if (strncasecmp(ct, "text/", 5) != 0)
				break;
			continue;
		}
		if (!snippet_generate(&ctx, block.data, block.size))
			break;
	}
	i_assert(ret != 0);
	message_decoder_deinit(&decoder);
	message_parser_deinit(&parser, &parts);
	if (ctx.html2text != NULL)
		mail_html2text_deinit(&ctx.html2text);
	pool_unref(&pool);
	return input->stream_errno == 0 ? 0 : -1;
}
Ejemplo n.º 4
0
static void test_message_part_idx(void)
{
	struct message_parser_ctx *parser;
	struct istream *input;
	struct message_part *parts, *part, *prev_part;
	struct message_block block;
	unsigned int i, prev_idx = 0, part_idx;
	pool_t pool;
	int ret;

	test_begin("message part indexes");
	pool = pool_alloconly_create("message parser", 10240);
	input = i_stream_create_from_data(test_msg, TEST_MSG_LEN);

	parser = message_parser_init(pool, input, 0, 0);
	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) {
		part_idx = message_part_to_idx(block.part);
		test_assert(part_idx >= prev_idx);
		prev_idx = part_idx;
	}
	test_assert(ret < 0);
	test_assert(message_parser_deinit(&parser, &parts) == 0);

	part = message_part_by_idx(parts, 0);
	test_assert(part == parts);
	test_assert(message_part_by_idx(parts, 1) == parts->children);

	for (i = 1; i < 11; i++) {
		prev_part = part;
		part = message_part_by_idx(parts, i);
		test_assert(part != NULL);
		test_assert(part != NULL && message_part_to_idx(part) == i);
		test_assert(part != NULL && prev_part != NULL &&
			    prev_part->physical_pos < part->physical_pos);
	}
	test_assert(message_part_by_idx(parts, i) == NULL);

	i_stream_unref(&input);
	pool_unref(&pool);
	test_end();
}
Ejemplo n.º 5
0
static int
message_search_msg_real(struct message_search_context *ctx,
			struct istream *input, struct message_part *parts,
			const char **error_r)
{
	const enum message_header_parser_flags hdr_parser_flags =
		MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
	struct message_parser_ctx *parser_ctx;
	struct message_block raw_block;
	struct message_part *new_parts;
	int ret;

	message_search_reset(ctx);

	if (parts != NULL) {
		parser_ctx = message_parser_init_from_parts(parts,
						input, hdr_parser_flags, 0);
	} else {
		parser_ctx = message_parser_init(pool_datastack_create(),
						 input, hdr_parser_flags, 0);
	}

	while ((ret = message_parser_parse_next_block(parser_ctx,
						      &raw_block)) > 0) {
		if (message_search_more(ctx, &raw_block)) {
			ret = 1;
			break;
		}
	}
	i_assert(ret != 0);
	if (ret < 0 && input->stream_errno == 0) {
		/* normal exit */
		ret = 0;
	}
	if (message_parser_deinit_from_parts(&parser_ctx, &new_parts, error_r) < 0) {
		/* broken parts */
		ret = -1;
	}
	return ret;
}
Ejemplo n.º 6
0
struct istream *
i_stream_create_attachment_extractor(struct istream *input,
				     struct istream_attachment_settings *set,
				     void *context)
{
	struct attachment_istream *astream;

	i_assert(set->min_size > 0);
	i_assert(set->hash_format != NULL);
	i_assert(set->open_attachment_ostream != NULL);
	i_assert(set->close_attachment_ostream != NULL);

	astream = i_new(struct attachment_istream, 1);
	astream->part.temp_fd = -1;
	astream->set = *set;
	astream->context = context;
	astream->retry_read = TRUE;

	/* make sure the caller doesn't try to double-free this */
	set->hash_format = NULL;

	astream->istream.max_buffer_size = input->real_stream->max_buffer_size;

	astream->istream.read = i_stream_attachment_extractor_read;
	astream->istream.iostream.close = i_stream_attachment_extractor_close;

	astream->istream.istream.readable_fd = FALSE;
	astream->istream.istream.blocking = input->blocking;
	astream->istream.istream.seekable = FALSE;

	astream->pool = pool_alloconly_create("istream attachment", 1024);
	astream->parser = message_parser_init(astream->pool, input, 0,
				MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS |
				MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES);
	return i_stream_create(&astream->istream, input,
			       i_stream_get_fd(input));
}