test-istream-attachment.c revision e869616aca1c2469c436e1e99dad93f7e4b2ae8a
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2007-2012 Dovecot authors, see the included COPYING file */
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen#include "lib.h"
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen#include "array.h"
86441ffc028f11857152c15fe7b0d24ff0874504Timo Sirainen#include "str.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "sha1.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "hash-format.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "safe-mkstemp.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "istream.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "istream-crlf.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "istream-attachment-extractor.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "istream-attachment-connector.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "ostream.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "test-common.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include <stdio.h>
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include <unistd.h>
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#define BINARY_TEXT_LONG "we have\ra lot \nof \0binary stuff in here\n" \
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"b adjig sadjg jasidgjiaehga3wht8a3w8ghxjc dsgad hasdghsd gasd ds" \
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"jdsoga sjdga0w3tjhawjgsertniq3n5oqerjqw2r89q23h awhrqh835r8a"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#define BINARY_TEXT_LONG_BASE64 \
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"d2UgaGF2ZQ1hIGxvdCAKb2YgAGJpbmFyeSBzdHVmZiBpbiBoZXJlCmIgYWRqaWcgc2FkamcgamFz\r\n" \
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"aWRnamlhZWhnYTN3aHQ4YTN3OGdoeGpjIGRzZ2FkIGhhc2RnaHNkIGdhc2QgZHNqZHNvZ2Egc2pk\r\n" \
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Z2EwdzN0amhhd2pnc2VydG5pcTNuNW9xZXJqcXcycjg5cTIzaCBhd2hycWg4MzVyOGE="
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#define BINARY_TEXT_SHORT "eh"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#define BINARY_TEXT_SHORT_BASE64 "ZWg="
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstatic const char mail_input[] =
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"MIME-Version: 1.0\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Type: multipart/alternative;\r\n boundary=\"bound\"\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"mime header\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n--bound\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Transfer-Encoding: base64\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Type: text/plain\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo SirainenBINARY_TEXT_LONG_BASE64
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n--bound\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Type: text/plain\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Transfer-Encoding: base64\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo SirainenBINARY_TEXT_SHORT_BASE64
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n--bound--\r\n";
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstatic const char mail_output[] =
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"MIME-Version: 1.0\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Type: multipart/alternative;\r\n boundary=\"bound\"\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"mime header\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n--bound\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Transfer-Encoding: base64\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Type: text/plain\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"\r\n--bound\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Type: text/plain\r\n"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen"Content-Transfer-Encoding: base64\r\n"
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen"\r\n"
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen"\r\n--bound--\r\n";
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainenstruct attachment {
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen size_t buffer_offset;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen uoff_t start_offset;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen uoff_t encoded_size, decoded_size;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen unsigned int base64_blocks_per_line;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen};
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainenstatic buffer_t *attachment_data;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainenstatic ARRAY(struct attachment) attachments;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainenstatic int test_open_temp_fd(void *context ATTR_UNUSED)
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen{
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen string_t *str = t_str_new(128);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen int fd;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen str_append(str, "/tmp/dovecot-test.");
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen fd = safe_mkstemp(str, 0600, (uid_t)-1, (gid_t)-1);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen if (fd == -1)
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen i_fatal("safe_mkstemp(%s) failed: %m", str_c(str));
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen (void)unlink(str_c(str));
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen return fd;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen}
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainenstatic int test_open_attachment_ostream(struct istream_attachment_info *info,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen struct ostream **output_r,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen void *context ATTR_UNUSED)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen{
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen struct attachment *a;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen if (attachment_data == NULL)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen attachment_data = buffer_create_dynamic(default_pool, 1024);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen if (!array_is_created(&attachments))
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_array_init(&attachments, 8);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a = array_append_space(&attachments);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a->buffer_offset = attachment_data->used;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a->start_offset = info->start_offset;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a->encoded_size = info->encoded_size;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a->base64_blocks_per_line = info->base64_blocks_per_line;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen test_assert(strlen(info->hash) == 160/8*2); /* sha1 size */
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen *output_r = o_stream_create_buffer(attachment_data);
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen if (o_stream_seek(*output_r, a->buffer_offset) < 0)
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen i_unreached();
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen return 0;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen}
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic int test_close_attachment_ostream(struct ostream *output, bool success,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen void *context ATTR_UNUSED)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen{
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen struct attachment *a;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_assert(success);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a = array_idx_modifiable(&attachments, array_count(&attachments)-1);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a->decoded_size = output->offset - a->buffer_offset;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen if (o_stream_nfinish(output) < 0)
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen i_unreached();
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen o_stream_destroy(&output);
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen return 0;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen}
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic struct istream *
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainentest_build_original_istream(struct istream *base_input, uoff_t msg_size)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen{
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen struct istream_attachment_connector *conn;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen const unsigned char *data = attachment_data->data;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen const struct attachment *a;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen struct istream *input;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen uoff_t data_size = attachment_data->used;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen const char *error;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen conn = istream_attachment_connector_begin(base_input, msg_size);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen array_foreach(&attachments, a) {
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen input = i_stream_create_from_data(data, a->decoded_size);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen if (istream_attachment_connector_add(conn, input,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen a->start_offset, a->encoded_size,
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen a->base64_blocks_per_line, TRUE, &error) < 0)
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen i_unreached();
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_stream_unref(&input);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_assert(a->decoded_size <= data_size);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen data += a->decoded_size;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen data_size -= a->decoded_size;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen }
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_assert(data_size == 0);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen return istream_attachment_connector_finish(&conn);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen}
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic void
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenget_istream_attachment_settings(struct istream_attachment_settings *set_r)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen{
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen const char *error;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen memset(set_r, 0, sizeof(*set_r));
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen set_r->min_size = 1;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen set_r->drain_parent_input = TRUE;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen set_r->open_temp_fd = test_open_temp_fd;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen set_r->open_attachment_ostream = test_open_attachment_ostream;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen set_r->close_attachment_ostream= test_close_attachment_ostream;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen if (hash_format_init("%{sha1}", &set_r->hash_format, &error) < 0)
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen i_unreached();
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen}
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainenstatic int test_input_stream(struct istream *file_input)
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen{
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen struct istream_attachment_settings set;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen struct istream *input, *input2;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen const unsigned char *data;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen size_t size;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen struct sha1_ctxt hash;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen uoff_t msg_size;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen buffer_t *base_buf;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen unsigned char hash_file[SHA1_RESULTLEN], hash_attached[SHA1_RESULTLEN];
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen int ret = 0;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* get hash when directly reading input */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch input = i_stream_create_crlf(file_input);
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch sha1_init(&hash);
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch while (i_stream_read_data(input, &data, &size, 0) > 0) {
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch sha1_loop(&hash, data, size);
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch i_stream_skip(input, size);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch }
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch sha1_result(&hash, hash_file);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch msg_size = input->v_offset;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_unref(&input);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* read through attachment extractor */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch get_istream_attachment_settings(&set);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_seek(file_input, 0);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch input = i_stream_create_crlf(file_input);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch input2 = i_stream_create_attachment_extractor(input, &set, NULL);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_unref(&input);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch base_buf = buffer_create_dynamic(default_pool, 1024);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch while (i_stream_read_data(input2, &data, &size, 0) > 0) {
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch buffer_append(base_buf, data, size);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_skip(input2, size);
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch }
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch i_stream_unref(&input2);
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch /* rebuild the original stream and see if the hash matches */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch input2 = i_stream_create_from_data(base_buf->data, base_buf->used);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch input = test_build_original_istream(input2, msg_size);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_unref(&input2);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch sha1_init(&hash);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch while (i_stream_read_data(input, &data, &size, 0) > 0) {
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch sha1_loop(&hash, data, size);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_skip(input, size);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch }
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch sha1_result(&hash, hash_attached);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_unref(&input);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch ret = memcmp(hash_file, hash_attached, SHA1_RESULTLEN) == 0 ? 0 : -1;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_stream_unref(&file_input);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch buffer_free(&base_buf);
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch if (attachment_data != NULL)
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch buffer_free(&attachment_data);
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch if (array_is_created(&attachments))
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch array_free(&attachments);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch return ret;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch}
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Boschstatic void test_istream_attachment(void)
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch{
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch struct istream_attachment_settings set;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch struct istream *datainput, *input;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch const unsigned char *data;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch size_t i, size;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch int ret;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch test_begin("istream attachment");
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch datainput = test_istream_create_data(mail_input, sizeof(mail_input));
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen test_istream_set_allow_eof(datainput, FALSE);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen get_istream_attachment_settings(&set);
b7324e421e2132cbbf753e6fdbe675bbaecdf929Timo Sirainen input = i_stream_create_attachment_extractor(datainput, &set, NULL);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen for (i = 1; i <= sizeof(mail_input); i++) {
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen test_istream_set_size(datainput, i);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen while ((ret = i_stream_read(input)) > 0) ;
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_assert(ret == 0);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi }
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_istream_set_allow_eof(datainput, TRUE);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi while ((ret = i_stream_read(input)) > 0) ;
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_assert(ret == -1);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi data = i_stream_get_data(input, &size);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_assert(size == sizeof(mail_output) &&
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi memcmp(data, mail_output, size) == 0);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi data = attachment_data->data;
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_assert(attachment_data->used ==
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi sizeof(BINARY_TEXT_LONG)-1 + strlen(BINARY_TEXT_SHORT));
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_assert(memcmp(data, BINARY_TEXT_LONG, sizeof(BINARY_TEXT_LONG)-1) == 0);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_assert(memcmp(data + sizeof(BINARY_TEXT_LONG)-1,
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi BINARY_TEXT_SHORT, strlen(BINARY_TEXT_SHORT)) == 0);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi i_stream_unref(&input);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi i_stream_unref(&datainput);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_end();
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi}
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvistatic int test_input_file(const char *path)
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi{
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi struct istream *file_input;
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi int ret = 0;
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen lib_init();
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen file_input = i_stream_create_file(path, 64);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen if (test_input_stream(file_input) < 0) {
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen fprintf(stderr, "istream-attachment-extractor: mismatch on file %s\n",
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen path);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen ret = -1;
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen }
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen i_stream_unref(&file_input);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen lib_deinit();
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen return ret;
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen}
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainenint main(int argc, char *argv[])
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen{
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen static void (*test_functions[])(void) = {
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi test_istream_attachment,
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi NULL
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi };
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi if (argc > 1)
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi return test_input_file(argv[1]) < 0 ? 1 : 0;
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi else
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi return test_run(test_functions);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi}
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi