From: Stephan Bosch Date: Sat, 6 Aug 2016 15:59:10 +0000 (+0200) Subject: istream-base64-encoder: Implemented proper stat function that returns the encoded... X-Git-Tag: 2.3.0.rc1~3233 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0b9667003a1d54aec1ef60dd8adedb80c5775b3a;p=thirdparty%2Fdovecot%2Fcore.git istream-base64-encoder: Implemented proper stat function that returns the encoded size of the stream. For Base64 encoding, the size of the encoded data can be determined from the input data size exactly. --- diff --git a/src/lib/istream-base64-encoder.c b/src/lib/istream-base64-encoder.c index 2b7b5670a2..b63c12e32b 100644 --- a/src/lib/istream-base64-encoder.c +++ b/src/lib/istream-base64-encoder.c @@ -143,6 +143,35 @@ i_stream_base64_encoder_seek(struct istream_private *stream, i_stream_default_seek_nonseekable(stream, v_offset, mark); } +static int +i_stream_base64_encoder_stat(struct istream_private *stream, + bool exact ATTR_UNUSED) +{ + struct base64_encoder_istream *bstream = + (struct base64_encoder_istream *)stream; + const struct stat *st; + off_t newlines, size; + + if (i_stream_stat(stream->parent, exact, &st) < 0) { + stream->istream.stream_errno = stream->parent->stream_errno; + return -1; + } + + stream->statbuf = *st; + + /* calculate size of encoded data */ + size = (st->st_size / 3) * 4 + + ((st->st_size % 3) == 0 ? 0 : 4); + + /* update size with added newlines */ + newlines = (size / bstream->chars_per_line - 1) + + ((size % bstream->chars_per_line) == 0 ? 0 : 1); + size += newlines * (bstream->crlf ? 2 : 1); + + stream->statbuf.st_size = size; + return 0; +} + struct istream * i_stream_create_base64_encoder(struct istream *input, unsigned int chars_per_line, bool crlf) @@ -158,6 +187,7 @@ i_stream_create_base64_encoder(struct istream *input, bstream->istream.read = i_stream_base64_encoder_read; bstream->istream.seek = i_stream_base64_encoder_seek; + bstream->istream.stat = i_stream_base64_encoder_stat; bstream->istream.istream.readable_fd = FALSE; bstream->istream.istream.blocking = input->blocking; diff --git a/src/lib/test-istream-base64-encoder.c b/src/lib/test-istream-base64-encoder.c index dcc564e786..e158078d1b 100644 --- a/src/lib/test-istream-base64-encoder.c +++ b/src/lib/test-istream-base64-encoder.c @@ -13,9 +13,22 @@ static struct test { } tests[] = { { "hello world", 80, FALSE, "aGVsbG8gd29ybGQ=" }, { "hello world", 4, FALSE, "aGVs\nbG8g\nd29y\nbGQ=" }, - { "hello world", 4, TRUE, "aGVs\r\nbG8g\r\nd29y\r\nbGQ=", }, + { "hello world", 4, TRUE, "aGVs\r\nbG8g\r\nd29y\r\nbGQ=" }, + { "hello worlds", 80, FALSE, "aGVsbG8gd29ybGRz" }, + { "hello worlds", 4, FALSE, "aGVs\nbG8g\nd29y\nbGRz" }, + { "hello worlds", 4, TRUE, "aGVs\r\nbG8g\r\nd29y\r\nbGRz" }, + { "hell world", 80, FALSE, "aGVsbCB3b3JsZA==" }, + { "hell world", 4, FALSE, "aGVs\nbCB3\nb3Js\nZA==" }, + { "hell world", 4, TRUE, "aGVs\r\nbCB3\r\nb3Js\r\nZA==" }, + { "hello to the world!!", 80, FALSE, + "aGVsbG8gdG8gdGhlIHdvcmxkISE=" }, + { "hello to the world!!", 8, FALSE, + "aGVsbG8g\ndG8gdGhl\nIHdvcmxk\nISE=" }, + { "hello to the world!!", 8, TRUE, + "aGVsbG8g\r\ndG8gdGhl\r\nIHdvcmxk\r\nISE=" }, }; + static const char *hello = "hello world"; static void encode_test(const char *text, unsigned int chars_per_line, @@ -24,6 +37,7 @@ static void encode_test(const char *text, unsigned int chars_per_line, unsigned int i, text_len = strlen(text); struct istream *input, *input_data; const unsigned char *data; + uoff_t stream_size; size_t size; ssize_t ret; @@ -43,6 +57,10 @@ static void encode_test(const char *text, unsigned int chars_per_line, data = i_stream_get_data(input, &size); test_assert(size == strlen(output) && memcmp(data, output, size) == 0); + ret = i_stream_get_size(input, TRUE, &stream_size); + test_assert(ret > 0); + test_assert(size == stream_size); + i_stream_unref(&input); i_stream_unref(&input_data); }