]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: mail - Group binary part properties into a struct for mail_get_binary_st...
authorStephan Bosch <stephan.bosch@open-xchange.com>
Mon, 8 May 2023 23:04:45 +0000 (01:04 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 20 Feb 2024 06:51:29 +0000 (06:51 +0000)
This makes several additional properties available from
mail_get_binary_stream(). This also changes mail_get_binary_size() into
mail_get_binary_properties().

src/lib-imap-storage/imap-msgpart.c
src/lib-storage/fail-mail.c
src/lib-storage/index/index-mail-binary.c
src/lib-storage/index/index-mail.h
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.h
src/lib-storage/mail.c
src/lib-storage/test-mail.c
src/plugins/virtual/virtual-mail.c

index 35f9a4cd697bea61d68553f01ddc75bef3163294..c6c5d639ea044e19c9dfd14eccc452006a010928 100644 (file)
@@ -12,6 +12,7 @@
 #include "ostream.h"
 #include "message-parser.h"
 #include "message-decoder.h"
+#include "message-part-data.h"
 #include "mail-storage-private.h"
 #include "mail-namespace.h"
 #include "imap-bodystructure.h"
@@ -673,6 +674,7 @@ int imap_msgpart_open(struct mail *mail, struct imap_msgpart *msgpart,
        struct message_part *part;
        uoff_t virtual_size;
        bool include_hdr, binary, use_partial_cache, have_crlfs;
+       struct mail_binary_properties bprops;
        int ret;
 
        i_zero(result_r);
@@ -696,9 +698,10 @@ int imap_msgpart_open(struct mail *mail, struct imap_msgpart *msgpart,
                                return -1;
                }
                if (mail_get_binary_stream(mail, part, include_hdr,
-                                          &virtual_size, &binary,
-                                          &result_r->input) < 0)
+                                          &bprops, &result_r->input) < 0)
                        return -1;
