static void test_quoted_printable_decode_final(void) { static struct test_quoted_printable_decode_data data[] = { { "=0A=0D ", "\n\r", 2, 0 }, { "foo=", "foo", 1, 0 }, { "foo ", "foo", 2, 0 }, { "foo= ", "foo", 3, 0 }, { "foo=A", "foo", 2, -1 } }; buffer_t *buf; unsigned int i, len; size_t src_pos; int ret; test_begin("quoted printable decode final"); buf = buffer_create_dynamic(pool_datastack_create(), 128); for (i = 0; i < N_ELEMENTS(data); i++) { len = strlen(data[i].input); ret = quoted_printable_decode_final((const void *)data[i].input, len, &src_pos, buf); test_assert(ret == data[i].ret); test_assert(src_pos + data[i].end_skip == len); test_assert(strcmp(data[i].output, str_c(buf)) == 0); buffer_set_used_size(buf, 0); } test_end(); }
static int i_stream_qp_try_decode_input(struct qp_decoder_istream *bstream, bool eof) { struct istream_private *stream = &bstream->istream; const unsigned char *data; size_t size, avail, buffer_avail, pos; buffer_t buf; int ret; data = i_stream_get_data(stream->parent, &size); if (size == 0) return 0; /* normally the decoded quoted-printable content can't be larger than the encoded content, but because we always use CRLFs, it may use twice as much space by only converting LFs to CRLFs. */ i_stream_try_alloc(stream, size, &avail); buffer_avail = stream->buffer_size - stream->pos; if (size > buffer_avail/2) { /* can't fit everything to destination buffer. write as much as we can. */ size = buffer_avail/2; if (size == 0) return -2; } buffer_create_from_data(&buf, stream->w_buffer + stream->pos, buffer_avail); ret = !eof ? quoted_printable_decode(data, size, &pos, &buf) : quoted_printable_decode_final(data, size, &pos, &buf); if (ret < 0) { io_stream_set_error(&stream->iostream, "Invalid quoted-printable data: 0x%s", binary_to_hex(data+pos, I_MAX(size-pos, 8))); stream->istream.stream_errno = EINVAL; return -1; } stream->pos += buf.used; i_stream_skip(stream->parent, pos); return pos > 0 ? 1 : 0; }
static int i_stream_qp_try_decode_input(struct qp_decoder_istream *bstream, bool eof) { struct istream_private *stream = &bstream->istream; const unsigned char *data; size_t size, avail, buffer_avail, pos; buffer_t buf; int ret; data = i_stream_get_data(stream->parent, &size); if (size == 0) return 0; /* the decoded quoted-printable content can never be larger than the encoded content. at worst they are equal. */ i_stream_try_alloc(stream, size, &avail); buffer_avail = stream->buffer_size - stream->pos; if (size > buffer_avail) { /* can't fit everything to destination buffer. write as much as we can. */ size = buffer_avail; if (size == 0) return -2; } buffer_create_from_data(&buf, stream->w_buffer + stream->pos, buffer_avail); ret = !eof ? quoted_printable_decode(data, size, &pos, &buf) : quoted_printable_decode_final(data, size, &pos, &buf); if (ret < 0) { stream->istream.stream_errno = EINVAL; return -1; } stream->pos += buf.used; i_stream_skip(stream->parent, pos); return pos > 0 ? 1 : 0; }