X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Freceive.c;h=7980c324fc1d42c1bca0462928e4cecb89782d00;hb=45f35410b4bdd59614dd9811ee99aea6a5d1164c;hp=b152ceefb68173f5b1c2e1f5d2e8f8f2ea874c28;hpb=cff70eb1c1eb494ee5964dca33dc115181baafd7;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/receive.c b/src/src/receive.c index b152ceefb..7980c324f 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -906,7 +906,8 @@ a cut-down version of the state-machine above; we don't need to do leading-dot detection and unstuffing. Arguments: - fout a FILE to which to write the message; NULL if skipping + fout a FILE to which to write the message; NULL if skipping; + must be open for both writing and reading. Returns: One of the END_xxx values indicating why it stopped reading */ @@ -916,14 +917,44 @@ read_message_bdat_smtp(FILE *fout) { int linelength = 0, ch; enum CH_STATE ch_state = LF_SEEN; +BOOL fix_nl = FALSE; for(;;) { switch ((ch = (bdat_getc)(GETC_BUFFER_UNLIMITED))) { case EOF: return END_EOF; - case EOD: return END_DOT; /* normal exit */ case ERR: return END_PROTOCOL; + case EOD: + /* Nothing to get from the sender anymore. We check the last + character written to the spool. + + RFC 3030 states, that BDAT chunks are normal text, terminated by CRLF. + If we would be strict, we would refuse such broken messages. + But we are liberal, so we fix it. It would be easy just to append + the "\n" to the spool. + + But there are some more things (line counting, message size calculation and such), + that would need to be duplicated here. So we simply do some ungetc + trickery. + */ + if (fout) + { + if (fseek(fout, -1, SEEK_CUR) < 0) return END_PROTOCOL; + if (fgetc(fout) == '\n') return END_DOT; + } + + if (linelength == -1) /* \r already seen (see below) */ + { + DEBUG(D_receive) debug_printf("Add missing LF\n"); + bdat_ungetc('\n'); + continue; + } + DEBUG(D_receive) debug_printf("Add missing CRLF\n"); + bdat_ungetc('\r'); /* not even \r was seen */ + fix_nl = TRUE; + + continue; case '\0': body_zerocount++; break; } switch (ch_state) @@ -944,6 +975,7 @@ for(;;) else if (ch == '\r') { ch_state = CR_SEEN; + if (fix_nl) bdat_ungetc('\n'); continue; /* don't write CR */ } break; @@ -958,7 +990,7 @@ for(;;) else { message_size++; - if (fout != NULL && fputc('\n', fout) == EOF) return END_WERROR; + if (fout && fputc('\n', fout) == EOF) return END_WERROR; (void) cutthrough_put_nl(); if (ch == '\r') continue; /* don't write CR */ ch_state = MID_LINE;