dovecot-2.0: lib-storage: Most of the attachment saving code is ...

dovecot at dovecot.org dovecot at dovecot.org
Sat Oct 2 14:33:56 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/8f724333db7f
changeset: 12241:8f724333db7f
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Aug 05 20:35:21 2010 +0100
description:
lib-storage: Most of the attachment saving code is no longer dbox-specific.

diffstat:

 src/lib-storage/index/Makefile.am                   |    3 +
 src/lib-storage/index/cydir/cydir-storage.c         |    1 +
 src/lib-storage/index/dbox-common/dbox-attachment.c |  421 +---------------------
 src/lib-storage/index/dbox-common/dbox-attachment.h |   21 +-
 src/lib-storage/index/dbox-common/dbox-save.c       |   15 +-
 src/lib-storage/index/dbox-common/dbox-save.h       |   26 -
 src/lib-storage/index/dbox-common/dbox-storage.h    |    3 -
 src/lib-storage/index/dbox-multi/mdbox-purge.c      |   14 +-
 src/lib-storage/index/dbox-multi/mdbox-storage.c    |    4 +-
 src/lib-storage/index/dbox-single/sdbox-storage.c   |    4 +-
 src/lib-storage/index/dbox-single/sdbox-sync.c      |   10 +-
 src/lib-storage/index/index-attachment.c            |  443 ++++++++++++++++++++++++
 src/lib-storage/index/index-attachment.h            |   32 +
 src/lib-storage/index/index-storage.c               |    2 +
 src/lib-storage/index/maildir/maildir-storage.c     |    1 +
 src/lib-storage/index/mbox/mbox-storage.c           |    1 +
 src/lib-storage/index/raw/raw-storage.c             |    1 +
 src/lib-storage/mail-storage-private.h              |    5 +
 src/lib-storage/test-mailbox.c                      |    1 +
 src/plugins/virtual/virtual-storage.c               |    1 +
 20 files changed, 552 insertions(+), 457 deletions(-)

diffs (truncated from 1365 to 300 lines):

diff -r 8da1cfdb7932 -r 8f724333db7f src/lib-storage/index/Makefile.am
--- a/src/lib-storage/index/Makefile.am	Thu Aug 05 19:34:51 2010 +0100
+++ b/src/lib-storage/index/Makefile.am	Thu Aug 05 20:35:21 2010 +0100
@@ -5,6 +5,7 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-test \
+	-I$(top_srcdir)/src/lib-fs \
 	-I$(top_srcdir)/src/lib-mail \
 	-I$(top_srcdir)/src/lib-imap \
 	-I$(top_srcdir)/src/lib-index \
@@ -12,6 +13,7 @@
 
 libstorage_index_la_SOURCES = \
 	istream-mail-stats.c \
+	index-attachment.c \
 	index-fetch.c \
 	index-mail.c \
 	index-mail-headers.c \
@@ -35,6 +37,7 @@
 
 headers = \
 	istream-mail-stats.h \
+	index-attachment.h \
 	index-mail.h \
 	index-search-result.h \
 	index-sort.h \
diff -r 8da1cfdb7932 -r 8f724333db7f src/lib-storage/index/cydir/cydir-storage.c
--- a/src/lib-storage/index/cydir/cydir-storage.c	Thu Aug 05 19:34:51 2010 +0100
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Thu Aug 05 20:35:21 2010 +0100
@@ -179,6 +179,7 @@
 		cydir_save_finish,
 		cydir_save_cancel,
 		mail_storage_copy,
+		NULL,
 		index_storage_is_inconsistent
 	}
 };
