bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "lib.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "array.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "str.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "sha1.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "hash-format.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "safe-mkstemp.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "istream.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "istream-crlf.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "istream-attachment-extractor.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "istream-attachment-connector.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "ostream.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "test-common.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include <stdio.h>
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include <unistd.h>
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#define BINARY_TEXT_LONG "we have\ra lot \nof \0binary stuff in here\n" \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"b adjig sadjg jasidgjiaehga3wht8a3w8ghxjc dsgad hasdghsd gasd ds" \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"jdsoga sjdga0w3tjhawjgsertniq3n5oqerjqw2r89q23h awhrqh835r8a"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#define BINARY_TEXT_LONG_BASE64 \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"d2UgaGF2ZQ1hIGxvdCAKb2YgAGJpbmFyeSBzdHVmZiBpbiBoZXJlCmIgYWRqaWcgc2FkamcgamFz\r\n" \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"aWRnamlhZWhnYTN3aHQ4YTN3OGdoeGpjIGRzZ2FkIGhhc2RnaHNkIGdhc2QgZHNqZHNvZ2Egc2pk\r\n" \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Z2EwdzN0amhhd2pnc2VydG5pcTNuNW9xZXJqcXcycjg5cTIzaCBhd2hycWg4MzVyOGE="
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#define BINARY_TEXT_SHORT "eh"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#define BINARY_TEXT_SHORT_BASE64 "ZWg="
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic const char mail_input[] =
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"MIME-Version: 1.0\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Type: multipart/alternative;\r\n boundary=\"bound\"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"mime header\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n--bound\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Transfer-Encoding: base64\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Type: text/plain\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo SirainenBINARY_TEXT_LONG_BASE64
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n--bound\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Type: text/plain\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Transfer-Encoding: base64\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo SirainenBINARY_TEXT_SHORT_BASE64
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n--bound--\r\n";
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic const char mail_output[] =
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"MIME-Version: 1.0\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Type: multipart/alternative;\r\n boundary=\"bound\"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"mime header\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n--bound\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Transfer-Encoding: base64\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Type: text/plain\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n--bound\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Type: text/plain\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"Content-Transfer-Encoding: base64\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen"\r\n--bound--\r\n";
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainenstatic const char *mail_broken_input_body_prefix =
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen"MIME-Version: 1.0\r\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen"Content-Type: multipart/alternative;\r\n boundary=\"bound\"\r\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen"\r\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen"--bound\r\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen"Content-Transfer-Encoding: base64\r\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen"Content-Type: text/plain\r\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen"\r\n";
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainenstatic const char *mail_broken_input_bodies[] = {
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* broken base64 input */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg=\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vC\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* extra whitespace */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\n Zm9v\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v \nZm9v\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* mixed LF vs CRLFs */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vYmFy\r\nZm9vYmFy\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vYmFy\nZm9vYmFy\r\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* line length increases */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\nZm9vYmFy\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\nZm9vCg==",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\nZm9vYgo="
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen};
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainenstatic const char *mail_nonbroken_input_bodies[] = {
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* suffixes with explicit '=' end */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg==",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg==\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg==\r\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg==\nfoo\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg==\r\nfoo\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vCg== \t\t\n\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* suffixes with shorter line length */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vYmFy\nZm9v\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vYmFy\r\nZm9v\r\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vYmFy\nZm9v\nfoo\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vYmFy\r\nZm9v\r\nfoo\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9vYmFy\nZm9v\n \t\t\n\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* suffixes with empty line */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\n\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\r\n\r\n",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\n\nfoo\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\r\n\nfoo\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v\r\n\r\nfoo\n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen#if 0
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen /* the whitespace here could be handled as suffixes, but for now
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen they're not: */
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v ",
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen "Zm9v \n"
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen#endif
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen};
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstruct attachment {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen size_t buffer_offset;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uoff_t start_offset;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uoff_t encoded_size, decoded_size;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen unsigned int base64_blocks_per_line;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen};
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic buffer_t *attachment_data;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ARRAY(struct attachment) attachments;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int test_open_temp_fd(void *context ATTR_UNUSED)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen string_t *str = t_str_new(128);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen int fd;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen str_append(str, "/tmp/dovecot-test.");
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen fd = safe_mkstemp(str, 0600, (uid_t)-1, (gid_t)-1);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (fd == -1)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_fatal("safe_mkstemp(%s) failed: %m", str_c(str));
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink(str_c(str));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return fd;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int test_open_attachment_ostream(struct istream_attachment_info *info,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct ostream **output_r,
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen const char **error_r ATTR_UNUSED,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen void *context ATTR_UNUSED)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct attachment *a;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (attachment_data == NULL)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen attachment_data = buffer_create_dynamic(default_pool, 1024);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (!array_is_created(&attachments))
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_array_init(&attachments, 8);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a = array_append_space(&attachments);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a->buffer_offset = attachment_data->used;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a->start_offset = info->start_offset;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a->encoded_size = info->encoded_size;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a->base64_blocks_per_line = info->base64_blocks_per_line;
e869616aca1c2469c436e1e99dad93f7e4b2ae8aTimo Sirainen test_assert(strlen(info->hash) == 160/8*2); /* sha1 size */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen *output_r = o_stream_create_buffer(attachment_data);
af5fc8ca268d69dd3ebbe0416ec6270f94121e39Timo Sirainen if (o_stream_seek(*output_r, a->buffer_offset) < 0)
af5fc8ca268d69dd3ebbe0416ec6270f94121e39Timo Sirainen i_unreached();
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainenstatic int
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainentest_open_attachment_ostream_error(struct istream_attachment_info *info ATTR_UNUSED,
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen struct ostream **output_r ATTR_UNUSED,
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen const char **error_r,
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen void *context ATTR_UNUSED)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen{
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen *error_r = "test open error";
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen return -1;
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen}
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int test_close_attachment_ostream(struct ostream *output, bool success,
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen const char **error_r ATTR_UNUSED,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen void *context ATTR_UNUSED)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct attachment *a;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_assert(success);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a = array_idx_modifiable(&attachments, array_count(&attachments)-1);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a->decoded_size = output->offset - a->buffer_offset;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen if (o_stream_finish(output) < 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_unreached();
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen o_stream_destroy(&output);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainenstatic int
aab5704d21173f9f825c016812c8099d16ea5b9fTimo Sirainentest_close_attachment_ostream_error(struct ostream *output,
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen bool success, const char **error,
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen void *context ATTR_UNUSED)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen{
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen if (success)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen *error = "test output error";
0a222deffd3f48e43aa61ceb73a4faeeeea5e12cTimo Sirainen o_stream_abort(output);
aab5704d21173f9f825c016812c8099d16ea5b9fTimo Sirainen o_stream_destroy(&output);
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen return -1;
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen}
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic struct istream *
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainentest_build_original_istream(struct istream *base_input, uoff_t msg_size)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct istream_attachment_connector *conn;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const unsigned char *data = attachment_data->data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const struct attachment *a;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct istream *input;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uoff_t data_size = attachment_data->used;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const char *error;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen conn = istream_attachment_connector_begin(base_input, msg_size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen array_foreach(&attachments, a) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen input = i_stream_create_from_data(data, a->decoded_size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (istream_attachment_connector_add(conn, input,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a->start_offset, a->encoded_size,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen a->base64_blocks_per_line, TRUE, &error) < 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_unreached();
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_unref(&input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_assert(a->decoded_size <= data_size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen data += a->decoded_size;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen data_size -= a->decoded_size;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_assert(data_size == 0);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return istream_attachment_connector_finish(&conn);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic void
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenget_istream_attachment_settings(struct istream_attachment_settings *set_r)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const char *error;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(set_r);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen set_r->min_size = 1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen set_r->drain_parent_input = TRUE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen set_r->open_temp_fd = test_open_temp_fd;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen set_r->open_attachment_ostream = test_open_attachment_ostream;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen set_r->close_attachment_ostream= test_close_attachment_ostream;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (hash_format_init("%{sha1}", &set_r->hash_format, &error) < 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_unreached();
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int test_input_stream(struct istream *file_input)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct istream_attachment_settings set;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct istream *input, *input2;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const unsigned char *data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen size_t size;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct sha1_ctxt hash;
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen uoff_t msg_size, orig_msg_size;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen buffer_t *base_buf;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen unsigned char hash_file[SHA1_RESULTLEN], hash_attached[SHA1_RESULTLEN];
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen int ret = 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* get hash when directly reading input */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen input = i_stream_create_crlf(file_input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen sha1_init(&hash);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while (i_stream_read_more(input, &data, &size) > 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen sha1_loop(&hash, data, size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_skip(input, size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen sha1_result(&hash, hash_file);
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen msg_size = orig_msg_size = input->v_offset;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_unref(&input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* read through attachment extractor */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen get_istream_attachment_settings(&set);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_seek(file_input, 0);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen input = i_stream_create_crlf(file_input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen input2 = i_stream_create_attachment_extractor(input, &set, NULL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_unref(&input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen base_buf = buffer_create_dynamic(default_pool, 1024);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while (i_stream_read_more(input2, &data, &size) > 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen buffer_append(base_buf, data, size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_skip(input2, size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_unref(&input2);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* rebuild the original stream and see if the hash matches */
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen for (unsigned int i = 0; i < 2; i++) {
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen input2 = i_stream_create_from_data(base_buf->data, base_buf->used);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen input = test_build_original_istream(input2, msg_size);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen i_stream_unref(&input2);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen sha1_init(&hash);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen while (i_stream_read_more(input, &data, &size) > 0) {
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen sha1_loop(&hash, data, size);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen i_stream_skip(input, size);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen }
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen test_assert_idx(input->eof && input->stream_errno == 0, i);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen sha1_result(&hash, hash_attached);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen i_stream_unref(&input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen if (memcmp(hash_file, hash_attached, SHA1_RESULTLEN) != 0)
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen ret = -1;
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen /* try again without knowing the message's size */
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen msg_size = (uoff_t)-1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen /* try with a wrong message size */
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen for (int i = 0; i < 2; i++) {
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen input2 = i_stream_create_from_data(base_buf->data, base_buf->used);
075081e25ef07989be10f7c9cf85f833f90be46fTimo Sirainen input = test_build_original_istream(input2, orig_msg_size +
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen (i == 0 ? 1 : -1));
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen i_stream_unref(&input2);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen while (i_stream_read_more(input, &data, &size) > 0)
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen i_stream_skip(input, size);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen test_assert(input->stream_errno == (i == 0 ? EPIPE : EINVAL));
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen i_stream_unref(&input);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen buffer_free(&base_buf);
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&attachment_data);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (array_is_created(&attachments))
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen array_free(&attachments);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic void test_istream_attachment(void)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct istream_attachment_settings set;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct istream *datainput, *input;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const unsigned char *data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen size_t i, size;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen int ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_begin("istream attachment");
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen datainput = test_istream_create_data(mail_input, sizeof(mail_input));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_istream_set_allow_eof(datainput, FALSE);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen get_istream_attachment_settings(&set);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen input = i_stream_create_attachment_extractor(datainput, &set, NULL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen for (i = 1; i <= sizeof(mail_input); i++) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_istream_set_size(datainput, i);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen while ((ret = i_stream_read(input)) > 0) ;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_assert(ret == 0);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_istream_set_allow_eof(datainput, TRUE);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen while ((ret = i_stream_read(input)) > 0) ;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_assert(ret == -1);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen data = i_stream_get_data(input, &size);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_assert(size == sizeof(mail_output) &&
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memcmp(data, mail_output, size) == 0);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen data = attachment_data->data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_assert(attachment_data->used ==
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen sizeof(BINARY_TEXT_LONG)-1 + strlen(BINARY_TEXT_SHORT));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_assert(memcmp(data, BINARY_TEXT_LONG, sizeof(BINARY_TEXT_LONG)-1) == 0);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_assert(memcmp(data + sizeof(BINARY_TEXT_LONG)-1,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen BINARY_TEXT_SHORT, strlen(BINARY_TEXT_SHORT)) == 0);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_unref(&input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_unref(&datainput);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&attachment_data);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen if (array_is_created(&attachments))
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen array_free(&attachments);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen test_end();
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen}
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainenstatic bool test_istream_attachment_extractor_one(const char *body, int err_type)
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen const size_t prefix_len = strlen(mail_broken_input_body_prefix);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen struct istream_attachment_settings set;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen struct istream *datainput, *input;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen char *mail_text;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen const unsigned char *data;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen size_t size;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen int ret;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen bool unchanged;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen mail_text = i_strconcat(mail_broken_input_body_prefix, body, NULL);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen datainput = test_istream_create_data(mail_text, strlen(mail_text));
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen get_istream_attachment_settings(&set);
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen if (err_type == 1)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen set.open_attachment_ostream = test_open_attachment_ostream_error;
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen else if (err_type == 2)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen set.close_attachment_ostream = test_close_attachment_ostream_error;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen input = i_stream_create_attachment_extractor(datainput, &set, NULL);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen while ((ret = i_stream_read(input)) > 0) ;
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen if (err_type != 0) {
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_assert(ret == -1 && input->stream_errno == EIO);
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen unchanged = FALSE;
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen goto cleanup;
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen }
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_assert(ret == -1 && input->stream_errno == 0);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen data = i_stream_get_data(input, &size);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen i_assert(size >= prefix_len &&
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen memcmp(data, mail_broken_input_body_prefix, prefix_len) == 0);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen data += prefix_len;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen size -= prefix_len;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen i_assert(attachment_data != NULL);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen unchanged = attachment_data->used <= strlen(body) &&
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen memcmp(attachment_data->data, body, attachment_data->used) == 0 &&
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen strlen(body) - attachment_data->used == size &&
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen memcmp(data, body + attachment_data->used, size) == 0;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainencleanup:
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&attachment_data);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen if (array_is_created(&attachments))
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen array_free(&attachments);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen i_stream_unref(&input);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen i_stream_unref(&datainput);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen i_free(mail_text);
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen return unchanged;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen}
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainenstatic void test_istream_attachment_extractor(void)
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen{
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen unsigned int i;
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen test_begin("istream attachment extractor");
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen for (i = 0; i < N_ELEMENTS(mail_broken_input_bodies); i++)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_assert(test_istream_attachment_extractor_one(mail_broken_input_bodies[i], 0));
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen for (i = 0; i < N_ELEMENTS(mail_nonbroken_input_bodies); i++)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_assert(!test_istream_attachment_extractor_one(mail_nonbroken_input_bodies[i], 0));
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_end();
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen}
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainenstatic void test_istream_attachment_extractor_error(void)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen{
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen unsigned int i;
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_begin("istream attachment extractor error");
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen for (int err_type = 1; err_type <= 2; err_type++) {
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_broken_input_bodies); i++)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_istream_attachment_extractor_one(mail_broken_input_bodies[i], err_type);
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_nonbroken_input_bodies); i++)
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_istream_attachment_extractor_one(mail_nonbroken_input_bodies[i], err_type);
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_end();
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainenstatic void test_istream_attachment_connector(void)
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen{
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen struct istream *input;
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen test_begin("istream attachment connector");
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen input = i_stream_create_from_data(mail_input, sizeof(mail_input));
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen test_assert(test_input_stream(input) == 0);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen i_stream_unref(&input);
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen test_end();
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen}
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int test_input_file(const char *path)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct istream *file_input;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen int ret = 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen lib_init();
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen file_input = i_stream_create_file(path, 64);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (test_input_stream(file_input) < 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen fprintf(stderr, "istream-attachment-extractor: mismatch on file %s\n",
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen path);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = -1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_stream_unref(&file_input);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen lib_deinit();
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenint main(int argc, char *argv[])
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainen static void (*const test_functions[])(void) = {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen test_istream_attachment,
108340ffacae3b7d09fa51b566d77aa51dd6483bTimo Sirainen test_istream_attachment_extractor,
9d0be57bcc352f776a327d7e2a6c6232137f4a04Timo Sirainen test_istream_attachment_extractor_error,
24d6fd2b8e2c327ae2a20a0c4be8af2ef7b3b468Timo Sirainen test_istream_attachment_connector,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen NULL
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen };
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (argc > 1)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return test_input_file(argv[1]) < 0 ? 1 : 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen else
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return test_run(test_functions);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}