diff options
Diffstat (limited to 'contrib/sendmail/src/mime.c')
| -rw-r--r-- | contrib/sendmail/src/mime.c | 110 |
1 files changed, 79 insertions, 31 deletions
diff --git a/contrib/sendmail/src/mime.c b/contrib/sendmail/src/mime.c index f5980bb481bea..32c0b478b597a 100644 --- a/contrib/sendmail/src/mime.c +++ b/contrib/sendmail/src/mime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1994, 1996-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1994 @@ -14,7 +14,7 @@ #include <sendmail.h> #include <string.h> -SM_RCSID("@(#)$Id: mime.c,v 8.125 2001/09/11 04:05:15 gshapiro Exp $") +SM_RCSID("@(#)$Id: mime.c,v 8.129 2002/03/13 07:28:05 gshapiro Exp $") /* ** MIME support. @@ -924,7 +924,7 @@ isboundary(line, boundaries) #endif /* MIME8TO7 */ #if MIME7TO8 -static int mime_fromqp __P((unsigned char *, unsigned char **, int, int)); +static int mime_fromqp __P((unsigned char *, unsigned char **, int)); /* ** MIME7TO8 -- output 7 bit encoded MIME body in 8 bit format @@ -936,7 +936,7 @@ static int mime_fromqp __P((unsigned char *, unsigned char **, int, int)); ** will be able to deal with encoded MIME bodies if it can parse MIME ** multipart messages. ** -** Note also that we wont be called unless it is a text/plain MIME +** Note also that we won't be called unless it is a text/plain MIME ** message, encoded base64 or QP and mailer flag '9' has been defined ** on mailer. ** @@ -971,6 +971,7 @@ mime7to8(mci, header, e) HDR *header; register ENVELOPE *e; { + int pxflags; register char *p; char *cte; char **pvp; @@ -1024,6 +1025,7 @@ mime7to8(mci, header, e) ** it is not base64. */ + pxflags = PXLF_MAPFROM; if (sm_strcasecmp(cte, "base64") == 0) { int c1, c2, c3, c4; @@ -1066,9 +1068,13 @@ mime7to8(mci, header, e) { if (*--fbufp != '\n' || (fbufp > fbuf && *--fbufp != '\r')) + { + pxflags |= PXLF_NOADDEOL; fbufp++; + } putxline((char *) fbuf, fbufp - fbuf, - mci, PXLF_MAPFROM); + mci, pxflags); + pxflags &= ~PXLF_NOADDEOL; fbufp = fbuf; } if (c3 == '=') @@ -1079,9 +1085,13 @@ mime7to8(mci, header, e) { if (*--fbufp != '\n' || (fbufp > fbuf && *--fbufp != '\r')) + { + pxflags |= PXLF_NOADDEOL; fbufp++; + } putxline((char *) fbuf, fbufp - fbuf, - mci, PXLF_MAPFROM); + mci, pxflags); + pxflags &= ~PXLF_NOADDEOL; fbufp = fbuf; } if (c4 == '=') @@ -1092,28 +1102,44 @@ mime7to8(mci, header, e) { if (*--fbufp != '\n' || (fbufp > fbuf && *--fbufp != '\r')) + { + pxflags |= PXLF_NOADDEOL; fbufp++; + } putxline((char *) fbuf, fbufp - fbuf, - mci, PXLF_MAPFROM); + mci, pxflags); + pxflags &= ~PXLF_NOADDEOL; fbufp = fbuf; } } } else { + int off; + /* quoted-printable */ + pxflags |= PXLF_NOADDEOL; fbufp = fbuf; - while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf) - != NULL) + while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, + sizeof buf) != NULL) { - if (mime_fromqp((unsigned char *) buf, &fbufp, 0, - &fbuf[MAXLINE] - fbufp) == 0) + off = mime_fromqp((unsigned char *) buf, &fbufp, + &fbuf[MAXLINE] - fbufp); +again: + if (off < -1) continue; if (fbufp - fbuf > 0) putxline((char *) fbuf, fbufp - fbuf - 1, mci, - PXLF_MAPFROM); + pxflags); fbufp = fbuf; + if (off >= 0 && buf[off] != '\0') + { + off = mime_fromqp((unsigned char *) (buf + off), + &fbufp, + &fbuf[MAXLINE] - fbufp); + goto again; + } } } @@ -1121,8 +1147,18 @@ mime7to8(mci, header, e) if (fbufp > fbuf) { *fbufp = '\0'; - putxline((char *) fbuf, fbufp - fbuf, mci, PXLF_MAPFROM); + putxline((char *) fbuf, fbufp - fbuf, mci, pxflags); } + + /* + ** The decoded text may end without an EOL. Since this function + ** is only called for text/plain MIME messages, it is safe to + ** add an extra one at the end just in case. This is a hack, + ** but so is auto-converting MIME in the first place. + */ + + putline("", mci); + if (tTd(43, 3)) sm_dprintf("\t\t\tmime7to8 => %s to 8bit done\n", cte); } @@ -1149,31 +1185,47 @@ static char index_hex[128] = # define HEXCHAR(c) (((c) < 0 || (c) > 127) ? -1 : index_hex[(c)]) +/* +** MIME_FROMQP -- decode quoted printable string +** +** Parameters: +** infile -- input (encoded) string +** outfile -- output string +** maxlen -- size of output buffer +** +** Returns: +** -2 if decoding failure +** -1 if infile completely decoded into outfile +** >= 0 is the position in infile decoding +** reached before maxlen was reached +*/ + static int -mime_fromqp(infile, outfile, state, maxlen) +mime_fromqp(infile, outfile, maxlen) unsigned char *infile; unsigned char **outfile; - int state; /* Decoding body (0) or header (1) */ int maxlen; /* Max # of chars allowed in outfile */ { int c1, c2; int nchar = 0; + unsigned char *b; - if (maxlen < 0) + /* decrement by one for trailing '\0', at least one other char */ + if (--maxlen < 1) return 0; - while ((c1 = *infile++) != '\0') + b = infile; + while ((c1 = *infile++) != '\0' && nchar < maxlen) { if (c1 == '=') { - if ((c1 = *infile++) == 0) + if ((c1 = *infile++) == '\0') break; if (c1 == '\n' || (c1 = HEXCHAR(c1)) == -1) { - /* ignore it */ - if (state == 0) - return 0; + /* ignore it and the rest of the buffer */ + return -2; } else { @@ -1186,27 +1238,23 @@ mime_fromqp(infile, outfile, state, maxlen) } } while ((c2 = HEXCHAR(c2)) == -1); - if (c2 == -1 || ++nchar > maxlen) + if (c2 == -1) break; - + nchar++; *(*outfile)++ = c1 << 4 | c2; } } else { - if (state == 1 && c1 == '_') - c1 = ' '; - - if (++nchar > maxlen) - break; - + nchar++; *(*outfile)++ = c1; - if (c1 == '\n') break; } } *(*outfile)++ = '\0'; - return 1; + if (nchar >= maxlen) + return (infile - b - 1); + return -1; } #endif /* MIME7TO8 */ |
