示例#1
0
static void test_message_header_parser_partial(void)
{
	struct message_header_parser_ctx *parser;
	struct message_header_line *hdr;
	struct istream *input;
	unsigned int i, max = (strlen(test1_msg)-TEST1_MSG_BODY_LEN)*2;
	string_t *str;
	int ret;

	test_begin("message header parser partial");
	input = test_istream_create(test1_msg);
	test_istream_set_allow_eof(input, FALSE);

	str = t_str_new(max);
	parser = message_parse_header_init(input, NULL, 0);
	for (i = 0; i <= max; i++) {
		test_istream_set_size(input, i/2);
		while ((ret = message_parse_header_next(parser, &hdr)) > 0)
			hdr_write(str, hdr);
		test_assert((ret == 0 && i < max) ||
			    (ret < 0 && i == max));
	}
	message_parse_header_deinit(&parser);

	str_append(str, " body");
	test_assert(strcmp(str_c(str), test1_msg) == 0);
	i_stream_unref(&input);
	test_end();
}
示例#2
0
static void test_message_header_parser(void)
{
	static enum message_header_parser_flags max_hdr_flags =
		MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
		MESSAGE_HEADER_PARSER_FLAG_DROP_CR |
		MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
	enum message_header_parser_flags hdr_flags;
	struct message_header_parser_ctx *parser;
	struct message_size hdr_size;
	struct istream *input;

	test_begin("message header parser");
	input = test_istream_create(test1_msg);

	for (hdr_flags = 0; hdr_flags <= max_hdr_flags; hdr_flags++) {
		i_stream_seek(input, 0);
		parser = message_parse_header_init(input, &hdr_size, hdr_flags);
		test_message_header_parser_one(parser, hdr_flags);
		message_parse_header_deinit(&parser);
	}
	test_assert(hdr_size.physical_size == strlen(test1_msg)-TEST1_MSG_BODY_LEN);
	test_assert(hdr_size.virtual_size == strlen(test1_msg) - TEST1_MSG_BODY_LEN + 4);

	i_stream_unref(&input);
	test_end();
}
示例#3
0
static int parse_next_header_init(struct message_parser_ctx *ctx,
				  struct message_block *block_r)
{
	i_assert(ctx->hdr_parser_ctx == NULL);

	ctx->hdr_parser_ctx =
		message_parse_header_init(ctx->input, &ctx->part->header_size,
					  ctx->hdr_flags);
	ctx->part_seen_content_type = FALSE;

	ctx->parse_next_block = parse_next_header;
	return parse_next_header(ctx, block_r);
}
void message_parse_header(struct istream *input, struct message_size *hdr_size,
			  enum message_header_parser_flags flags,
			  message_header_callback_t *callback, void *context)
{
	struct message_header_parser_ctx *hdr_ctx;
	struct message_header_line *hdr;
	int ret;

	hdr_ctx = message_parse_header_init(input, hdr_size, flags);
	while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0)
		callback(hdr, context);
	i_assert(ret != 0);
	message_parse_header_deinit(&hdr_ctx);

	/* call after the final skipping */
	callback(NULL, context);
}
static void test_message_header_parser_no_eoh(void)
{
	static const char *str = "a:b\n";
	struct message_header_parser_ctx *parser;
	struct message_header_line *hdr;
	struct istream *input;

	test_begin("message header parser no EOH");

	input = test_istream_create(str);
	parser = message_parse_header_init(input, NULL, 0);
	test_assert(message_parse_header_next(parser, &hdr) > 0 &&
		    strcmp(hdr->name, "a") == 0);
	test_assert(message_parse_header_next(parser, &hdr) < 0);
	message_parse_header_deinit(&parser);
	test_assert(input->stream_errno == 0);
	i_stream_unref(&input);
	test_end();
}
示例#6
0
static void
test_message_header_parser_long_lines_str(const char *str,
					  unsigned int buffer_size,
					  struct message_size *size_r)
{
	struct message_header_parser_ctx *parser;
	struct message_header_line *hdr;
	struct istream *input;
	unsigned int i, len = strlen(str);

	input = test_istream_create(str);
	test_istream_set_max_buffer_size(input, buffer_size);

	parser = message_parse_header_init(input, size_r, 0);
	for (i = 1; i <= len; i++) {
		test_istream_set_size(input, i);
		while (message_parse_header_next(parser, &hdr) > 0) ;
	}
	message_parse_header_deinit(&parser);
	i_stream_unref(&input);
}
示例#7
0
bool mbox_sync_parse_match_mail(struct mbox_mailbox *mbox,
				struct mail_index_view *view, uint32_t seq)
{
        struct mbox_sync_mail_context ctx;
	struct message_header_parser_ctx *hdr_ctx;
	struct message_header_line *hdr;
	struct header_func *func;
	struct mbox_md5_context *mbox_md5_ctx;
	const void *data;
	bool expunged;
	uint32_t uid;
	int ret;

	/* we only wish to be sure that this mail actually is what we expect
	   it to be. If there's X-UID header and it matches our UID, we use it.
	   Otherwise it could mean that the X-UID header is invalid and it's
	   just not yet been rewritten. In that case use MD5 sum, if it
	   exists. */

