Hi,

as I recently found out courier does not check for CRLF sequences at the end 
of lines. It just blindy inserts CR. In case there's already a CR there it 
will still insert, causing invalid IMAP transactions.

Here is a patch that fixes at least the easy places to correctly send out the 
mails. The patch to the POP3 server already proved that it works. There are 
more places in imap/fetch.c that I suspect to possibly cause trouble (for 
example dofetchmsgbody) but they are less easy to fix.

With this patch it is checked first if the previous character was CR before CR 
is inserted. There is also a very small change in behaviour int the second 
hunk: the for look to find the end of line at the bottom dofetchheadersbuf() 
does not need to search the buffer starting at the first character to find 
LF. The "if" before already checked that and in case of a match jumped 
somewhere else. You can see the complete thing in the second hunk of the 
diff.

Greetings,

Eike
diff -Naurp courier-imap-4.1.1-orig/imap/fetch.c courier-imap-4.1.1/imap/fetch.c
--- courier-imap-4.1.1-orig/imap/fetch.c	2004-06-09 00:44:20.000000000 +0200
+++ courier-imap-4.1.1/imap/fetch.c	2006-05-31 13:31:08.000000000 +0200
@@ -1003,7 +1003,7 @@ char	buf[BUFSIZ+2];
 int	goodheader;
 unsigned long skipping;
 unsigned long cnt;
-char	*p;
+char	*p, oldp = 0;
 int	ii;
 
 	rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
@@ -1098,24 +1098,27 @@ int	ii;
 			}
 		}
 		--skipping;
-		++p;
+		oldp = *p++;
 	}
 
 	while (cnt)
 	{
 		if (*p == '\n')
 		{
-			writes("\r");
-			if (--cnt == 0)	break;
+			if (oldp != '\r') {
+				writes("\r");
+				if (--cnt == 0)	break;
+			}
 			writes("\n");
 			--cnt;
-			++p;
+			oldp = *p++;
 			continue;
 		}
-		for (i=0; i<cnt; i++)
+		for (i=1; i<cnt; i++)
 			if (p[i] == '\n')
 				break;
 		writemem(p, i);
+		oldp = p[i - 1];
 		p += i;
 		cnt -= i;
 		header_count += i;
@@ -1181,6 +1184,8 @@ struct	fetchheaderinfo finfo;
 		goodheader= (*headerfunc)(fi, "");
 		while (left)
 		{
+			char oldc = 0;
+
 			for (i=0; i<sizeof(buf1)-1 && i<left; i++)
 			{
 				c=getc(fp);
@@ -1242,10 +1247,14 @@ struct	fetchheaderinfo finfo;
 				if (c == '\n')
 				{
 					(*func)(&finfo, buf1, i);
-					buf1[0]='\r';
-					i=1;
+					if (oldc != '\r') {
+						buf1[0]='\r';
+						i=1;
+					} else
+						i = 0;
 				}
 				buf1[i++]=c;
+				oldc = c;
 				if (c == '\n')	break;
 			}
 			(*func)(&finfo, buf1, i);
@@ -1288,7 +1297,7 @@ static void rfc822(FILE *fp, struct fetc
 	struct rfc2045 *rfcp)
 {
 unsigned long n=0;
-int	c;
+int	c, oldc = 0;
 char	buf[BUFSIZ];
 unsigned long i;
 
@@ -1303,7 +1312,9 @@ unsigned long i;
 	while ((c=getc(fp)) != EOF)
 	{
 		++n;
-		if (c == '\n')	++n;
+		if ((c == '\n') && (oldc != '\r'))
+			++n;
+		oldc = c;
 	}
 
 	if (fseek(fp, 0L, SEEK_SET) == -1)
@@ -1327,7 +1338,8 @@ unsigned long i;
 				writemem(buf, i);
 				i=0;
 			}
-			buf[i++]='\r';
+			if (oldc != '\r')
+				buf[i++]='\r';
 			if (--n == 0)	break;
 		}
 
@@ -1337,6 +1349,7 @@ unsigned long i;
 			i=0;
 		}
 		buf[i++]=c;
+		oldc = c;
 		--n;
 		++body_count;
 	}
