From: Stephan Bosch Date: Mon, 8 May 2023 23:04:45 +0000 (+0200) Subject: lib-storage: mail - Group binary part properties into a struct for mail_get_binary_st... X-Git-Tag: 2.4.0~1767 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=10ae3f851fd403f094e5cb37237f7fcccd06cfdd;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: mail - Group binary part properties into a struct for mail_get_binary_stream(). This makes several additional properties available from mail_get_binary_stream(). This also changes mail_get_binary_size() into mail_get_binary_properties(). --- diff --git a/src/lib-imap-storage/imap-msgpart.c b/src/lib-imap-storage/imap-msgpart.c index 35f9a4cd69..c6c5d639ea 100644 --- a/src/lib-imap-storage/imap-msgpart.c +++ b/src/lib-imap-storage/imap-msgpart.c @@ -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) { diff --git a/src/lib-storage/fail-mail.c b/src/lib-storage/fail-mail.c index f236d76b38..376486210a 100644 --- a/src/lib-storage/fail-mail.c +++ b/src/lib-storage/fail-mail.c @@ -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; diff --git a/src/lib-storage/index/index-mail-binary.c b/src/lib-storage/index/index-mail-binary.c index decc486f4c..9dfed154b8 100644 --- a/src/lib-storage/index/index-mail-binary.c +++ b/src/lib-storage/index/index-mail-binary.c @@ -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 { diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h index b06e07da57..9e2159898e 100644 --- a/src/lib-storage/index/index-mail.h +++ b/src/lib-storage/index/index-mail.h @@ -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); diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h index 0cbdf4c48a..76615f8bf7 100644 --- a/src/lib-storage/mail-storage-private.h +++ b/src/lib-storage/mail-storage-private.h @@ -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, diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h index af050bb0ff..3b10a1356d 100644 --- a/src/lib-storage/mail-storage.h +++ b/src/lib-storage/mail-storage.h @@ -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); diff --git a/src/lib-storage/mail.c b/src/lib-storage/mail.c index 3b2284e907..8bd4e83e93 100644 --- a/src/lib-storage/mail.c +++ b/src/lib-storage/mail.c @@ -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; } diff --git a/src/lib-storage/test-mail.c b/src/lib-storage/test-mail.c index fff9997051..718684d8a5 100644 --- a/src/lib-storage/test-mail.c +++ b/src/lib-storage/test-mail.c @@ -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: diff --git a/src/plugins/virtual/virtual-mail.c b/src/plugins/virtual/virtual-mail.c index 7afb932d4a..7eefcf3142 100644 --- a/src/plugins/virtual/virtual-mail.c +++ b/src/plugins/virtual/virtual-mail.c @@ -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; }