	mail_index_lookup_uid(view, seq, &uid);
	memset(&ctx, 0, sizeof(ctx));
        mbox_md5_ctx = mbox->md5_v.init();

	hdr_ctx = message_parse_header_init(mbox->mbox_stream, NULL, 0);
	while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0) {
		if (hdr->eoh)
			break;

		func = bsearch(hdr->name, header_funcs,
			       N_ELEMENTS(header_funcs), sizeof(*header_funcs),
			       mbox_sync_bsearch_header_func_cmp);
		if (func != NULL) {
			if (strcasecmp(hdr->name, "X-UID") == 0) {
				if (hdr->continues) {
					hdr->use_full_value = TRUE;
					continue;
				}
				(void)parse_x_uid(&ctx, hdr);

				if (ctx.mail.uid == uid)
					break;
			}
		} else {
			mbox->md5_v.more(mbox_md5_ctx, hdr);
		}
	}
	i_assert(ret != 0);
	message_parse_header_deinit(&hdr_ctx);

	mbox->md5_v.finish(mbox_md5_ctx, ctx.hdr_md5_sum);

	if (ctx.mail.uid == uid)
		return TRUE;

	/* match by MD5 sum */
	mbox->mbox_save_md5 = TRUE;

	mail_index_lookup_ext(view, seq, mbox->md5hdr_ext_idx,
			      &data, &expunged);
	return data == NULL ? 0 :
		memcmp(data, ctx.hdr_md5_sum, 16) == 0;
}
示例#8
0
int mbox_sync_parse_next_mail(struct istream *input,
			      struct mbox_sync_mail_context *ctx)
{
	struct mbox_sync_context *sync_ctx = ctx->sync_ctx;
	struct message_header_parser_ctx *hdr_ctx;
	struct message_header_line *hdr;
	struct mbox_sync_header_func *func;
	struct mbox_md5_context *mbox_md5_ctx;
	size_t line_start_pos;
	int i, ret;

	ctx->hdr_offset = ctx->mail.offset;
	ctx->mail.flags = MAIL_RECENT; /* default to having recent flag */

        ctx->header_first_change = (size_t)-1;
	ctx->header_last_change = 0;

	for (i = 0; i < MBOX_HDR_COUNT; i++)
		ctx->hdr_pos[i] = (size_t)-1;

	ctx->content_length = (uoff_t)-1;
	str_truncate(ctx->header, 0);

        mbox_md5_ctx = ctx->sync_ctx->mbox->md5_v.init();

        line_start_pos = 0;
	hdr_ctx = message_parse_header_init(input, NULL, 0);
	while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0) {
		if (hdr->eoh) {
			ctx->have_eoh = TRUE;
			break;
		}

		if (!hdr->continued) {
			line_start_pos = str_len(ctx->header);
			str_append(ctx->header, hdr->name);
			str_append_n(ctx->header, hdr->middle, hdr->middle_len);
		}

		func = bsearch(hdr->name, header_funcs,
			       N_ELEMENTS(header_funcs), sizeof(*header_funcs),
			       mbox_sync_bsearch_header_func_cmp);

		if (func != NULL) {
			if (hdr->continues) {
				hdr->use_full_value = TRUE;
				continue;
			}

			if (!func->func(ctx, hdr)) {
				/* this header is broken, remove it */
				ctx->need_rewrite = TRUE;
				str_truncate(ctx->header, line_start_pos);
				if (ctx->header_first_change == (size_t)-1) {
					ctx->header_first_change =
						line_start_pos;
				}
				continue;
			}
			buffer_append(ctx->header, hdr->full_value,
				      hdr->full_value_len);
		} else {
			ctx->sync_ctx->mbox->md5_v.more(mbox_md5_ctx, hdr);
			buffer_append(ctx->header, hdr->value,
				      hdr->value_len);
		}
		if (!hdr->no_newline) {
			if (hdr->crlf_newline)
				str_append_c(ctx->header, '\r');
			str_append_c(ctx->header, '\n');
		}
	}
	i_assert(ret != 0);
	message_parse_header_deinit(&hdr_ctx);

	ctx->sync_ctx->mbox->md5_v.finish(mbox_md5_ctx, ctx->hdr_md5_sum);

	if ((ctx->seq == 1 && !ctx->seen_imapbase) ||
	    (ctx->seq > 1 && sync_ctx->dest_first_mail)) {
		/* missing X-IMAPbase */
		ctx->need_rewrite = TRUE;
		if (sync_ctx->base_uid_validity == 0) {
			/* figure out a new UIDVALIDITY for us. */
			sync_ctx->base_uid_validity =
				sync_ctx->hdr->uid_validity != 0 &&
				!sync_ctx->renumber_uids ?
				sync_ctx->hdr->uid_validity :
				I_MAX((uint32_t)ioloop_time, 1);
		}
	}

	ctx->body_offset = input->v_offset;
	if (input->stream_errno != 0) {
		mbox_sync_set_critical(ctx->sync_ctx, "read(%s) failed: %s",
			i_stream_get_name(input), i_stream_get_error(input));
		return -1;
	}
	return 0;
}