+               virtual_size = bprops.size;
+               binary = bprops.binary;
                have_crlfs = TRUE;
                use_partial_cache = FALSE;
        } else {
@@ -723,7 +726,7 @@ int imap_msgpart_size(struct mail *mail, struct imap_msgpart *msgpart,
        struct imap_msgpart_open_result result;
        struct message_part *part;
        bool include_hdr;
-       unsigned int lines;
+       struct mail_binary_properties bprops;
        int ret;
 
        if (!msgpart->decode_cte_to_binary ||
@@ -751,7 +754,10 @@ int imap_msgpart_size(struct mail *mail, struct imap_msgpart *msgpart,
                        return -1;
        }
        include_hdr = msgpart->fetch_type == FETCH_FULL;
-       return mail_get_binary_size(mail, part, include_hdr, size_r, &lines);
+       if (mail_get_binary_properties(mail, part, include_hdr, &bprops) < 0)
+               return -1;
+       *size_r = bprops.size;
+       return 0;
 }
 
 static int
@@ -785,16 +791,15 @@ imap_msgpart_vsizes_to_binary(struct mail *mail, const struct message_part *part
                              struct message_part **binpart_r)
 {
        struct message_part **pos;
-       uoff_t size;
-       unsigned int lines;
+       struct mail_binary_properties bprops;
 
-       if (mail_get_binary_size(mail, part, FALSE, &size, &lines) < 0)
+       if (mail_get_binary_properties(mail, part, FALSE, &bprops) < 0)
                return -1;
 
        *binpart_r = t_new(struct message_part, 1);
        **binpart_r = *part;
-       (*binpart_r)->body_size.virtual_size = size;
-       (*binpart_r)->body_size.lines = lines;
+       (*binpart_r)->body_size.virtual_size = bprops.size;
+       (*binpart_r)->body_size.lines = bprops.lines;
 
        pos = &(*binpart_r)->children;
        for (part = part->children; part != NULL; part = part->next) {
index f236d76b38695e19c6f7fe0666274c7a342b01df..376486210a9a8cf63ba3ecd9d94ec38e1180e218 100644 (file)
@@ -179,9 +179,7 @@ static int
 fail_mail_get_binary_stream(struct mail *_mail ATTR_UNUSED,
                            const struct message_part *part ATTR_UNUSED,
                            bool include_hdr ATTR_UNUSED,
-                           uoff_t *size_r ATTR_UNUSED,
-                           unsigned int *body_lines_r ATTR_UNUSED,
-                           bool *binary_r ATTR_UNUSED,
+                           struct mail_binary_properties *bprops_r ATTR_UNUSED,
                            struct istream **stream_r ATTR_UNUSED)
 {
        return -1;
index decc486f4c90353d0285fa14f5da0797250d37fb..9dfed154b8f829b6db83e1f1225c8531ec6ed628 100644 (file)
@@ -479,9 +479,10 @@ msg_part_find(struct message_part *parts, uoff_t physical_pos)
 }
 
 static int
-index_mail_get_binary_size(struct mail *_mail,
-                          const struct message_part *part, bool include_hdr,
-                          uoff_t *size_r, unsigned int *lines_r)
+index_mail_get_binary_properties(struct mail *_mail,
+                                const struct message_part *part,
+                                bool include_hdr,
+                                struct mail_binary_properties *bprops_r)
 {
        struct index_mail *mail = INDEX_MAIL(_mail);
        struct message_part *all_parts, *msg_part;
@@ -494,7 +495,10 @@ index_mail_get_binary_size(struct mail *_mail,
                return -1;
 
        /* first lookup from cache */
-       if (!get_cached_binary_parts(mail)) {
+       if (get_cached_binary_parts(mail)) {
+               converted = (mail->data.bin_parts != NULL);
+               binary = converted || message_parts_have_nuls(all_parts);
+       } else {
                /* not found. parse the whole message */
                if (index_mail_read_binary_to_cache(_mail, all_parts, TRUE,
                                                    "binary.size", &binary, &converted) < 0)
@@ -539,15 +543,20 @@ index_mail_get_binary_size(struct mail *_mail,
                        size -= part->header_size.virtual_size;
                lines -= part->header_size.lines;
        }
-       *size_r = size;
-       *lines_r = lines;
+
+       if (bprops_r != NULL) {
+               bprops_r->size = size;
+               bprops_r->lines = lines;
+               bprops_r->binary = binary;
+               bprops_r->converted = converted;
+       }
        return 0;
 }
 
 int index_mail_get_binary_stream(struct mail *_mail,
                                 const struct message_part *part,
-                                bool include_hdr, uoff_t *size_r,
-                                unsigned int *lines_r, bool *binary_r,
+                                bool include_hdr,
+                                struct mail_binary_properties *bprops_r,
                                 struct istream **stream_r)
 {
        struct index_mail *mail = INDEX_MAIL(_mail);
@@ -556,12 +565,9 @@ int index_mail_get_binary_stream(struct mail *_mail,
        bool binary, converted;
 
        if (stream_r == NULL) {
-               return index_mail_get_binary_size(_mail, part, include_hdr,
-                                                 size_r, lines_r);
+               return index_mail_get_binary_properties(_mail, part,
+                                                       include_hdr, bprops_r);
        }
-       /* current implementation doesn't bother implementing this,
-          because it's not needed by anything. */
-       i_assert(lines_r == NULL);
 
        /* FIXME: always put the header to temp file. skip it when needed. */
        if (cache->box == _mail->box && cache->uid == _mail->uid &&
@@ -578,8 +584,14 @@ int index_mail_get_binary_stream(struct mail *_mail,
                        return -1;
                mail->data.cache_fetch_fields |= MAIL_FETCH_STREAM_BINARY;
        }
-       *size_r = cache->size;
-       *binary_r = binary;
+       if (bprops_r != NULL) {
+               bprops_r->size = cache->size;
+               /* FIXME: lines is a bit complex to calculate in this code path,
+                  and current callers don't need it either. */
+               bprops_r->lines = UINT_MAX;
+               bprops_r->binary = binary;
+               bprops_r->converted = converted;
+       }
        if (!converted) {
                /* don't keep this cached. it's exactly the same as
                   the original stream */
@@ -588,7 +600,7 @@ int index_mail_get_binary_stream(struct mail *_mail,
                              (include_hdr ? 0 :
                               part->header_size.physical_size));
                input = i_stream_create_crlf(mail->data.stream);
-               *stream_r = i_stream_create_limit(input, *size_r);
+               *stream_r = i_stream_create_limit(input, cache->size);
                i_stream_unref(&input);
                mail_storage_free_binary_cache(_mail->box->storage);
        } else {
index b06e07da57672f3aad29be61c604c0e989ece47a..9e2159898e9820bc079f473016b19b401ec4e826 100644 (file)
@@ -236,8 +236,8 @@ int index_mail_init_stream(struct index_mail *mail,
                           struct istream **stream_r) ATTR_NULL(2, 3);
 int index_mail_get_binary_stream(struct mail *_mail,
                                 const struct message_part *part,
-                                bool include_hdr, uoff_t *size_r,
-                                unsigned int *body_lines_r, bool *binary_r,
+                                bool include_hdr,
+                                struct mail_binary_properties *bprops_r,
                                 struct istream **stream_r);
 int index_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
                           const char **value_r);
index 0cbdf4c48ab15651e6c0ea28dd3f547ac3bd41d8..76615f8bf7be38b03322b80c839a8ea719e8d03b 100644 (file)
@@ -554,10 +554,10 @@ struct mail_vfuncs {
                          struct message_size *hdr_size,
                          struct message_size *body_size,
                          struct istream **stream_r);
-       int (*get_binary_stream)(struct mail *mail,
+       int (*get_binary_stream)(struct mail *_mail,
                                 const struct message_part *part,
-                                bool include_hdr, uoff_t *size_r,
-                                unsigned int *lines_r, bool *binary_r,
+                                bool include_hdr,
+                                struct mail_binary_properties *bprops_r,
                                 struct istream **stream_r);
 
        int (*get_special)(struct mail *mail, enum mail_fetch_field field,
index af050bb0ffa71d8c4abace6c8ed98dada6dc5b47..3b10a1356d6aba9e4ce9c74b0ece31860f6e2bf8 100644 (file)
@@ -398,6 +398,14 @@ enum mail_access_type {
        MAIL_ACCESS_TYPE_SORT,
 };
 
+struct mail_binary_properties {
+       uoff_t size;
+       unsigned int lines;
+
+       bool binary;
+       bool converted;
+};
+
 struct mail {
        /* always set */
        struct mailbox *box;
@@ -994,13 +1002,14 @@ int mail_get_hdr_stream_because(struct mail *mail,
    children are returned decoded. Note that the returned stream must be
    unreferenced, unlike mail_get_*stream*() which automatically free it. */
 int mail_get_binary_stream(struct mail *mail, const struct message_part *part,
-                          bool include_hdr, uoff_t *size_r,
-                          bool *binary_r, struct istream **stream_r);
-/* Like mail_get_binary_stream(), but only return the size. */
-int mail_get_binary_size(struct mail *mail, const struct message_part *part,
-                        bool include_hdr, uoff_t *size_r,
-                        unsigned int *lines_r);
-
+                          bool include_hdr,
+                          struct mail_binary_properties *bprops_r,
+                          struct istream **stream_r);
+/* Like mail_get_binary_stream(), but only return the properties. */
+int mail_get_binary_properties(struct mail *mail,
+                              const struct message_part *part,
+                              bool include_hdr,
+                              struct mail_binary_properties *bprops_r);
 /* Get any of the "special" fields. Unhandled specials are returned as "". */
 int mail_get_special(struct mail *mail, enum mail_fetch_field field,
                     const char **value_r);
index 3b2284e907286ea677ab3a95b1e5954c36e79f49..8bd4e83e93ca8060fd70f718a501dc291835a4c8 100644 (file)
@@ -387,35 +387,42 @@ int mail_get_hdr_stream_because(struct mail *mail,
 }
 
 int mail_get_binary_stream(struct mail *mail, const struct message_part *part,
-                          bool include_hdr, uoff_t *size_r,
-                          bool *binary_r, struct istream **stream_r)
+                          bool include_hdr,
+                          struct mail_binary_properties *bprops_r,
+                          struct istream **stream_r)
 {
        struct mail_private *p = (struct mail_private *)mail;
        int ret;
 
+       if (bprops_r != NULL)
+               i_zero(bprops_r);
+
        if (mail->lookup_abort != MAIL_LOOKUP_ABORT_NEVER) {
                mail_set_aborted(mail);
                return -1;
        }
        T_BEGIN {
                ret = p->v.get_binary_stream(mail, part, include_hdr,
-                                            size_r, NULL, binary_r, stream_r);
+                                            bprops_r, stream_r);
        } T_END;
        i_assert(ret < 0 || (*stream_r)->blocking);
        return ret;
 }
 
-int mail_get_binary_size(struct mail *mail, const struct message_part *part,
-                        bool include_hdr, uoff_t *size_r,
-                        unsigned int *lines_r)
+int mail_get_binary_properties(struct mail *mail,
+                              const struct message_part *part,
+                              bool include_hdr,
+                              struct mail_binary_properties *bprops_r)
 {
        struct mail_private *p = (struct mail_private *)mail;
-       bool binary;
        int ret;
 
+       if (bprops_r != NULL)
+               i_zero(bprops_r);
+
        T_BEGIN {
                ret = p->v.get_binary_stream(mail, part, include_hdr,
-                                            size_r, lines_r, &binary, NULL);
+                                            bprops_r, NULL);
        } T_END;
        return ret;
 }
index fff9997051339112cd9f4d2865cd1f5e54f1be4e..718684d8a5c0f0e15cea4f7bf4ca9da5a2d65c29 100644 (file)
@@ -109,8 +109,7 @@ test_mail_fetch_field(struct mail *mail, enum mail_fetch_field field)
        const char *str;
        time_t t;
        uoff_t size;
-       unsigned int lines;
-       bool binary;
+       struct mail_binary_properties bprops;
        int tz, ret = 0;
 
        e_debug(test_event, "field=0x%x", field);
@@ -156,13 +155,13 @@ test_mail_fetch_field(struct mail *mail, enum mail_fetch_field field)
                if (i_rand_limit(2) == 0) {
                        ret = mail_get_binary_stream(mail, parts,
                                                     i_rand_limit(2) == 0,
-                                                    &size, &binary, &input);
+                                                    &bprops, &input);
                        if (ret == 0)
                                i_stream_unref(&input);
                } else {
-                       ret = mail_get_binary_size(mail, parts,
-                                                  i_rand_limit(2) == 0,
-                                                  &size, &lines);
+                       ret = mail_get_binary_properties(mail, parts,
+                                                        i_rand_limit(2) == 0,
+                                                        &bprops);
                }
                break;
        case MAIL_FETCH_IMAP_BODY:
index 7afb932d4ab22151ccf9d39ff38b6e97ce0f01f6..7eefcf31426863ff28800f80f8bb016bae7b93e5 100644 (file)
@@ -474,8 +474,8 @@ virtual_mail_get_stream(struct mail *mail, bool get_body,
 static int
 virtual_mail_get_binary_stream(struct mail *mail,
                               const struct message_part *part,
-                              bool include_hdr, uoff_t *size_r,
-                              unsigned int *lines_r, bool *binary_r,
+                              bool include_hdr,
+                              struct mail_binary_properties *bprops_r,
                               struct istream **stream_r)
 {
        struct virtual_mail *vmail = virtual_mail_container_of(mail);
@@ -487,7 +487,7 @@ virtual_mail_get_binary_stream(struct mail *mail,
        struct mail_private *p =
                container_of(backend_mail, struct mail_private, mail);
        if (p->v.get_binary_stream(backend_mail, part, include_hdr,
-                                  size_r, lines_r, binary_r, stream_r) < 0) {
+                                  bprops_r, stream_r) < 0) {
                virtual_box_copy_error(mail->box, backend_mail->box);
                return -1;
        }