--
On Fri, 2003-12-19 at 19:11, Kjetil Torgrim Homme wrote:
> On Fri, 2003-12-19 at 10:52, Philip Hazel wrote:
> > Possibly. I need to think about this. "If first line of DATA is
> > terminated by CRLF, then fixup bare LF in header lines" might indeed be
> > the best heuristic.
>
> I'll have a look at it.
my apologies for taking so long for something so small, please consider
the enclosed patch for the next release of Exim.
notice:
* the heuristic is applied regardless of the source of the message.
* if strict mode has been entered, "LF . LF" will not terminate DATA;
however, "CR LF . LF" will. I don't think adding the code to be
pedantically correct is worthwhile, it's certainly not a common
occurence to terminate DATA within headers, and that dot should have
been dot stuffed by an RFC compliant sender.
--
Kjetil T.
--
--- exim-4.30/src/receive.c.~1~ Mon Dec 1 11:15:41 2003
+++ exim-4.30/src/receive.c Thu Feb 19 06:32:11 2004
@@ -956,6 +956,7 @@
BOOL had_zero = FALSE;
BOOL smtp_yield = TRUE;
BOOL yield = FALSE;
+enum { CRLF_UNKNOWN, CRLF_STRICT, CRLF_LENIENT } crlf_mode = CRLF_UNKNOWN;
BOOL resents_exist = FALSE;
uschar *resent_prefix = US"";
@@ -1142,8 +1143,23 @@
other MTAs accept this. We are therefore forced into this "liberalisation"
too. */
- if (ch == EOF || ch == '\n') goto EOL;
-
+ if (ch == EOF) goto EOL;
+ if (ch == '\n')
+ switch (crlf_mode)
+ {
+ case CRLF_UNKNOWN:
+ crlf_mode = CRLF_LENIENT;
+ /* Fall through */
+ case CRLF_LENIENT:
+ goto EOL;
+ case CRLF_STRICT:
+ /* The very first line of the DATA input was properly CR LF
+ terminated, so assume that the complete message has proper CR LF
+ endings. In such messages, bare linefeeds must be escaped. */
+ next->text[ptr++] = '\n';
+ message_size++;
+ ch = ' ';
+ }
/* This is not the end of the line. If this is SMTP input and this is
the first character in the line and it is a "." character, ignore it.
@@ -1185,12 +1201,18 @@
}
}
- /* If CR is immediately followed by LF, end the line, ignoring the CR. */
+ /* If CR is immediately followed by LF, end the line, ignoring the CR.
+ If this is the first line, enter strict mode, requiring every line to
+ be terminated by CR LF. */
if (ch == '\r')
{
ch = (receive_getc)();
- if (ch == '\n') goto EOL;
+ if (ch == '\n')
+ {
+ if (crlf_mode == CRLF_UNKNOWN) crlf_mode = CRLF_STRICT;
+ goto EOL;
+ }
/* Otherwise, put back the character after CR, and turn the bare CR
into LF SP. */
--