]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Moved more of dbox attachments code to generic code.
authorTimo Sirainen <tss@iki.fi>
Wed, 6 Nov 2013 21:00:58 +0000 (23:00 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 6 Nov 2013 21:00:58 +0000 (23:00 +0200)
src/lib-storage/index/dbox-common/dbox-attachment.c
src/lib-storage/index/dbox-common/dbox-attachment.h
src/lib-storage/index/dbox-multi/mdbox-purge.c
src/lib-storage/index/dbox-single/sdbox-copy.c
src/lib-storage/index/dbox-single/sdbox-file.c
src/lib-storage/index/dbox-single/sdbox-sync.c
src/lib-storage/index/index-attachment.c
src/lib-storage/index/index-attachment.h

index 35a835f61f99401eb3c07b93bf9c22e2301202a6..caa3ee5ca1fcb55b6c9ef34fdbd843568002a33e 100644 (file)
 #include "lib.h"
 #include "istream.h"
 #include "str.h"
-#include "fs-api.h"
-#include "istream-fs-file.h"
-#include "istream-attachment-connector.h"
 #include "dbox-file.h"
 #include "dbox-save.h"
 #include "dbox-attachment.h"
 
-enum dbox_attachment_decode_option {
-       DBOX_ATTACHMENT_DECODE_OPTION_NONE = '-',
-       DBOX_ATTACHMENT_DECODE_OPTION_BASE64 = 'B',
-       DBOX_ATTACHMENT_DECODE_OPTION_CRLF = 'C'
-};
-
 void dbox_attachment_save_write_metadata(struct mail_save_context *ctx,
                                         string_t *str)
 {
        const ARRAY_TYPE(mail_attachment_extref) *extrefs;
-       const struct mail_attachment_extref *extref;
-       bool add_space = FALSE;
-       unsigned int startpos;
 
        extrefs = index_attachment_save_get_extrefs(ctx);
        if (extrefs == NULL || array_count(extrefs) == 0)
                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" ",
-                           extref->start_offset, extref->size);
-
-               startpos = str_len(str);
-               if (extref->base64_have_crlf)
-                       str_append_c(str, DBOX_ATTACHMENT_DECODE_OPTION_CRLF);
-               if (extref->base64_blocks_per_line > 0) {
-                       str_printfa(str, "%c%u",
-                                   DBOX_ATTACHMENT_DECODE_OPTION_BASE64,
-                                   extref->base64_blocks_per_line * 4);
-               }
-               if (startpos == str_len(str)) {
-                       /* make it clear there are no options */
-                       str_append_c(str, DBOX_ATTACHMENT_DECODE_OPTION_NONE);
-               }
-               str_append_c(str, ' ');
-               str_append(str, extref->path);
-       }
+       index_attachment_append_extrefs(str, extrefs);
        str_append_c(str, '\n');
 }
 
