bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* how far in string "\r\n.\r" are we */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* state didn't actually start with \r */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* state didn't contain \n either (only at the beginnign of stream) */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* we've seen the "." line, keep returning EOF */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainenstatic int i_stream_dot_read_some(struct dot_istream *dstream)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen struct istream_private *stream = &dstream->istream;
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen size = i_stream_get_data_size(stream->parent);
22ee6e1e6193299034ab99f77a650290de2fd6caTimo Sirainen i_assert(ret != -2); /* 0 sized buffer can't be full */
21bf1ba026461d15b5ecc2c2b6272206ce84fa80Timo Sirainen /* we didn't see "." line */
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen "dot-input stream ends without '.' line");
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen size = i_stream_get_data_size(stream->parent);
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen if (!i_stream_try_alloc(stream, size, &avail))
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainenstatic bool flush_pending(struct dot_istream *dstream, size_t *destp)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen struct istream_private *stream = &dstream->istream;
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen unsigned int i = 0;
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen for (; dstream->pending[i] != '\0' && dest < stream->buffer_size; i++)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen stream->w_buffer[dest++] = dstream->pending[i];
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen memmove(dstream->pending, dstream->pending + i,
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainenstatic bool flush_dot_state(struct dot_istream *dstream, size_t *destp)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen unsigned int i = 0;
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* \r\n.\r seen, go back to \r state */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainenstatic void i_stream_dot_eof(struct dot_istream *dstream, size_t *destp)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Siraineni_stream_dot_return(struct istream_private *stream, size_t dest, ssize_t ret)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainenstatic ssize_t i_stream_dot_read(struct istream_private *stream)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* @UNSAFE */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen struct dot_istream *dstream = (struct dot_istream *)stream;
21bf1ba026461d15b5ecc2c2b6272206ce84fa80Timo Sirainen /* we have to update stream->pos before reading more data */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen if ((ret = i_stream_dot_read_some(dstream)) <= 0) {
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen return i_stream_dot_return(stream, dest, ret);
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen data = i_stream_get_data(stream->parent, &size);
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen for (i = 0; i < size && dest < stream->buffer_size; i++) {
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* CR seen */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* [CR]LF seen */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* [CR]LF. seen */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* drop the initial dot */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* [CR]LF.CR seen */
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen /* drop the initial dot */
21bf1ba026461d15b5ecc2c2b6272206ce84fa80Timo Sirainen ret = i_stream_dot_return(stream, dest, 0) + ret1;
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainenstruct istream *i_stream_create_dot(struct istream *input, bool send_last_lf)
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen dstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
eca36422686d8672ff73b84067a16bdb01fe6746Timo Sirainen dstream->istream.istream.blocking = input->blocking;