@@ -1348,7 +1361,7 @@ static void rfc822header(FILE *fp, struc
 	struct rfc2045 *rfcp)
 {
 unsigned long n=0;
-int	c;
+int	c, oldc = 0;
 char	buf[BUFSIZ];
 unsigned long i;
 int	eol;
@@ -1369,9 +1382,11 @@ int	eol;
 		if (c != '\n')
 		{
 			eol=0;
+			oldc = c;
 			continue;
 		}
-		++n;
+		if (oldc != '\r')
+			++n;
 		if (eol)	break;
 		eol=1;
 	}
@@ -1389,6 +1404,7 @@ int	eol;
 	i=0;
 	while (n)
 	{
+		oldc = c;
 		c=getc(fp);
 		if (c == '\n')
 		{
@@ -1397,7 +1413,8 @@ int	eol;
 				writemem(buf, i);
 				i=0;
 			}
-			buf[i++]='\r';
+			if (oldc != '\r')
+				buf[i++]='\r';
 			if (--n == 0)	break;
 		}
 
@@ -1420,7 +1437,7 @@ static void rfc822text(FILE *fp, struct 
 off_t start_pos, end_pos, start_body;
 off_t nlines, nbodylines;
 unsigned long i;
-int	c;
+int	oldc = 0;
 char	buf[BUFSIZ];
 unsigned long l;
 
@@ -1444,6 +1461,8 @@ unsigned long l;
 	l=0;
 	while (i)
 	{
+		int c;
+
 		c=getc(fp);
 		if (c == EOF)
 		{
@@ -1459,7 +1478,8 @@ unsigned long l;
 		if (c == '\n' && i)
 		{
 			--i;
-			buf[l++]='\r';
+			if (oldc != '\r')
+				buf[l++]='\r';
 			if (l >= sizeof(BUFSIZ))
 			{
 				writemem(buf, l);
@@ -1467,6 +1487,7 @@ unsigned long l;
 			}
 		}
 		buf[l++]=c;
+		oldc = c;
 		++body_count;
 	}
 	writemem(buf, l);
diff -Naurp courier-imap-4.1.1-orig/imap/pop3dserver.c courier-imap-4.1.1/imap/pop3dserver.c
--- courier-imap-4.1.1-orig/imap/pop3dserver.c	2005-10-01 17:32:16.000000000 +0200
+++ courier-imap-4.1.1/imap/pop3dserver.c	2006-05-31 11:32:36.000000000 +0200
@@ -133,11 +133,18 @@ int	c, lastc;
 	lastc='\n';
 	while ((c=getc(f)) >= 0)
 	{
-		if (c == '\n')	++m->size;
+		/* LF will be expanded to CRLF if CR is not present */
+		if ((c == '\n') && (lastc != '\r'))
+			++m->size;
 		++m->size;
 		lastc=c;
 	}
-	if (lastc != '\n')	m->size += 2;
+	if (lastc != '\n') {
+		if (lastc != '\r')
+			m->size += 2;
+		else
+			m->size++;
+	}
 
 	if (ferror(f))
 	{
@@ -668,15 +675,20 @@ unsigned long *cntr;
 			{
 				if (inheader)
 				{
-					if (c == '\n')	inheader=0;
+					if ((c == '\n') || (c == '\r'))
+						inheader=0;
 				}
 				else if ( (*lptr)-- == 0)	break;
 			}
 
 			if (c == '.')
 				printchar('.');
+		} else if ((lastc == '\r') && (c != '\n')) {
+			printchar('\n');
+			lastc = '\n';
 		}
-		if (c == '\n')	printchar('\r');
+		if ((c == '\n') && (lastc != '\r'))
+			printchar('\r');
 		printchar(c);
 		++*cntr;
 	}
@@ -687,7 +699,12 @@ unsigned long *cntr;
 		acctout("INFO: I/O error disconnect");
 		exit(1);
 	}
-	if (lastc != '\n')	printed(printf("\r\n"));
+	if (lastc != '\n') {
+		if (lastc != '\r')
+			printed(printf("\r\n"));
+		else
+			printchar('\n');
+	}
 	printed(printf(".\r\n"));
 	fflush(stdout);
 	fclose(f);

Attachment: pgpvmtS2ybLNK.pgp
Description: PGP signature

_______________________________________________
Courier-imap mailing list
[email protected]
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-imap

Reply via email to