]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
istream-base64-encoder: Implemented proper stat function that returns the encoded...
authorStephan Bosch <stephan@dovecot.fi>
Sat, 6 Aug 2016 15:59:10 +0000 (17:59 +0200)
committerStephan Bosch <stephan@dovecot.fi>
Sat, 6 Aug 2016 16:04:53 +0000 (18:04 +0200)
For Base64 encoding, the size of the encoded data can be determined from the input data size exactly.

src/lib/istream-base64-encoder.c
src/lib/test-istream-base64-encoder.c

index 2b7b5670a2c74a3aed274e5fc1b8e6bb7ae47f62..b63c12e32b47befa815140dc69ab2479515d0ce8 100644 (file)
@@ -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;
index dcc564e786b37fe0d61ad6b300cb75157a9d6e82..e158078d1b4e7828e2d29cb7657be2aeaa0df50d 100644 (file)
@@ -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);
 }