-static bool
-parse_extref_decode_options(const char *str,
-                           struct mail_attachment_extref *extref)
-{
-       unsigned int num;
-
-       if (*str == DBOX_ATTACHMENT_DECODE_OPTION_NONE)
-               return str[1] == '\0';
-
-       while (*str != '\0') {
-               switch (*str) {
-               case DBOX_ATTACHMENT_DECODE_OPTION_BASE64:
-                       str++; num = 0;
-                       while (*str >= '0' && *str <= '9') {
-                               num = num*10 + (*str-'0');
-                               str++;
-                       }
-                       if (num == 0 || num % 4 != 0)
-                               return FALSE;
-
-                       extref->base64_blocks_per_line = num/4;
-                       break;
-               case DBOX_ATTACHMENT_DECODE_OPTION_CRLF:
-                       extref->base64_have_crlf = TRUE;
-                       str++;
-                       break;
-               default:
-                       return FALSE;
-               }
-       }
-       return TRUE;
-}
-
-static bool
-dbox_attachment_parse_extref_real(const char *line, pool_t pool,
-                                 ARRAY_TYPE(mail_attachment_extref) *extrefs)
-{
-       struct mail_attachment_extref extref;
-       const char *const *args;
-       unsigned int i, len;
-       uoff_t last_voffset;
-
-       args = t_strsplit(line, " ");
-       len = str_array_length(args);
-       if ((len % 4) != 0)
-               return FALSE;
-
-       last_voffset = 0;
-       for (i = 0; args[i] != NULL; i += 4) {
-               const char *start_offset_str = args[i+0];
-               const char *size_str = args[i+1];
-               const char *decode_options = args[i+2];
-               const char *path = args[i+3];
-
-               memset(&extref, 0, sizeof(extref));
-               if (str_to_uoff(start_offset_str, &extref.start_offset) < 0 ||
-                   str_to_uoff(size_str, &extref.size) < 0 ||
-                   extref.start_offset < last_voffset ||
-                   !parse_extref_decode_options(decode_options, &extref))
-                       return FALSE;
-
-               last_voffset += extref.size +
-                       (extref.start_offset - last_voffset);
-
-               extref.path = p_strdup(pool, path);
-               array_append(extrefs, &extref, 1);
-       }
-       return TRUE;
-}
-
-bool dbox_attachment_parse_extref(const char *line, pool_t pool,
-                                 ARRAY_TYPE(mail_attachment_extref) *extrefs)
-{
-       bool ret;
-
-       T_BEGIN {
-               ret = dbox_attachment_parse_extref_real(line, pool, extrefs);
-       } T_END;
-       return ret;
-}
-
 static int
 dbox_attachment_file_get_stream_from(struct dbox_file *file,
                                     const char *ext_refs,
                                     struct istream **stream,
                                     const char **error_r)
 {
-       ARRAY_TYPE(mail_attachment_extref) extrefs_arr;
-       const struct mail_attachment_extref *extref;
-       struct istream_attachment_connector *conn;
-       struct fs_file *fsfile;
-       struct istream *input;
-       const char *path, *path_suffix;
+       const char *path_suffix;
        uoff_t msg_size;
-       int ret;
-
-       *error_r = NULL;
 
        if (*file->storage->attachment_dir == '\0') {
                mail_storage_set_critical(&file->storage->storage,
@@ -160,37 +37,13 @@ dbox_attachment_file_get_stream_from(struct dbox_file *file,
                return -1;
        }
 
-       t_array_init(&extrefs_arr, 16);
-       if (!dbox_attachment_parse_extref_real(ext_refs, pool_datastack_create(),
-                                              &extrefs_arr)) {
-               *error_r = "Broken ext-refs string";
-               return 0;
-       }
        msg_size = dbox_file_get_plaintext_size(file);
-       conn = istream_attachment_connector_begin(*stream, msg_size);
-
        path_suffix = file->storage->v.get_attachment_path_suffix(file);
-       array_foreach(&extrefs_arr, extref) {
-               path = t_strdup_printf("%s/%s%s", file->storage->attachment_dir,
-                                      extref->path, path_suffix);
-               fsfile = fs_file_init(file->storage->attachment_fs, path,
-                                     FS_OPEN_MODE_READONLY);
-               input = i_stream_create_fs_file(&fsfile, IO_BLOCK_SIZE);
-
-               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;
-               }
-       }
-
-       input = istream_attachment_connector_finish(&conn);
-       i_stream_unref(stream);
-       *stream = input;
+       if (index_attachment_stream_get(file->storage->attachment_fs,
+                                       file->storage->attachment_dir,
+                                       path_suffix, stream, msg_size,
+                                       ext_refs, error_r) < 0)
+               return 0;
        return 1;
 }
 
index 943bdf0ca14393f5b23810cc668d83e8b0102ccd..a90ba541e21f0be4b4fc3fceb12a65d18d0078c1 100644 (file)
@@ -8,10 +8,6 @@ struct dbox_file;
 void dbox_attachment_save_write_metadata(struct mail_save_context *ctx,
                                         string_t *str);
 
-/* Parse DBOX_METADATA_EXT_REF line to given array. Names are allocated
-   from the given pool. */
-bool dbox_attachment_parse_extref(const char *line, pool_t pool,
-                                 ARRAY_TYPE(mail_attachment_extref) *extrefs);
 /* Build a single message body stream out of the current message and all of its
    attachments. */
 int dbox_attachment_file_get_stream(struct dbox_file *file,
index 3c5d9d2a1b1f95c4aad07ebbdf0848020407416c..41decd67ac3cfd256d4ccbccacdffdb739d7f197 100644 (file)
@@ -147,13 +147,13 @@ mdbox_metadata_get_extrefs(struct dbox_file *file, pool_t ext_refs_pool,
                        /* end of metadata */
                        break;
                }
-               if (*line == DBOX_METADATA_EXT_REF) {
-                       if (!dbox_attachment_parse_extref(line+1, ext_refs_pool,
-                                                         extrefs)) {
+               if (*line == DBOX_METADATA_EXT_REF) T_BEGIN {
+                       if (!index_attachment_parse_extrefs(line+1, ext_refs_pool,
+                                                           extrefs)) {
                                i_warning("%s: Ignoring corrupted extref: %s",
                                          file->cur_path, line);
                        }
-               }
+               } T_END;
        }
        i_stream_set_max_buffer_size(file->input, buf_size);
 
index e3fa5540bd9d6d41464a9b4fc8584d8465fbc465..7a1ed3c354deef25e14bf3ec1c93edf98a6fa480 100644 (file)
@@ -40,7 +40,7 @@ sdbox_file_copy_attachments(struct sdbox_file *src_file,
 
        pool = pool_alloconly_create("sdbox attachments copy", 1024);
        p_array_init(&extrefs, pool, 16);
-       if (!dbox_attachment_parse_extref(extrefs_line, pool, &extrefs)) {
+       if (!index_attachment_parse_extrefs(extrefs_line, pool, &extrefs)) {
                mail_storage_set_critical(&dest_storage->storage,
                        "Can't copy %s with corrupted extref metadata: %s",
                        src_file->file.cur_path, extrefs_line);
index b020c6072502c5dcab848c7a85bfced688e0f4ae..a9ba411f57a6f210f7e7e36bf230038d4ca2e926 100644 (file)
@@ -436,7 +436,7 @@ int sdbox_file_unlink_with_attachments(struct sdbox_file *sfile)
 
        pool = pool_alloconly_create("sdbox attachments unlink", 1024);
        p_array_init(&extrefs, pool, 16);
-       if (!dbox_attachment_parse_extref(extrefs_line, pool, &extrefs)) {
+       if (!index_attachment_parse_extrefs(extrefs_line, pool, &extrefs)) {
                i_warning("%s: Ignoring corrupted extref: %s",
                          sfile->file.cur_path, extrefs_line);
                array_clear(&extrefs);
index 9ed7b9f00747e943d2d33b3f944082ff69799935..ab6009e704387d93881cae6593e18c02f27128e7 100644 (file)
@@ -160,8 +160,9 @@ static void dbox_sync_expunge_files(struct sdbox_sync_context *ctx)
        /* NOTE: Index is no longer locked. Multiple processes may be unlinking
           the files at the same time. */
        ctx->mbox->box.tmp_sync_view = ctx->sync_view;
-       array_foreach(&ctx->expunged_uids, uidp)
+       array_foreach(&ctx->expunged_uids, uidp) T_BEGIN {
                dbox_sync_file_expunge(ctx, *uidp);
+       } T_END;
        if (ctx->mbox->box.v.sync_notify != NULL)
                ctx->mbox->box.v.sync_notify(&ctx->mbox->box, 0, 0);
        ctx->mbox->box.tmp_sync_view = NULL;
index 29ca262d6d9efcfe9f4fc602fbb47992f617d553..39503818972f8fa1e6d2071c69a4614b6f1f1158 100644 (file)
 #include "str.h"
 #include "message-parser.h"
 #include "rfc822-parser.h"
+#include "fs-api.h"
+#include "istream-fs-file.h"
+#include "istream-attachment-connector.h"
 #include "istream-attachment-extractor.h"
 #include "mail-user.h"
 #include "index-mail.h"
 #include "index-attachment.h"
 
+enum mail_attachment_decode_option {
+       MAIL_ATTACHMENT_DECODE_OPTION_NONE = '-',
+       MAIL_ATTACHMENT_DECODE_OPTION_BASE64 = 'B',
+       MAIL_ATTACHMENT_DECODE_OPTION_CRLF = 'C'
+};
+
 struct mail_save_attachment {
        pool_t pool;
        struct fs *fs;
@@ -104,7 +113,7 @@ index_attachment_open_ostream(struct istream_attachment_info *info,
                               digest[2], digest[3], digest,
                               guid_128_to_string(guid_128));
        attach->cur_file = fs_file_init(attach->fs, path,
-                                       FS_OPEN_MODE_CREATE | flags);
+                                       FS_OPEN_MODE_REPLACE | flags);
 
        extref = array_append_space(&attach->extrefs);
        extref->start_offset = info->start_offset;
@@ -286,3 +295,150 @@ int index_attachment_delete(struct mail_storage *storage,
        } T_END;
        return ret;
 }
+
+void index_attachment_append_extrefs(string_t *str,
+       const ARRAY_TYPE(mail_attachment_extref) *extrefs)
+{
+       const struct mail_attachment_extref *extref;
+       bool add_space = FALSE;
+       unsigned int startpos;
+
+       array_foreach(extrefs, extref) {
+               if (!add_space)
+                       add_space = TRUE;
+               else
+                       str_append_c(str, ' ');
+               str_printfa(str, "%"PRIuUOFF_T" %"PRIuUOFF_T" ",
+                           extref->start_offset, extref->size);
+
+               startpos = str_len(str);
+               if (extref->base64_have_crlf)
+                       str_append_c(str, MAIL_ATTACHMENT_DECODE_OPTION_CRLF);
+               if (extref->base64_blocks_per_line > 0) {
+                       str_printfa(str, "%c%u",
+                                   MAIL_ATTACHMENT_DECODE_OPTION_BASE64,
+                                   extref->base64_blocks_per_line * 4);
+               }
+               if (startpos == str_len(str)) {
+                       /* make it clear there are no options */
+                       str_append_c(str, MAIL_ATTACHMENT_DECODE_OPTION_NONE);
+               }
+               str_append_c(str, ' ');
+               str_append(str, extref->path);
+       }
+}
+
+static bool
+parse_extref_decode_options(const char *str,
+                           struct mail_attachment_extref *extref)
+{
+       unsigned int num;
+
+       if (*str == MAIL_ATTACHMENT_DECODE_OPTION_NONE)
+               return str[1] == '\0';
+
+       while (*str != '\0') {
+               switch (*str) {
+               case MAIL_ATTACHMENT_DECODE_OPTION_BASE64:
+                       str++; num = 0;
+                       while (*str >= '0' && *str <= '9') {
+                               num = num*10 + (*str-'0');
+                               str++;
+                       }
+                       if (num == 0 || num % 4 != 0)
+                               return FALSE;
+
+                       extref->base64_blocks_per_line = num/4;
+                       break;
+               case MAIL_ATTACHMENT_DECODE_OPTION_CRLF:
+                       extref->base64_have_crlf = TRUE;
+                       str++;
+                       break;
+               default:
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
+
+bool index_attachment_parse_extrefs(const char *line, pool_t pool,
+                                   ARRAY_TYPE(mail_attachment_extref) *extrefs)
+{
+       struct mail_attachment_extref extref;
+       const char *const *args;
+       unsigned int i, len;
+       uoff_t last_voffset;
+
+       args = t_strsplit(line, " ");
+       len = str_array_length(args);
+       if ((len % 4) != 0)
+               return FALSE;
+
+       last_voffset = 0;
+       for (i = 0; args[i] != NULL; i += 4) {
+               const char *start_offset_str = args[i+0];
+               const char *size_str = args[i+1];
+               const char *decode_options = args[i+2];
+               const char *path = args[i+3];
+
+               memset(&extref, 0, sizeof(extref));
+               if (str_to_uoff(start_offset_str, &extref.start_offset) < 0 ||
+                   str_to_uoff(size_str, &extref.size) < 0 ||
+                   extref.start_offset < last_voffset ||
+                   !parse_extref_decode_options(decode_options, &extref))
+                       return FALSE;
+
+               last_voffset += extref.size +
+                       (extref.start_offset - last_voffset);
+
+               extref.path = p_strdup(pool, path);
+               array_append(extrefs, &extref, 1);
+       }
+       return TRUE;
+}
+
+int index_attachment_stream_get(struct fs *fs, const char *attachment_dir,
+                               const char *path_suffix,
+                               struct istream **stream, uoff_t full_size,
+                               const char *ext_refs, const char **error_r)
+{
+       ARRAY_TYPE(mail_attachment_extref) extrefs_arr;
+       const struct mail_attachment_extref *extref;
+       struct istream_attachment_connector *conn;
+       struct istream *input;
+       struct fs_file *file;
+       const char *path;
+       int ret;
+
+       *error_r = NULL;
+
+       t_array_init(&extrefs_arr, 16);
+       if (!index_attachment_parse_extrefs(ext_refs, pool_datastack_create(),
+                                           &extrefs_arr)) {
+               *error_r = "Broken ext-refs string";
+               return -1;
+       }
+       conn = istream_attachment_connector_begin(*stream, full_size);
+
+       array_foreach(&extrefs_arr, extref) {
+               path = t_strdup_printf("%s/%s%s", attachment_dir,
+                                      extref->path, path_suffix);
+               file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
+               input = i_stream_create_fs_file(&file, IO_BLOCK_SIZE);
+
+               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 -1;
+               }
+       }
+
+       input = istream_attachment_connector_finish(&conn);
+       i_stream_unref(stream);
+       *stream = input;
+       return 0;
+}
index 92a4521f1a66eb557386a220196ff90eb24b5ead..a52f158f6b535a321f52ebb3d18c258f0eab58c6 100644 (file)
@@ -37,4 +37,16 @@ index_attachment_save_get_extrefs(struct mail_save_context *ctx);
 int index_attachment_delete(struct mail_storage *storage,
                            struct fs *fs, const char *name);
 
+void index_attachment_append_extrefs(string_t *str,
+       const ARRAY_TYPE(mail_attachment_extref) *extrefs);
+/* Parse extrefs value to given array. Names are allocated from the
+   given pool. */
+bool index_attachment_parse_extrefs(const char *line, pool_t pool,
+                                   ARRAY_TYPE(mail_attachment_extref) *extrefs);
+
+int index_attachment_stream_get(struct fs *fs, const char *attachment_dir,
+                               const char *path_suffix,
+                               struct istream **stream, uoff_t full_size,
+                               const char *ext_refs, const char **error_r);
+
 #endif