dovecot: Added input stream filters for reading linefeeds as CRL...

dovecot at dovecot.org dovecot at dovecot.org
Sat Oct 6 01:50:58 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/ba65c858b7dd
changeset: 6527:ba65c858b7dd
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Oct 06 01:46:22 2007 +0300
description:
Added input stream filters for reading linefeeds as CRLFs or LFs.

diffstat:

3 files changed, 170 insertions(+)
src/lib/Makefile.am    |    2 
src/lib/istream-crlf.c |  159 ++++++++++++++++++++++++++++++++++++++++++++++++
src/lib/istream-crlf.h |    9 ++

diffs (195 lines):

diff -r c4205f6ac88f -r ba65c858b7dd src/lib/Makefile.am
--- a/src/lib/Makefile.am	Tue Oct 02 22:27:30 2007 +0300
+++ b/src/lib/Makefile.am	Sat Oct 06 01:46:22 2007 +0300
@@ -36,6 +36,7 @@ liblib_a_SOURCES = \
 	imem.c \
 	iostream.c \
 	istream.c \
+	istream-crlf.c \
 	istream-data.c \
 	istream-file.c \
 	istream-limit.c \
@@ -131,6 +132,7 @@ headers = \
 	imem.h \
 	iostream-internal.h \
 	istream.h \
+	istream-crlf.h \
 	istream-internal.h \
 	istream-seekable.h \
 	istream-tee.h \
diff -r c4205f6ac88f -r ba65c858b7dd src/lib/istream-crlf.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-crlf.c	Sat Oct 06 01:46:22 2007 +0300
@@ -0,0 +1,159 @@
+/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "istream-internal.h"
+#include "istream-crlf.h"
+
+struct crlf_istream {
+	struct istream_private istream;
+
+	struct istream *input;
+	char last_char;
+	unsigned int crlf:1;
+};
+
+static void i_stream_crlf_destroy(struct iostream_private *stream)
+{
+	struct crlf_istream *cstream = (struct crlf_istream *)stream;
+
+	i_stream_unref(&cstream->input);
+}
+
+static void
+i_stream_crlf_set_max_buffer_size(struct iostream_private *stream,
+				   size_t max_size)
+{
+	struct crlf_istream *cstream = (struct crlf_istream *)stream;
+
+	i_stream_set_max_buffer_size(cstream->input, max_size);
+}
+
+static ssize_t i_stream_crlf_read(struct istream_private *stream)
+{
+	struct crlf_istream *cstream = (struct crlf_istream *)stream;
+	const unsigned char *data;
+	size_t i, dest, size;
+	ssize_t ret;
+
+	ret = i_stream_read(cstream->input);
+	if (ret <= 0 && ret != -2) {
+		stream->istream.stream_errno = cstream->input->stream_errno;
+		stream->istream.eof = cstream->input->eof;
+		return ret;
+	}
+
+	data = i_stream_get_data(cstream->input, &size);
+	i_assert(size != 0);
+
+	if (size > stream->buffer_size - stream->pos) {
+		if (stream->skip > 0) {
+			/* remove the unused bytes from beginning of buffer */
+                        i_stream_compress(stream);
+		} else if (stream->max_buffer_size == 0 ||
+			   stream->buffer_size < stream->max_buffer_size) {
+			/* buffer is full - grow it */
+			i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
+		}
+
+		if (stream->pos == stream->buffer_size)
+			return -2;
+	}
+
+	/* @UNSAFE */
+	dest = stream->pos;
+	if (data[0] == '\n')
+		i = 0;
+	else {
+		if (cstream->last_char == '\r') {
+			/* CR without LF */
+			stream->w_buffer[dest++] = '\r';
+			if (dest == stream->buffer_size) {
+				cstream->last_char = 0;
+				return 1;
+			}
+		}
+		if (data[0] != '\r')
+			stream->w_buffer[dest++] = data[0];
+		i = 1;
+	}
+	cstream->last_char = data[size-1];
+	for (; i < size && dest < stream->buffer_size; i++) {
+		if (data[i] <= '\r') {
+			if (data[i] == '\n') {
+				if (cstream->crlf) {
+					if (dest + 1 == stream->buffer_size)
+						break;
+					stream->w_buffer[dest++] = '\r';
+				}
+				stream->w_buffer[dest++] = '\n';
+				continue;
+			}
+			if (data[i] == '\r' && data[i-1] != '\r')
+				continue;
+		}
+		if (data[i-1] == '\r') {
+			/* CR without LF */
+			stream->w_buffer[dest++] = '\r';
+			if (dest == stream->buffer_size) {
+				cstream->last_char = 0;
+				break;
+			}
+			if (data[i] == '\r')
+				continue;
+		}
+		stream->w_buffer[dest++] = data[i];
+	}
+	i_stream_skip(cstream->input, i);
+	stream->pos = dest;
+
+	return dest - stream->pos;
+}
+
+static void ATTR_NORETURN
+i_stream_crlf_seek(struct istream_private *stream ATTR_UNUSED,
+		   uoff_t v_offset ATTR_UNUSED, bool mark ATTR_UNUSED)
+{
+	i_panic("crlf-istream: seeking unsupported currently");
+}
+
+static const struct stat *
+i_stream_crlf_stat(struct istream_private *stream, bool exact)
+{
+	struct crlf_istream *cstream = (struct crlf_istream *)stream;
+
+	return i_stream_stat(cstream->input, exact);
+}
+
+static struct istream *
+i_stream_create_crlf_full(struct istream *input, bool crlf)
+{
+	struct crlf_istream *cstream;
+
+	i_stream_ref(input);
+
+	cstream = i_new(struct crlf_istream, 1);
+	cstream->input = input;
+	cstream->crlf = crlf;
+
+	cstream->istream.iostream.destroy = i_stream_crlf_destroy;
+	cstream->istream.iostream.set_max_buffer_size =
+		i_stream_crlf_set_max_buffer_size;
+
+	cstream->istream.read = i_stream_crlf_read;
+	cstream->istream.seek = i_stream_crlf_seek;
+	cstream->istream.stat = i_stream_crlf_stat;
+
+	cstream->istream.istream.blocking = input->blocking;
+	cstream->istream.istream.seekable = input->seekable;
+	return i_stream_create(&cstream->istream, i_stream_get_fd(input), 0);
+}
+
+struct istream *i_stream_create_crlf(struct istream *input)
+{
+	return i_stream_create_crlf_full(input, TRUE);
+}
+
+struct istream *i_stream_create_lf(struct istream *input)
+{
+	return i_stream_create_crlf_full(input, FALSE);
+}
diff -r c4205f6ac88f -r ba65c858b7dd src/lib/istream-crlf.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-crlf.h	Sat Oct 06 01:46:22 2007 +0300
@@ -0,0 +1,9 @@
+#ifndef ISTREAM_CRLF_H
+#define ISTREAM_CRLF_H
+
+/* Read all linefeeds as CRLF */
+struct istream *i_stream_create_crlf(struct istream *input);
+/* Read all linefeeds as LF */
+struct istream *i_stream_create_lf(struct istream *input);
+
+#endif


More information about the dovecot-cvs mailing list