dbox-attachment.c revision 4a962dccf2fee41bbfec0475c8dd4387d4608f37
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "istream.h"
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen#include "istream-concat.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream-attachment.h"
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen#include "istream-base64-encoder.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "dbox-file.h"
146f9076cd456ea1e9b3f8536456d9d3c962fadbStephan Bosch#include "dbox-save.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "dbox-attachment.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainenenum dbox_attachment_decode_option {
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen DBOX_ATTACHMENT_DECODE_OPTION_NONE = '-',
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen DBOX_ATTACHMENT_DECODE_OPTION_BASE64 = 'B',
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen DBOX_ATTACHMENT_DECODE_OPTION_CRLF = 'C'
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen};
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainenvoid dbox_attachment_save_write_metadata(struct mail_save_context *ctx,
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainen string_t *str)
1a5573ebc32fae2fe576ec544e1781323c1db609Timo Sirainen{
1a5573ebc32fae2fe576ec544e1781323c1db609Timo Sirainen const ARRAY_TYPE(mail_attachment_extref) *extrefs;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const struct mail_attachment_extref *extref;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen bool add_space = FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen unsigned int startpos;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen extrefs = index_attachment_save_get_extrefs(ctx);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (extrefs == NULL || array_count(extrefs) == 0)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen str_append_c(str, DBOX_METADATA_EXT_REF);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen array_foreach(extrefs, extref) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (!add_space)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen add_space = TRUE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen str_append_c(str, ' ');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(str, "%"PRIuUOFF_T" %"PRIuUOFF_T" ",
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen extref->start_offset, extref->size);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen startpos = str_len(str);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (extref->base64_have_crlf)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append_c(str, DBOX_ATTACHMENT_DECODE_OPTION_CRLF);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (extref->base64_blocks_per_line > 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_printfa(str, "%c%u",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen DBOX_ATTACHMENT_DECODE_OPTION_BASE64,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen extref->base64_blocks_per_line * 4);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (startpos == str_len(str)) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* make it clear there are no options */
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen str_append_c(str, DBOX_ATTACHMENT_DECODE_OPTION_NONE);
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen }
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen str_append_c(str, ' ');
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen str_append(str, extref->path);
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen }
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen str_append_c(str, '\n');
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic bool
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenparse_extref_decode_options(const char *str,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct mail_attachment_extref *extref)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen unsigned int num;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (*str == DBOX_ATTACHMENT_DECODE_OPTION_NONE)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return str[1] == '\0';
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen while (*str != '\0') {
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen switch (*str) {
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen case DBOX_ATTACHMENT_DECODE_OPTION_BASE64:
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen str++; num = 0;
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen while (*str >= '0' && *str <= '9') {
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen num = num*10 + (*str-'0');
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str++;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen if (num == 0 || num % 4 != 0)
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen return FALSE;
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen extref->base64_blocks_per_line = num/4;
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen break;
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen case DBOX_ATTACHMENT_DECODE_OPTION_CRLF:
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen extref->base64_have_crlf = TRUE;
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen str++;
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen break;
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen default:
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen return FALSE;
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen }
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen }
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen return TRUE;
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek}
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipekstatic bool
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainendbox_attachment_parse_extref_real(const char *line, pool_t pool,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen ARRAY_TYPE(mail_attachment_extref) *extrefs)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen{
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen struct mail_attachment_extref extref;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen const char *const *args;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen unsigned int i, len;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen uoff_t last_voffset;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen args = t_strsplit(line, " ");
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen len = str_array_length(args);
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen if ((len % 4) != 0)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen return FALSE;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen last_voffset = 0;
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen for (i = 0; args[i] != NULL; i += 4) {
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen const char *start_offset_str = args[i+0];
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen const char *size_str = args[i+1];
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen const char *decode_options = args[i+2];
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *path = args[i+3];
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen memset(&extref, 0, sizeof(extref));
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (str_to_uoff(start_offset_str, &extref.start_offset) < 0 ||
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen str_to_uoff(size_str, &extref.size) < 0 ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen extref.start_offset < last_voffset ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !parse_extref_decode_options(decode_options, &extref))
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return FALSE;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen last_voffset += extref.size +
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen (extref.start_offset - last_voffset);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen extref.path = p_strdup(pool, path);
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen array_append(extrefs, &extref, 1);
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen }
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen return TRUE;
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen}
7900eb30bac4a46b259522c58362884661483d7cJosef 'Jeff' Sipek
7900eb30bac4a46b259522c58362884661483d7cJosef 'Jeff' Sipekbool dbox_attachment_parse_extref(const char *line, pool_t pool,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen ARRAY_TYPE(mail_attachment_extref) *extrefs)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi bool ret;
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi T_BEGIN {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen ret = dbox_attachment_parse_extref_real(line, pool, extrefs);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen } T_END;
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen return ret;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen}
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainendbox_attachment_file_get_stream_from(struct dbox_file *file,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *ext_refs,
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen struct istream **stream,
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen ARRAY_TYPE(mail_attachment_extref) extrefs_arr;
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen ARRAY_DEFINE(streams, struct istream *);
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen const struct mail_attachment_extref *extref;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen struct istream **inputs, *input, *input2;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen const char *path, *path_suffix;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen uoff_t psize, last_voffset = 0;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen unsigned int i;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen int ret = 1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen *error_r = NULL;
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen t_array_init(&extrefs_arr, 16);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (!dbox_attachment_parse_extref_real(ext_refs, pool_datastack_create(),
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi &extrefs_arr)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "Broken ext-refs string";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen psize = dbox_file_get_plaintext_size(file);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen t_array_init(&streams, 8);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_foreach(&extrefs_arr, extref) {
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen path_suffix = file->storage->v.get_attachment_path_suffix(file);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen path = t_strdup_printf("%s/%s%s", file->storage->attachment_dir,
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen extref->path, path_suffix);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen if (extref->start_offset != last_voffset) {
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen uoff_t part_size = extref->start_offset - last_voffset;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen if ((*stream)->v_offset + part_size > psize) {
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen *error_r = t_strdup_printf(
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen "ext-refs point outside message "
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen "(%"PRIuUOFF_T" + %"PRIuUOFF_T" > %"PRIuUOFF_T")",
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen (*stream)->v_offset, part_size, psize);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen ret = 0;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen }
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen input = i_stream_create_limit(*stream, part_size);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen array_append(&streams, &input, 1);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen i_stream_seek(*stream, (*stream)->v_offset + part_size);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen last_voffset += part_size;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen last_voffset += extref->size;
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen input2 = i_stream_create_file(path, IO_BLOCK_SIZE);
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (extref->base64_blocks_per_line > 0) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen input = i_stream_create_base64_encoder(input2,
e03d986a74128f5ba30fcfda9f6e36578f5d8decTimo Sirainen extref->base64_blocks_per_line*4,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen extref->base64_have_crlf);
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen i_stream_unref(&input2);
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen input2 = input;
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen }
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen input = i_stream_create_attachment(input2, extref->size);
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen i_stream_unref(&input2);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen array_append(&streams, &input, 1);
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen }
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen if (psize != (*stream)->v_offset) {
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen if ((*stream)->v_offset > psize) {
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen *error_r = t_strdup_printf(
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen "ext-refs point outside message "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "(%"PRIuUOFF_T" > %"PRIuUOFF_T")",
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen (*stream)->v_offset, psize);
6cc4cce2078aca138fbce19305e69e77edcee614Timo Sirainen ret = 0;
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek } else {
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi uoff_t trailer_size = psize - last_voffset;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek input = i_stream_create_limit(*stream, trailer_size);
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen array_append(&streams, &input, 1);
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen (void)array_append_space(&streams);
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen }
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen }
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen inputs = array_idx_modifiable(&streams, 0);
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen i_stream_unref(stream);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen *stream = i_stream_create_concat(inputs);
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen for (i = 0; inputs[i] != NULL; i++)
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen i_stream_unref(&inputs[i]);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen return ret;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen}
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainenint dbox_attachment_file_get_stream(struct dbox_file *file,
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen struct istream **stream)
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen{
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen const char *ext_refs, *error;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen int ret;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* need to read metadata in case there are external references */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if ((ret = dbox_file_metadata_read(file)) <= 0)
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen return ret;
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen i_stream_seek(file->input, file->cur_offset + file->msg_header_size);
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen ext_refs = dbox_file_metadata_get(file, DBOX_METADATA_EXT_REF);
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (ext_refs == NULL)
4b41116563110d00330896a568eff1078c382827Timo Sirainen return 1;
4b41116563110d00330896a568eff1078c382827Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen /* we have external references. */
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen T_BEGIN {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen ret = dbox_attachment_file_get_stream_from(file, ext_refs,
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen stream, &error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dbox_file_set_corrupted(file,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen "Corrupted ext-refs metadata %s: %s",
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ext_refs, error);
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen }
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
dbe64f3893616a4005c8946be75d2dc8f6823d72Timo Sirainen}
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainen