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