#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"
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);
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 {
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 ||
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
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) {
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;
}
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;
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)
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);
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 &&
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 */
(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 {
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);
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,
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;
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);
}
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;
}
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);
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:
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);
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;
}