[dovecot-cvs] dovecot/src/lib-mail message-parser.c,1.41,1.42 message-parser.h,1.19,1.20 message-send.c,1.17,1.18 message-send.h,1.10,1.11 message-size.c,1.12,1.13 message-size.h,1.10,1.11

cras at procontrol.fi cras at procontrol.fi
Wed Jun 4 19:58:01 EEST 2003


Update of /home/cvs/dovecot/src/lib-mail
In directory danu:/tmp/cvs-serv27024/lib-mail

Modified Files:
	message-parser.c message-parser.h message-send.c 
	message-send.h message-size.c message-size.h 
Log Message:
IMAP protocol doesn't allow server to send NULs to client. Send ascii #128
instead.



Index: message-parser.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-parser.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- message-parser.c	4 Jun 2003 14:47:22 -0000	1.41
+++ message-parser.c	4 Jun 2003 15:57:58 -0000	1.42
@@ -38,6 +38,8 @@
 	string_t *name;
 	buffer_t *value_buf;
 	size_t skip;
+
+	int has_nuls;
 };
 
 static struct message_part *
@@ -46,12 +48,12 @@
 
 static struct message_part *
 message_parse_body(struct istream *input, struct message_boundary *boundaries,
-		   struct message_size *body_size);
+		   struct message_size *body_size, int *has_nuls);
 
 static struct message_part *
 message_skip_boundary(struct istream *input,
 		      struct message_boundary *boundaries,
-		      struct message_size *boundary_size);
+		      struct message_size *boundary_size, int *has_nuls);
 
 static void message_size_add_part(struct message_size *dest,
 				  struct message_part *part)
@@ -138,6 +140,7 @@
 {
 	struct message_part *parent_part, *next_part, *part;
 	struct message_boundary *b;
+	int has_nuls;
 
 	/* multipart message. add new boundary */
 	b = t_new(struct message_boundary, 1);
@@ -155,7 +158,9 @@
 	/* skip the data before the first boundary */
 	parent_part = parser_ctx->part;
 	next_part = message_skip_boundary(input, parser_ctx->boundaries,
-					  &parent_part->body_size);
+					  &parent_part->body_size, &has_nuls);
+	if (has_nuls)
+		parent_part->flags |= MESSAGE_PART_FLAG_HAS_NULS;
 
 	/* now, parse the parts */
 	while (next_part == parent_part) {
@@ -165,6 +170,11 @@
                 parser_ctx->part = part;
 		next_part = message_parse_part(input, parser_ctx);
 
+		if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
+			/* it also belongs to parent */
+			parent_part->flags |= MESSAGE_PART_FLAG_HAS_NULS;
+		}
+
 		/* update our size */
 		message_size_add_part(&parent_part->body_size, part);
 
@@ -173,7 +183,10 @@
 
 		/* skip the boundary */
 		next_part = message_skip_boundary(input, parser_ctx->boundaries,
-						  &parent_part->body_size);
+						  &parent_part->body_size,
+						  &has_nuls);
+		if (has_nuls)
+			parent_part->flags |= MESSAGE_PART_FLAG_HAS_NULS;
 	}
 
 	/* remove boundary */
@@ -192,6 +205,7 @@
 	struct message_header_line *hdr;
 	struct message_part *next_part, *part;
 	uoff_t hdr_size;
+	int has_nuls;
 
 	hdr_ctx = message_parse_header_init(input,
 					    &parser_ctx->part->header_size);
@@ -219,6 +233,8 @@
 		parser_ctx->callback(parser_ctx->part, NULL,
 				     parser_ctx->context);
 	}
+	if (hdr_ctx->has_nuls)
+		parser_ctx->part->flags |= MESSAGE_PART_FLAG_HAS_NULS;
 	message_parse_header_deinit(hdr_ctx);
 
 	i_assert((parser_ctx->part->flags & MUTEX_FLAGS) != MUTEX_FLAGS);
