bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainenstatic int i_stream_read_parent(struct istream_private *stream)
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen size = i_stream_get_data_size(stream->parent);
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen /* we have less than one base64 block.
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen see if there is more data available. */
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen size = i_stream_get_data_size(stream->parent);
3700eab7818bcf8a68424c418485ae4e8770865dTimo Siraineni_stream_base64_try_decode_block(struct base64_decoder_istream *bstream)
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen struct istream_private *stream = &bstream->istream;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen data = i_stream_get_data(stream->parent, &size);
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen i_stream_try_alloc(stream, (size+3)/4*3, &avail);
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen buffer_avail = stream->buffer_size - stream->pos;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen /* can't fit everything to destination buffer.
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen write as much as we can. */
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_data(&buf, stream->w_buffer + stream->pos,
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen if (base64_decode(data, size, &pos, &buf) < 0) {
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen "Invalid base64 data: 0x%s",
e0bd5e662367e8c53c65ee3ad1252dd9469784cfTimo Sirainenstatic void i_stream_base64_last_partial_block(struct istream_private *stream)
e0bd5e662367e8c53c65ee3ad1252dd9469784cfTimo Sirainen /* base64 input with a partial block */
e0bd5e662367e8c53c65ee3ad1252dd9469784cfTimo Sirainen data = i_stream_get_data(stream->parent, &size);
e0bd5e662367e8c53c65ee3ad1252dd9469784cfTimo Sirainen for (i = 0; i < size; i++) {
e0bd5e662367e8c53c65ee3ad1252dd9469784cfTimo Sirainen "base64 input ends with a partial block: 0x%s",
e0bd5e662367e8c53c65ee3ad1252dd9469784cfTimo Sirainen "Invalid base64 data: 0x%s",
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainenstatic ssize_t i_stream_base64_decoder_read(struct istream_private *stream)
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen if (ret < 0 && stream->istream.stream_errno == 0 &&
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen /* encode as many blocks as fits into destination buffer */
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen while ((ret = i_stream_base64_try_decode_block(bstream)) > 0) ;
36a50bc13192383ee374be3c68c18842aa597f62Timo Sirainen } while (ret == 0 && pre_count == post_count);
3700eab7818bcf8a68424c418485ae4e8770865dTimo Siraineni_stream_base64_decoder_seek(struct istream_private *stream,
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen /* seeking backwards - go back to beginning and seek
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen forward from there. */
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen stream->parent_expected_offset = stream->parent_start_offset;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen i_stream_default_seek_nonseekable(stream, v_offset, mark);
3700eab7818bcf8a68424c418485ae4e8770865dTimo Siraineni_stream_create_base64_decoder(struct istream *input)
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen bstream = i_new(struct base64_decoder_istream, 1);
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen bstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen bstream->istream.read = i_stream_base64_decoder_read;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen bstream->istream.seek = i_stream_base64_decoder_seek;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen bstream->istream.istream.blocking = input->blocking;
3700eab7818bcf8a68424c418485ae4e8770865dTimo Sirainen bstream->istream.istream.seekable = input->seekable;