dovecot-2.2: lib-storage: Use the new istream-attachment-* APIs ...

dovecot at dovecot.org dovecot at dovecot.org
Fri Jun 29 08:01:25 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/38b0986605a6
changeset: 14699:38b0986605a6
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Jun 29 08:01:08 2012 +0300
description:
lib-storage: Use the new istream-attachment-* APIs to handle external mail attachments.

diffstat:

 src/lib-storage/index/dbox-common/dbox-attachment.c |   82 +-
 src/lib-storage/index/index-attachment.c            |  713 +++----------------
 2 files changed, 133 insertions(+), 662 deletions(-)

diffs (truncated from 925 to 300 lines):

diff -r ffab35ef2e5b -r 38b0986605a6 src/lib-storage/index/dbox-common/dbox-attachment.c
--- a/src/lib-storage/index/dbox-common/dbox-attachment.c	Fri Jun 29 08:00:19 2012 +0300
+++ b/src/lib-storage/index/dbox-common/dbox-attachment.c	Fri Jun 29 08:01:08 2012 +0300
@@ -2,10 +2,8 @@
 
 #include "lib.h"
 #include "istream.h"
-#include "istream-concat.h"
 #include "str.h"
-#include "istream-sized.h"
-#include "istream-base64-encoder.h"
+#include "istream-attachment-connector.h"
 #include "dbox-file.h"
 #include "dbox-save.h"
 #include "dbox-attachment.h"
@@ -143,13 +141,12 @@
 				     const char **error_r)
 {
 	ARRAY_TYPE(mail_attachment_extref) extrefs_arr;
-	ARRAY_DEFINE(streams, struct istream *);
 	const struct mail_attachment_extref *extref;
-	struct istream **inputs, *input, *input2;
+	struct istream_attachment_connector *conn;
+	struct istream *input;
 	const char *path, *path_suffix;
-	uoff_t psize, last_voffset = 0;
-	unsigned int i;
-	int ret = 1;
+	uoff_t msg_size;
+	int ret;
 
 	*error_r = NULL;
 
@@ -159,69 +156,30 @@
 		*error_r = "Broken ext-refs string";
 		return 0;
 	}
-	psize = dbox_file_get_plaintext_size(file);
+	msg_size = dbox_file_get_plaintext_size(file);
+	conn = istream_attachment_connector_begin(*stream, msg_size);
 