@@ -263,23 +279,35 @@
 		/* normal message, read until the next boundary */
 		part = parser_ctx->part;
 		next_part = message_parse_body(input, parser_ctx->boundaries,
-					       &part->body_size);
+					       &part->body_size, &has_nuls);
+		if (has_nuls)
+			part->flags |= MESSAGE_PART_FLAG_HAS_NULS;
+	}
+
+	if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0 &&
+	    part->parent != NULL) {
+		/* it also belongs to parent */
+		part->parent->flags |= MESSAGE_PART_FLAG_HAS_NULS;
 	}
 
 	return next_part;
 }
 
 static void message_skip_line(struct istream *input,
-			      struct message_size *msg_size, int skip_lf)
+			      struct message_size *msg_size, int skip_lf,
+			      int *has_nuls)
 {
 	const unsigned char *msg;
 	size_t i, size, startpos;
 
 	startpos = 0;
+	*has_nuls = FALSE;
 
 	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size; i++) {
-			if (msg[i] == '\n') {
+			if (msg[i] == '\0')
+				*has_nuls = TRUE;
+			else if (msg[i] == '\n') {
 				if (!skip_lf) {
 					if (i > 0 && msg[i-1] == '\r')
 						i--;
@@ -336,7 +364,8 @@
 static struct message_boundary *
 message_find_boundary(struct istream *input,
 		      struct message_boundary *boundaries,
-		      struct message_size *msg_size, int skip_over)
+		      struct message_size *msg_size, int skip_over,
+		      int *has_nuls)
 {
 	struct message_boundary *boundary;
 	const unsigned char *msg;
@@ -344,11 +373,15 @@
 
 	boundary = NULL;
 	missing_cr_count = startpos = line_start = 0;
+	*has_nuls = FALSE;
 
 	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size; i++) {
-			if (msg[i] != '\n')
+			if (msg[i] != '\n') {
+				if (msg[i] == '\0')
+					*has_nuls = TRUE;
 				continue;
+			}
 
 			if (line_start != (size_t)-1 &&
 			    i >= line_start+2 && msg[line_start] == '-' &&
@@ -447,20 +480,22 @@
 
 static struct message_part *
 message_parse_body(struct istream *input, struct message_boundary *boundaries,
-		   struct message_size *msg_size)
+		   struct message_size *msg_size, int *has_nuls)
 {
 	struct message_boundary *boundary;
 	struct message_size body_size;
 
 	if (boundaries == NULL) {
-		message_get_body_size(input, &body_size, (uoff_t)-1, NULL);
+		message_get_body_size(input, &body_size,
+				      (uoff_t)-1, NULL, has_nuls);
 		message_size_add(msg_size, &body_size);
-		return NULL;
+		boundary = NULL;
 	} else {
 		boundary = message_find_boundary(input, boundaries,
-						 msg_size, FALSE);
-		return boundary == NULL ? NULL : boundary->part;
+						 msg_size, FALSE, has_nuls);
 	}
+
+	return boundary == NULL ? NULL : boundary->part;
 }
 
 /* skip data until next boundary is found. if it's end boundary,
@@ -468,7 +503,7 @@
 static struct message_part *
 message_skip_boundary(struct istream *input,
 		      struct message_boundary *boundaries,
-		      struct message_size *boundary_size)
+		      struct message_size *boundary_size, int *has_nuls)
 {
 	struct message_boundary *boundary;
 	const unsigned char *msg;
@@ -476,7 +511,7 @@
 	int end_boundary;
 
 	boundary = message_find_boundary(input, boundaries,
-					 boundary_size, TRUE);
+					 boundary_size, TRUE, has_nuls);
 	if (boundary == NULL)
 		return NULL;
 
@@ -486,11 +521,12 @@
 		end_boundary = msg[0] == '-' && msg[1] == '-';
 
 	/* skip the rest of the line */
-	message_skip_line(input, boundary_size, !end_boundary);
+	message_skip_line(input, boundary_size, !end_boundary, has_nuls);
 
 	if (end_boundary) {
 		/* skip the footer */
-		return message_parse_body(input, boundary->next, boundary_size);
+		return message_parse_body(input, boundary->next,
+					  boundary_size, has_nuls);
 	}
 
 	return boundary == NULL ? NULL : boundary->part;
@@ -615,7 +651,7 @@
 			if (colon_pos == UINT_MAX) {
 				/* header name is huge. just skip it. */
 				message_skip_line(ctx->input, ctx->hdr_size,
-						  TRUE);
+						  TRUE, &ctx->has_nuls);
 				continue;
 			}
 
@@ -645,14 +681,21 @@
 						/* end of headers, or error */
 						break;
 					}
+
+					if (msg[i] == '\0')
+						ctx->has_nuls = TRUE;
 				}
 			}
 		}
 
 		/* find '\n' */
 		for (i = startpos; i < parse_size; i++) {
-			if (msg[i] == '\n')
-				break;
+			if (msg[i] <= '\n') {
+				if (msg[i] == '\n')
+					break;
+				if (msg[i] == '\0')
+					ctx->has_nuls = TRUE;
+			}
 		}
 
 		if (i < parse_size) {

Index: message-parser.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-parser.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- message-parser.h	26 Mar 2003 17:29:02 -0000	1.19
+++ message-parser.h	4 Jun 2003 15:57:58 -0000	1.20
@@ -15,7 +15,10 @@
 	MESSAGE_PART_FLAG_TEXT			= 0x08,
 
 	/* content-transfer-encoding: binary */
-	MESSAGE_PART_FLAG_BINARY		= 0x10
+	MESSAGE_PART_FLAG_BINARY		= 0x10,
+
+	/* message part header or body contains NULs */
+	MESSAGE_PART_FLAG_HAS_NULS		= 0x20
 };
 
 struct message_part {

Index: message-send.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-send.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- message-send.c	26 Apr 2003 21:52:38 -0000	1.17
+++ message-send.c	4 Jun 2003 15:57:58 -0000	1.18
@@ -9,13 +9,14 @@
 
 off_t message_send(struct ostream *output, struct istream *input,
 		   const struct message_size *msg_size,
-		   uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr)
+		   uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr,
+		   int fix_nuls)
 {
 	const unsigned char *msg;
 	uoff_t old_limit, limit;
 	size_t i, size;
 	off_t ret;
-	int cr_skipped, add_cr;
+	int cr_skipped, add;
 
 	if (last_cr != NULL)
 		*last_cr = -1;
@@ -27,7 +28,7 @@
 	if (max_virtual_size > msg_size->virtual_size - virtual_skip)
 		max_virtual_size = msg_size->virtual_size - virtual_skip;
 
-	if (msg_size->physical_size == msg_size->virtual_size) {
+	if (msg_size->physical_size == msg_size->virtual_size && !fix_nuls) {
 		/* no need to kludge with CRs, we can use sendfile() */
 		i_stream_skip(input, virtual_skip);
 
@@ -46,7 +47,7 @@
 	ret = 0;
 	while (max_virtual_size > 0 &&
 	       i_stream_read_data(input, &msg, &size, 0) > 0) {
-		add_cr = FALSE;
+		add = '\0';
 		for (i = 0; i < size && max_virtual_size > 0; i++) {
 			max_virtual_size--;
 
@@ -54,9 +55,12 @@
 				if ((i == 0 && !cr_skipped) ||
 				    (i > 0 && msg[i-1] != '\r')) {
 					/* missing CR */
-					add_cr = TRUE;
+					add = '\r';
 					break;
 				}
+			} else if (msg[i] == '\0') {
+				add = 128;
+				break;
 			}
 		}
 
@@ -64,11 +68,12 @@
 		if (o_stream_send(output, msg, i) < 0)
 			return -1;
 
-		if (add_cr) {
+		if (add != '\0') {
 			ret++;
-			if (o_stream_send(output, "\r", 1) < 0)
+			if (o_stream_send(output, &add, 1) < 0)
 				return -1;
-			cr_skipped = TRUE;
+			cr_skipped = add == '\r';
+			if (add == 128) i++;
 		} else {
 			cr_skipped = i > 0 && msg[i-1] == '\r';
 		}

Index: message-send.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-send.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- message-send.h	26 Apr 2003 21:52:38 -0000	1.10
+++ message-send.h	4 Jun 2003 15:57:58 -0000	1.11
@@ -10,7 +10,8 @@
    known. Returns number of bytes sent, or -1 if error. */
 off_t message_send(struct ostream *output, struct istream *input,
 		   const struct message_size *msg_size,
-		   uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr);
+		   uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr,
+		   int fix_nuls);
 
 /* Skip number of virtual bytes from putfer. msg_size is updated if it's not
    NULL. If cr_skipped is TRUE and first character is \n, it's not treated as

Index: message-size.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-size.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- message-size.c	26 Apr 2003 21:52:38 -0000	1.12
+++ message-size.c	4 Jun 2003 15:57:58 -0000	1.13
@@ -5,18 +5,24 @@
 #include "message-parser.h"
 #include "message-size.h"
 
-void message_get_header_size(struct istream *input, struct message_size *hdr)
+void message_get_header_size(struct istream *input, struct message_size *hdr,
+			     int *has_nuls)
 {
 	const unsigned char *msg;
 	size_t i, size, startpos, missing_cr_count;
 
 	memset(hdr, 0, sizeof(struct message_size));
+	if (has_nuls != NULL)
+		*has_nuls = FALSE;
 
 	missing_cr_count = 0; startpos = 0;
 	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size; i++) {
-			if (msg[i] != '\n')
+			if (msg[i] != '\n') {
+				if (msg[i] == '\0' && has_nuls != NULL)
+					*has_nuls = TRUE;
 				continue;
+			}
 
 			hdr->lines++;
 			if (i == 0 || msg[i-1] != '\r') {
@@ -56,13 +62,15 @@
 }
 
 void message_get_body_size(struct istream *input, struct message_size *body,
-			   uoff_t max_virtual_size, int *last_cr)
+			   uoff_t max_virtual_size, int *last_cr, int *has_nuls)
 {
 	const unsigned char *msg;
 	size_t i, size, startpos, missing_cr_count;
 	int cr;
 
 	memset(body, 0, sizeof(struct message_size));
+	if (has_nuls != NULL)
+		*has_nuls = FALSE;
 
 	cr = 0;
 	missing_cr_count = 0; startpos = 0;
@@ -72,7 +80,10 @@
 		for (i = startpos; i < size && max_virtual_size > 0; i++) {
 			max_virtual_size--;
 
-			if (msg[i] == '\n') {
+			if (msg[i] == '\0') {
+				if (has_nuls != NULL)
+					*has_nuls = TRUE;
+			} else if (msg[i] == '\n') {
 				if (i == 0 || msg[i-1] != '\r') {
 					/* missing CR */
 					missing_cr_count++;

Index: message-size.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-size.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- message-size.h	26 Apr 2003 21:52:38 -0000	1.10
+++ message-size.h	4 Jun 2003 15:57:58 -0000	1.11
@@ -9,12 +9,14 @@
 
 /* Calculate size of message header. Leave the input point to first
    character in body. */
-void message_get_header_size(struct istream *input, struct message_size *hdr);
+void message_get_header_size(struct istream *input, struct message_size *hdr,
+			     int *has_nuls);
 /* Calculate size of message body. Read only max_virtual_size virtual bytes,
    if you want it unlimited, use (uoff_t)-1. If last_cr is not NULL, it's set
    to 1 if last character is CR, 2 if it's virtual CR. */
 void message_get_body_size(struct istream *input, struct message_size *body,
-			   uoff_t max_virtual_size, int *last_cr);
+			   uoff_t max_virtual_size, int *last_cr,
+			   int *has_nuls);
 
 /* Sum contents of src into dest. */
 void message_size_add(struct message_size *dest,



More information about the dovecot-cvs mailing list