Exemplo n.º 1
0
int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input)
{
	struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
	struct maildir_filename *mf;

	/* new mail, new failure state */
	ctx->failed = FALSE;

	T_BEGIN {
		/* create a new file in tmp/ directory */
		const char *fname;

		ctx->fd = maildir_create_tmp(ctx->mbox, ctx->tmpdir, &fname);
		if (ctx->fd == -1)
			ctx->failed = TRUE;
		else {
			if (ctx->mbox->storage->storage.set->mail_save_crlf)
				ctx->input = i_stream_create_crlf(input);
			else
				ctx->input = i_stream_create_lf(input);
			mf = maildir_save_add(_ctx, fname, NULL);
			if (_ctx->data.guid != NULL) {
				maildir_save_set_dest_basename(_ctx, mf,
							       _ctx->data.guid);
			}
		}
	} T_END;

	if (!ctx->failed) {
		_ctx->data.output = o_stream_create_fd_file(ctx->fd, 0, FALSE);
		o_stream_cork(_ctx->data.output);
		ctx->last_save_finished = FALSE;
	}
	return ctx->failed ? -1 : 0;
}
Exemplo n.º 2
0
int dsync_mail_get_hdr_hash(struct mail *mail, const char **hdr_hash_r)
{
	struct istream *hdr_input, *input;
	struct mailbox_header_lookup_ctx *hdr_ctx;
	struct md5_context md5_ctx;
	unsigned char md5_result[MD5_RESULTLEN];
	const unsigned char *data;
	size_t size;
	int ret = 0;

	hdr_ctx = mailbox_header_lookup_init(mail->box, hashed_headers);
	ret = mail_get_header_stream(mail, hdr_ctx, &hdr_input);
	mailbox_header_lookup_unref(&hdr_ctx);
	if (ret < 0)
		return -1;

	input = i_stream_create_lf(hdr_input);

	md5_init(&md5_ctx);
	while (!i_stream_is_eof(input)) {
		if (i_stream_read_data(input, &data, &size, 0) == -1)
			break;
		if (size == 0)
			break;
		md5_update(&md5_ctx, data, size);
		i_stream_skip(input, size);
	}
	if (input->stream_errno != 0)
		ret = -1;
	i_stream_unref(&input);

	md5_final(&md5_ctx, md5_result);
	*hdr_hash_r = binary_to_hex(md5_result, sizeof(md5_result));
	return ret;
}
Exemplo n.º 3
0
static struct istream *
mbox_save_get_input_stream(struct mbox_save_context *ctx, struct istream *input)
{
	struct istream *filter, *ret, *cache_input, *streams[3];

	/* filter out unwanted headers and keep track of headers' MD5 sum */
	filter = i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE |
					       HEADER_FILTER_NO_CR |
					       HEADER_FILTER_ADD_MISSING_EOH |
					       HEADER_FILTER_END_BODY_WITH_LF,
					       mbox_save_drop_headers,
					       mbox_save_drop_headers_count,
					       save_header_callback, ctx);

	if ((ctx->mbox->storage->storage.flags &
	     MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0) {
		/* we're using MD5 sums to generate POP3 UIDLs.
		   clients don't like it much if there are duplicates,
		   so make sure that there can't be any by appending
		   our own X-Delivery-ID header. */
		const char *hdr;

		T_BEGIN {
			mbox_save_x_delivery_id(ctx);
		} T_END;
		hdr = ctx->x_delivery_id_header;

		streams[0] = i_stream_create_from_data(hdr, strlen(hdr));
		streams[1] = filter;
		streams[2] = NULL;
		ret = i_stream_create_concat(streams);
		i_stream_unref(&filter);
		filter = ret;
	}

	/* convert linefeeds to wanted format */
	ret = ctx->mbox->storage->storage.set->mail_save_crlf ?
		i_stream_create_crlf(filter) : i_stream_create_lf(filter);
	i_stream_unref(&filter);

	if (ctx->ctx.dest_mail != NULL) {
		/* caching creates a tee stream */
		cache_input =
			index_mail_cache_parse_init(ctx->ctx.dest_mail, ret);
		i_stream_unref(&ret);
		ret = cache_input;
	}
	return ret;
}
Exemplo n.º 4
0
void dbox_save_begin(struct dbox_save_context *ctx, struct istream *input)
{
	struct mail_save_context *_ctx = &ctx->ctx;
	struct mail_storage *_storage = _ctx->transaction->box->storage;
	struct dbox_storage *storage = (struct dbox_storage *)_storage;
	struct dbox_message_header dbox_msg_hdr;
	struct istream *crlf_input;

	dbox_save_add_to_index(ctx);

	if (_ctx->dest_mail == NULL) {
		if (ctx->mail == NULL)
			ctx->mail = mail_alloc(_ctx->transaction, 0, NULL);
		_ctx->dest_mail = ctx->mail;
	}
	mail_set_seq_saving(_ctx->dest_mail, ctx->seq);

	crlf_input = i_stream_create_lf(input);
	ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
	i_stream_unref(&crlf_input);

	/* write a dummy header. it'll get rewritten when we're finished */
	memset(&dbox_msg_hdr, 0, sizeof(dbox_msg_hdr));
	o_stream_cork(ctx->dbox_output);
	if (o_stream_send(ctx->dbox_output, &dbox_msg_hdr,
			  sizeof(dbox_msg_hdr)) < 0) {
		mail_storage_set_critical(_storage, "write(%s) failed: %m",
					  o_stream_get_name(ctx->dbox_output));
		ctx->failed = TRUE;
	}
	_ctx->data.output = ctx->dbox_output;

	if (_ctx->data.received_date == (time_t)-1)
		_ctx->data.received_date = ioloop_time;
	index_attachment_save_begin(_ctx, storage->attachment_fs, ctx->input);
}
Exemplo n.º 5
0
static void test_istream_crlf_input(const char *input)
{
	string_t *output;
	const unsigned char *data;
	size_t size = 0;
	ssize_t ret1, ret2;
	unsigned int i, j, pos, input_len = strlen(input);
	struct istream *istream, *crlf_istream;

	output = t_str_new(256);

	for (j = 0; j < 4; j++) {
		istream = i_stream_create_from_data(input, input_len);
		str_truncate(output, 0);
		if (j%2 == 0) {
			/* drop CRs */
			crlf_istream = i_stream_create_lf(istream);
			for (i = 0; i < input_len; i++) {
				if (input[i] == '\r' &&
				    (i == input_len || input[i+1] == '\n'))
					;
				else
					str_append_c(output, input[i]);
			}
		} else {
			/* add missing CRs */
			crlf_istream = i_stream_create_crlf(istream);
			for (i = 0; i < input_len; i++) {
				if (input[i] == '\n' &&
				    (i == 0 || input[i-1] != '\r'))
					str_append_c(output, '\r');
				str_append_c(output, input[i]);
			}
		}

		pos = 0;
		for (i = 1; i <= input_len; i++) {
			if (j >= 2) {
				i_stream_unref(&istream);
				i_stream_unref(&crlf_istream);
				istream = i_stream_create_from_data(input,
								    input_len);
				crlf_istream = j%2 == 0 ?
					i_stream_create_lf(istream) :
					i_stream_create_crlf(istream);
				pos = 0;
			}
			istream->real_stream->pos = i;
			ret1 = i_stream_read(crlf_istream);
			if (crlf_istream->real_stream->buffer_size != 0) {
				/* this is pretty evil */
				crlf_istream->real_stream->buffer_size =
					I_MAX(crlf_istream->real_stream->pos, i);
			}
			ret2 = i_stream_read(crlf_istream);
			data = i_stream_get_data(crlf_istream, &size);
			if (ret1 > 0 || ret2 > 0) {
				ret1 = I_MAX(ret1, 0) + I_MAX(ret2, 0);
				test_assert(pos + (unsigned int)ret1 == size);
				pos += ret1;
			}
			test_assert(memcmp(data, str_data(output), size) == 0);
		}
		test_assert(size == str_len(output));
		i_stream_unref(&crlf_istream);
		i_stream_unref(&istream);
	}
}