istream-base64-decoder.c revision 36a50bc13192383ee374be3c68c18842aa597f62
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int i_stream_read_parent(struct istream_private *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size = i_stream_get_data_size(stream->parent);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* we have less than one base64 block.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen see if there is more data available. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Sirainen size = i_stream_get_data_size(stream->parent);
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Siraineni_stream_base64_try_decode_block(struct base64_decoder_istream *bstream)
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Sirainen struct istream_private *stream = &bstream->istream;
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Sirainen const unsigned char *data;
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Sirainen data = i_stream_get_data(stream->parent, &size);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen i_stream_try_alloc(stream, (size+3)/4*3, &avail);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen buffer_avail = stream->buffer_size - stream->pos;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* can't fit everything to destination buffer.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen write as much as we can. */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen buffer_create_data(&buf, stream->w_buffer + stream->pos, buffer_avail);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (base64_decode(data, size, &pos, &buf) < 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic ssize_t i_stream_base64_decoder_read(struct istream_private *stream)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (ret < 0 && stream->istream.stream_errno == 0 &&
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* base64 input with a partial block */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen /* encode as many blocks as fits into destination buffer */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen while ((ret = i_stream_base64_try_decode_block(bstream)) > 0) ;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } while (ret == 0 && pre_count == post_count);
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Siraineni_stream_base64_decoder_seek(struct istream_private *stream,
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen /* seeking backwards - go back to beginning and seek
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen forward from there. */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen stream->parent_expected_offset = stream->parent_start_offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_default_seek_nonseekable(stream, v_offset, mark);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Siraineni_stream_create_base64_decoder(struct istream *input)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bstream = i_new(struct base64_decoder_istream, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bstream->istream.read = i_stream_base64_decoder_read;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bstream->istream.seek = i_stream_base64_decoder_seek;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bstream->istream.istream.blocking = input->blocking;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bstream->istream.istream.seekable = input->seekable;