diff -r 8da1cfdb7932 -r 8f724333db7f src/lib-storage/index/dbox-common/dbox-attachment.c
--- a/src/lib-storage/index/dbox-common/dbox-attachment.c	Thu Aug 05 19:34:51 2010 +0100
+++ b/src/lib-storage/index/dbox-common/dbox-attachment.c	Thu Aug 05 20:35:21 2010 +0100
@@ -1,370 +1,42 @@
 /* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "safe-mkstemp.h"
-#include "fs-api.h"
 #include "istream.h"
 #include "istream-concat.h"
-#include "ostream.h"
-#include "sha1.h"
-#include "hex-binary.h"
 #include "str.h"
-#include "message-parser.h"
-#include "rfc822-parser.h"
-#include "mail-user.h"
-#include "index-mail.h"
 #include "dbox-file.h"
 #include "dbox-save.h"
 #include "dbox-attachment.h"
 
-void dbox_attachment_save_begin(struct dbox_save_context *ctx)
+void dbox_attachment_save_write_metadata(struct mail_save_context *ctx,
+					 string_t *str)
 {
-	struct dbox_storage *storage =
-		(struct dbox_storage *)ctx->ctx.transaction->box->storage;
+	const ARRAY_TYPE(mail_attachment_extref) *extrefs;
+	const struct mail_attachment_extref *extref;
+	bool add_space = FALSE;
 
-	if (*storage->attachment_dir == '\0')
+	extrefs = index_attachment_save_get_extrefs(ctx);
+	if (extrefs == NULL || array_count(extrefs) == 0)
 		return;
 
-	ctx->attach.parser = message_parser_init(default_pool,
-						 ctx->input, 0, 0);
-}
-
-static void dbox_parse_content_type(struct dbox_save_context *ctx,
-				    const struct message_header_line *hdr)
-{
-	struct rfc822_parser_context parser;
-	string_t *content_type;
-
-	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
-	(void)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.content_type);
-			ctx->attach.content_type = i_strdup(str_c(content_type));
-		}
-	} T_END;
-}
-
-static void
-dbox_parse_content_disposition(struct dbox_save_context *ctx,
-			       const struct message_header_line *hdr)
-{
-	/* just pass it as-is to backend. */
-	i_free(ctx->attach.content_disposition);
-	ctx->attach.content_disposition =
-		i_strndup(hdr->full_value, hdr->full_value_len);
-}
-
-static void dbox_save_mail_header(struct dbox_save_context *ctx,
-				  struct message_header_line *hdr)
-{
-	if (hdr->continues) {
-		hdr->use_full_value = TRUE;
-		return;
+	str_append_c(str, DBOX_METADATA_EXT_REF);
+	array_foreach(extrefs, extref) {
+		if (!add_space)
+			add_space = TRUE;
+		else
+			str_append_c(str, ' ');
+		str_printfa(str, "%"PRIuUOFF_T" %"PRIuUOFF_T" %s",
+			    extref->start_offset, extref->size, extref->path);
+		str_append(str, extref->path);
 	}
-
-	if (strcasecmp(hdr->name, "Content-Type") == 0)
-		dbox_parse_content_type(ctx, hdr);
-	else if (strcasecmp(hdr->name, "Content-Disposition") == 0)
-		dbox_parse_content_disposition(ctx, hdr);
-
-	o_stream_send(ctx->ctx.output, hdr->name, hdr->name_len);
-	o_stream_send(ctx->ctx.output, hdr->middle, hdr->middle_len);
-	o_stream_send(ctx->ctx.output, hdr->full_value, hdr->full_value_len);
-	if (!hdr->no_newline) {
-		if (hdr->crlf_newline)
-			o_stream_send(ctx->ctx.output, "\r\n", 2);
-		else
-			o_stream_send(ctx->ctx.output, "\n", 1);
-	}
-}
-
-static bool dbox_save_is_attachment(struct dbox_save_context *ctx,
-				    struct message_part *part)
-{
-	struct dbox_storage *storage =
-		(struct dbox_storage *)ctx->ctx.transaction->box->storage;
-
-	if ((part->flags & MESSAGE_PART_FLAG_MULTIPART) != 0) {
-		/* multiparts may contain attachments as children,
-		   but they're never themselves */
-		return FALSE;
-	}
-	if (storage->v.save_is_attachment == NULL)
-		return TRUE;
-	else
-		return storage->v.save_is_attachment(ctx, part);
-}
-
-static int dbox_save_attachment_temp_open(struct dbox_save_context *ctx)
-{
-	struct mail_storage *storage = ctx->ctx.transaction->box->storage;
-	string_t *temp_path;
-	int fd;
-
-	temp_path = t_str_new(256);
-	mail_user_set_get_temp_prefix(temp_path, storage->user->set);
-	fd = safe_mkstemp_hostpid(temp_path, 0600, (uid_t)-1, (gid_t)-1);
-	if (fd == -1) {
-		mail_storage_set_critical(storage,
-			"safe_mkstemp(%s) failed: %m", str_c(temp_path));
-		return -1;
-	}
-	if (unlink(str_c(temp_path)) < 0) {
-		mail_storage_set_critical(storage,
-			"unlink(%s) failed: %m", str_c(temp_path));
-		(void)close(fd);
-		return -1;
-	}
-
-	ctx->attach.temp_fd = fd;
-	ctx->attach.output = o_stream_create_fd(fd, 0, FALSE);
-	sha1_init(&ctx->attach.part_hash);
-	return 0;
-}
-
-static int dbox_save_attachment_finish(struct dbox_save_context *ctx)
-{
-	struct dbox_storage *storage =
-		(struct dbox_storage *)ctx->ctx.transaction->box->storage;
-	struct fs_file *file;
-	struct istream *input;
-	struct ostream *output;
-	unsigned char digest[SHA1_RESULTLEN];
-	uint8_t guid_128[MAIL_GUID_128_SIZE];
-	const char *path, *digest_str;
-	const unsigned char *data;
-	size_t size;
-	uoff_t attachment_size;
-	enum fs_open_flags flags = FS_OPEN_FLAG_MKDIR;
-	int ret = 0;
-
-	/* open the attachment destination file */
-	if (storage->storage.set->parsed_fsync_mode != FSYNC_MODE_NEVER)
-		flags |= FS_OPEN_FLAG_FDATASYNC;
-
-	sha1_result(&ctx->attach.part_hash, digest);
-	digest_str = binary_to_hex(digest, sizeof(digest));
-
-	mail_generate_guid_128(guid_128);
-	path = t_strdup_printf("%s/%c%c/%c%c/%s-%s", storage->attachment_dir,
-			       digest_str[0], digest_str[1],
-			       digest_str[2], digest_str[3], digest_str,
-			       mail_guid_128_to_string(guid_128));
-	if (fs_open(storage->attachment_fs, path,
-		    FS_OPEN_MODE_CREATE | flags, &file) < 0) {
-		mail_storage_set_critical(&storage->storage, "%s",
-			fs_last_error(storage->attachment_fs));
-		return -1;
-	}
-
-	/* copy data to it from temp file */
-	input = i_stream_create_fd(ctx->attach.temp_fd, IO_BLOCK_SIZE, FALSE);
-	output = fs_write_stream(file);
-	while (i_stream_read_data(input, &data, &size, 0) > 0) {
-		o_stream_send(output, data, size);
-		i_stream_skip(input, size);
-	}
-
-	if (input->stream_errno != 0) {
-		mail_storage_set_critical(&storage->storage,
-			"read(%s) failed: %m", i_stream_get_name(input));
-		ret = -1;
-	}
-	attachment_size = input->v_offset;
-	i_stream_destroy(&input);
-
-	if (ret < 0)
-		fs_write_stream_abort(file, &output);
-	else if (fs_write_stream_finish(file, &output) < 0) {
-		mail_storage_set_critical(&storage->storage, "%s",
-					  fs_file_last_error(file));
-		ret = -1;
-	}
-	fs_close(&file);
-
-	if (ret == 0) {
-		if (ctx->attach.ext_refs == NULL) {
-			ctx->attach.ext_refs = str_new(default_pool, 256);
-			str_append_c(ctx->attach.ext_refs,
-				     DBOX_METADATA_EXT_REF);
-		} else {
-			str_append_c(ctx->attach.ext_refs, ' ');
-		}
-		str_printfa(ctx->attach.ext_refs,
-			    "%"PRIuUOFF_T" %"PRIuUOFF_T" ",
-			    ctx->attach.start_offset, attachment_size);
-		str_append(ctx->attach.ext_refs,
-			   path + strlen(storage->attachment_dir) + 1);
-	}
-	return ret;
-}
-
-static void dbox_save_body(struct dbox_save_context *ctx,
-			   const struct message_block *block)
-{
-	struct mail_storage *storage = ctx->ctx.transaction->box->storage;
-	buffer_t *part_buf;
-	size_t new_size;
-
-	switch (ctx->attach.state) {
-	case DBOX_ATTACHMENT_STATE_NO:
-		o_stream_send(ctx->ctx.output, block->data, block->size);
-		break;
-	case DBOX_ATTACHMENT_STATE_MAYBE:
-		if (ctx->attach.part_buf == NULL) {
-			ctx->attach.part_buf =
-				buffer_create_dynamic(default_pool,
-					storage->set->mail_attachment_min_size);
-		}
-		part_buf = ctx->attach.part_buf;
-		new_size = part_buf->used + block->size;
-		if (new_size < storage->set->mail_attachment_min_size) {
-			buffer_append(part_buf, block->data, block->size);
-			break;
-		}
-		/* attachment is large enough. we'll first write it to
-		   temp file. */
-		if (dbox_save_attachment_temp_open(ctx) < 0) {
-			/* failed, fallback to just saving it inline */
-			ctx->attach.state = DBOX_ATTACHMENT_STATE_NO;
-			o_stream_send(ctx->ctx.output, part_buf->data,
-				      part_buf->used);
-			o_stream_send(ctx->ctx.output,
-				      block->data, block->size);
-			break;
-		}
-		ctx->attach.state = DBOX_ATTACHMENT_STATE_YES;
-		sha1_loop(&ctx->attach.part_hash, part_buf->data,
-			  part_buf->used);
-		o_stream_send(ctx->attach.output, part_buf->data,


More information about the dovecot-cvs mailing list