-	t_array_init(&streams, 8);
+	path_suffix = file->storage->v.get_attachment_path_suffix(file);
 	array_foreach(&extrefs_arr, extref) {
-		path_suffix = file->storage->v.get_attachment_path_suffix(file);
 		path = t_strdup_printf("%s/%s%s", file->storage->attachment_dir,
 				       extref->path, path_suffix);
+		input = i_stream_create_file(path, IO_BLOCK_SIZE);
 
-		if (extref->start_offset != last_voffset) {
-			uoff_t part_size = extref->start_offset - last_voffset;
-
-			if ((*stream)->v_offset + part_size > psize) {
-				*error_r = t_strdup_printf(
-					"ext-refs point outside message "
-					"(%"PRIuUOFF_T" + %"PRIuUOFF_T" > %"PRIuUOFF_T")",
-					(*stream)->v_offset, part_size, psize);
-				ret = 0;
-			}
-
-			input = i_stream_create_limit(*stream, part_size);
-			array_append(&streams, &input, 1);
-			i_stream_seek(*stream, (*stream)->v_offset + part_size);
-			last_voffset += part_size;
-		}
-
-		last_voffset += extref->size;
-		input2 = i_stream_create_file(path, IO_BLOCK_SIZE);
-
-		if (extref->base64_blocks_per_line > 0) {
-			input = i_stream_create_base64_encoder(input2,
-					extref->base64_blocks_per_line*4,
-					extref->base64_have_crlf);
-			i_stream_unref(&input2);
-			input2 = input;
-		}
-
-		input = i_stream_create_sized(input2, extref->size);
-		i_stream_unref(&input2);
-		array_append(&streams, &input, 1);
-	}
-
-	if (psize != (*stream)->v_offset) {
-		if ((*stream)->v_offset > psize) {
-			*error_r = t_strdup_printf(
-				"ext-refs point outside message "
-				"(%"PRIuUOFF_T" > %"PRIuUOFF_T")",
-				(*stream)->v_offset, psize);
-			ret = 0;
-		} else {
-			uoff_t trailer_size = psize - last_voffset;
-
-			input = i_stream_create_limit(*stream, trailer_size);
-			array_append(&streams, &input, 1);
-			array_append_zero(&streams);
+		ret = istream_attachment_connector_add(conn, input,
+					extref->start_offset, extref->size,
+					extref->base64_blocks_per_line,
+					extref->base64_have_crlf, error_r);
+		i_stream_unref(&input);
+		if (ret < 0) {
+			istream_attachment_connector_abort(&conn);
+			return 0;
 		}
 	}
 
-	inputs = array_idx_modifiable(&streams, 0);
+	input = istream_attachment_connector_finish(&conn);
 	i_stream_unref(stream);
-	*stream = i_stream_create_concat(inputs);
-	for (i = 0; inputs[i] != NULL; i++)
-		i_stream_unref(&inputs[i]);
-	return ret;
+	*stream = input;
+	return 1;
 }
 
 int dbox_attachment_file_get_stream(struct dbox_file *file,
diff -r ffab35ef2e5b -r 38b0986605a6 src/lib-storage/index/index-attachment.c
--- a/src/lib-storage/index/index-attachment.c	Fri Jun 29 08:00:19 2012 +0300
+++ b/src/lib-storage/index/index-attachment.c	Fri Jun 29 08:01:08 2012 +0300
@@ -10,57 +10,17 @@
 #include "str.h"
 #include "message-parser.h"
 #include "rfc822-parser.h"
+#include "istream-attachment-extractor.h"
 #include "mail-user.h"
 #include "index-mail.h"
 #include "index-attachment.h"
 
-#define BASE64_ATTACHMENT_MAX_EXTRA_BYTES 1024
-
-enum mail_attachment_state {
-	MAIL_ATTACHMENT_STATE_NO,
-	MAIL_ATTACHMENT_STATE_MAYBE,
-	MAIL_ATTACHMENT_STATE_YES
-};
-
-enum base64_state {
-	BASE64_STATE_0 = 0,
-	BASE64_STATE_1,
-	BASE64_STATE_2,
-	BASE64_STATE_3,
-	BASE64_STATE_CR,
-	BASE64_STATE_EOB,
-	BASE64_STATE_EOM
-};
-
-struct mail_save_attachment_part {
-	char *content_type, *content_disposition;
-	enum mail_attachment_state state;
-	/* start offset of the message part in the original input stream */
-	uoff_t start_offset;
-
-	/* for saving attachments base64-decoded: */
-	enum base64_state base64_state;
-	unsigned int base64_line_blocks, cur_base64_blocks;
-	uoff_t base64_bytes;
-	bool base64_have_crlf; /* CRLF linefeeds */
-	bool base64_failed;
-
-	int temp_fd;
-	struct ostream *output;
-	struct hash_format *part_hash;
-	buffer_t *part_buf;
-};
-
 struct mail_save_attachment {
 	pool_t pool;
-	struct message_parser_ctx *parser;
 	struct fs *fs;
 	struct istream *input;
 
-	/* per-MIME part data */
-	struct mail_save_attachment_part part;
-	struct message_part *prev_part;
-
+	struct fs_file *cur_file;
 	ARRAY_TYPE(mail_attachment_extref) extrefs;
 };
 
@@ -70,102 +30,25 @@
 				     storage->set->mail_attachment_dir);
 }
 
