bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen#include "lib.h"
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen#include "istream-private.h"
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen#include "istream-nonuls.h"
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainenstruct nonuls_istream {
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen struct istream_private istream;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen char replace_chr;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen};
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainenstatic int i_stream_read_parent(struct istream_private *stream)
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen{
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen ssize_t ret;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen if (i_stream_get_data_size(stream->parent) > 0)
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen return 1;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
bcd286622779a93f809b11993db0550f8c7cc9b5Timo Sirainen ret = i_stream_read_memarea(stream->parent);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen if (ret <= 0) {
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen stream->istream.eof = stream->parent->eof;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen return ret;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen }
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen i_assert(i_stream_get_data_size(stream->parent) != 0);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen return 1;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen}
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainenstatic ssize_t i_stream_nonuls_read(struct istream_private *stream)
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen{
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen struct nonuls_istream *nstream = (struct nonuls_istream *)stream;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen const unsigned char *data, *p;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen size_t i, size, avail_size;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen int ret;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen if ((ret = i_stream_read_parent(stream)) <= 0)
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen return ret;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen data = i_stream_get_data(stream->parent, &size);
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen if (!i_stream_try_alloc(stream, size, &avail_size))
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen return -2;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen if (size > avail_size)
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen size = avail_size;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen i_assert(size > 0);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen p = memchr(data, '\0', size);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen if (p == NULL) {
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen /* no NULs in this block */
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen memcpy(stream->w_buffer+stream->pos, data, size);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen } else {
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen i = p-data;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen memcpy(stream->w_buffer+stream->pos, data, i);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen for (; i < size; i++) {
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen stream->w_buffer[stream->pos+i] = data[i] == '\0' ?
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream->replace_chr : data[i];
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen }
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen }
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen stream->pos += size;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen i_stream_skip(stream->parent, size);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen return size;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen}
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainenstruct istream *i_stream_create_nonuls(struct istream *input, char replace_chr)
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen{
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen struct nonuls_istream *nstream;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream = i_new(struct nonuls_istream, 1);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
5df8396a7cbad0b38b83a86667fb3d4c223f6f7cTimo Sirainen nstream->istream.stream_size_passthrough = TRUE;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream->istream.read = i_stream_nonuls_read;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream->istream.istream.readable_fd = FALSE;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream->istream.istream.blocking = input->blocking;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream->istream.istream.seekable = FALSE;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen nstream->replace_chr = replace_chr;
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen return i_stream_create(&nstream->istream, input,
2974dca6be5120e49279f06c8aa952e5fac56048Timo Sirainen i_stream_get_fd(input), 0);
e587908c556b449e5bb874e520e1d23993db3ae0Timo Sirainen}