-void index_attachment_save_begin(struct mail_save_context *ctx,
-				 struct fs *fs, struct istream *input)
+static bool index_attachment_want(const struct istream_attachment_header *hdr,
+				  void *context)
 {
-	struct mail_storage *storage = ctx->transaction->box->storage;
-	pool_t pool;
+	struct mail_save_context *ctx = context;
+	struct mail_attachment_part apart;
 
-	i_assert(ctx->attach == NULL);
+	memset(&apart, 0, sizeof(apart));
+	apart.part = hdr->part;
+	apart.content_type = hdr->content_type;
+	apart.content_disposition = hdr->content_disposition;
 
-	if (*storage->set->mail_attachment_dir == '\0')
-		return;
-
-	pool = pool_alloconly_create("save attachment", 1024*4);
-	ctx->attach = p_new(pool, struct mail_save_attachment, 1);
-	ctx->attach->pool = pool;
-	ctx->attach->fs = fs;
-	ctx->attach->input = input;
-	ctx->attach->parser =
-		message_parser_init(ctx->attach->pool, input, 0, 0);
-	p_array_init(&ctx->attach->extrefs, ctx->attach->pool, 8);
+	return ctx->part_is_attachment == NULL ? TRUE :
+		ctx->part_is_attachment(ctx, &apart);
 }
 
-static void parse_content_type(struct mail_save_context *ctx,
-			       const struct message_header_line *hdr)
+static int index_attachment_open_temp_fd(void *context)
 {
-	struct rfc822_parser_context parser;
-	string_t *content_type;
-
-	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
-	rfc822_skip_lwsp(&parser);
-
-	T_BEGIN {
-		content_type = t_str_new(64);
-		if (rfc822_parse_content_type(&parser, content_type) >= 0) {
-			i_free(ctx->attach->part.content_type);
-			ctx->attach->part.content_type =
-				i_strdup(str_c(content_type));
-		}
-	} T_END;
-}
-
-static void
-parse_content_disposition(struct mail_save_context *ctx,
-			  const struct message_header_line *hdr)
-{
-	/* just pass it as-is to backend. */
-	i_free(ctx->attach->part.content_disposition);
-	ctx->attach->part.content_disposition =
-		i_strndup(hdr->full_value, hdr->full_value_len);
-}
-
-static void index_attachment_save_mail_header(struct mail_save_context *ctx,
-					      struct message_header_line *hdr)
-{
-	if (hdr->continues) {
-		hdr->use_full_value = TRUE;
-		return;
-	}
-
-	if (strcasecmp(hdr->name, "Content-Type") == 0)
-		parse_content_type(ctx, hdr);
-	else if (strcasecmp(hdr->name, "Content-Disposition") == 0)
-		parse_content_disposition(ctx, hdr);
-
-	o_stream_nsend(ctx->output, hdr->name, hdr->name_len);
-	o_stream_nsend(ctx->output, hdr->middle, hdr->middle_len);
-	o_stream_nsend(ctx->output, hdr->full_value, hdr->full_value_len);
-	if (!hdr->no_newline) {
-		if (hdr->crlf_newline)
-			o_stream_nsend(ctx->output, "\r\n", 2);
-		else
-			o_stream_nsend(ctx->output, "\n", 1);
-	}
-}
-
-static bool save_is_attachment(struct mail_save_context *ctx,
-			       struct message_part *part)
-{
-	struct mail_attachment_part apart;
-
-	if ((part->flags & MESSAGE_PART_FLAG_MULTIPART) != 0) {
-		/* multiparts may contain attachments as children,
-		   but they're never themselves */
-		return FALSE;
-	}
-	if (ctx->part_is_attachment == NULL)
-		return TRUE;
-
-	memset(&apart, 0, sizeof(apart));
-	apart.part = part;
-	apart.content_type = ctx->attach->part.content_type;
-	apart.content_disposition = ctx->attach->part.content_disposition;
-	return ctx->part_is_attachment(ctx, &apart);
-}
-
-static int index_attachment_save_temp_open_fd(struct mail_storage *storage)
-{
+	struct mail_save_context *ctx = context;
+	struct mail_storage *storage = ctx->transaction->box->storage;
 	string_t *temp_path;
 	int fd;
 
@@ -186,203 +69,22 @@
 	return fd;
 }


More information about the dovecot-cvs mailing list