From f2c6d1760ac6971fcc63c9dbde8752dc721c6bc3 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sat, 9 Jan 1999 23:52:27 +0000 Subject: Henrik's fix for mimedecode. svn path=/trunk/; revision=2345 --- Makefile.in | 6 +++--- NEWS | 3 +++ fetchmail.man | 4 ---- unmime.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/Makefile.in b/Makefile.in index 98e86efd..e71237b2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,7 +4,7 @@ # So just uncomment all the lines marked QNX. PACKAGE = fetchmail -VERSION = 4.7.5 +VERSION = 4.7.6 SUBDIRS = @INTLSUB@ @POSUB@ @@ -121,8 +121,8 @@ rfc822: rfc822.c gcc -DTESTMAIN -g rfc822.c -o rfc822 # Stand-alone MIME decoder -unmime: unmime.c base64.c rfc822.c xmalloc.c error.c memmove.c - $(CC) -DSTANDALONE -g -o $@ $^ +unmime: unmime.c base64.c rfc822.c xmalloc.c error.c + $(CC) -DSTANDALONE -DHAVE_CONFIG_H -I. -g -o $@ $^ .c.o: $(CC) $(defines) -c $(CPFLAGS) -I$(srcdir) -I. $(CEFLAGS) $(CFLAGS) $< diff --git a/NEWS b/NEWS index 346d3037..0a44c25e 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ Release Notes: +fetchmail-4.7.6 (): +* Henrik Storner's fix for mimedecode + fetchmail-4.7.5 (Sat Jan 9 17:01:13 EST 1999): * Issue proper logout after running fetchmail -c * Fix prefix problem with internationalized version. diff --git a/fetchmail.man b/fetchmail.man index 04344264..a8d13eb7 100644 --- a/fetchmail.man +++ b/fetchmail.man @@ -1750,10 +1750,6 @@ in foreground while a background fetchmail is running will do whichever of these is appropriate to wake it up. .SH BUGS AND KNOWN PROBLEMS -Enabling the `mimedecode' option (which defaults to off) may render -invalid any PGP signatures attached to mail with quoted-printable headers. -This bug will be fixed in a future version. -.PP The RFC822 address parser used in multidrop mode chokes on some @-addresses that are technically legal but bizarre. Strange uses of quoting and embedded comments are likely to confuse it. diff --git a/unmime.c b/unmime.c index cedc6737..753c9aa1 100644 --- a/unmime.c +++ b/unmime.c @@ -250,6 +250,7 @@ static int BodyState = S_BODY_DATA; * a quoted-printable body part. */ static int CurrEncodingIsQP = 0; +static int CurrTypeNeedsDecode = 0; /* * Delimiter for multipart messages. RFC 2046 states that this must @@ -325,6 +326,36 @@ static char *GetBoundary(char *CntType) } +int CheckContentType(char *CntType) +{ + /* + * Static array of Content-Type's for which we will do + * quoted-printable decoding, if requested. + * It is probably wise to do this only on known text-only types; + * be really careful if you change this. + */ + + static char *DecodedTypes[] = { + "text/", /* Will match ALL content-type's starting with 'text/' */ + "message/rfc822", + NULL + }; + + char *p = CntType; + int i; + + /* Skip whitespace, if any */ + for (; isspace(*p); p++) ; + + for (i=0; + (DecodedTypes[i] && + (strncasecmp(p, DecodedTypes[i], strlen(DecodedTypes[i])))); + i++) ; + + return (DecodedTypes[i] != NULL); +} + + /* * This routine does three things: * 1) It determines - based on the message headers - whether the @@ -336,8 +367,9 @@ static char *GetBoundary(char *CntType) * - All other messages are assumed NOT to include 8-bit data. * 2) It determines the delimiter-string used in multi-part message * bodies. - * 3) It sets the initial values of the CurrEncodingIsQP and BodyState - * variables, from the header contents. + * 3) It sets the initial values of the CurrEncodingIsQP, + * CurrTypeNeedsDecode, and BodyState variables, from the header + * contents. * * The return value is a bitmask. */ @@ -350,7 +382,7 @@ int MimeBodyType(unsigned char *hdrs, int WantDecode) /* Setup for a standard (no MIME, no QP, 7-bit US-ASCII) message */ MultipartDelimiter[0] = '\0'; - CurrEncodingIsQP = 0; + CurrEncodingIsQP = CurrTypeNeedsDecode = 0; BodyState = S_BODY_DATA; BodyType = 0; @@ -418,6 +450,8 @@ int MimeBodyType(unsigned char *hdrs, int WantDecode) /* Done looking through the headers, now check what they say */ if ((MimeVer != NULL) && (strcmp(MimeVer, "1.0") == 0)) { + CurrTypeNeedsDecode = CheckContentType(CntType); + /* Check Content-Type to see if this is a multipart message */ if ( (CntType != NULL) && ((strncasecmp(CntType, "multipart/", 10) == 0) || @@ -442,7 +476,7 @@ int MimeBodyType(unsigned char *hdrs, int WantDecode) if (strcasecmp(XferEnc, "quoted-printable") == 0) { CurrEncodingIsQP = 1; BodyType = (MSG_IS_8BIT | MSG_NEEDS_DECODE); - if (WantDecode) { + if (WantDecode && CurrTypeNeedsDecode) { SetEncoding8bit(XferEncOfs); } } @@ -546,17 +580,27 @@ int UnMimeBodyline(unsigned char **bufp, int collapsedoubledot) switch (BodyState) { case S_BODY_HDR: UnMimeHeader(buf); /* Headers in body-parts can be encoded, too! */ - if (strncasecmp("Content-Transfer-Encoding:", buf, 26) == 0) { + if ((*buf == '\0') || (*buf == '\n') || (strcmp(buf, "\r\n") == 0)) { + BodyState = S_BODY_DATA; + } + else if (strncasecmp("Content-Transfer-Encoding:", buf, 26) == 0) { char *XferEnc; XferEnc = nxtaddr(buf); if ((XferEnc != NULL) && (strcasecmp(XferEnc, "quoted-printable") == 0)) { CurrEncodingIsQP = 1; - SetEncoding8bit(buf); + + /* Hmm ... we cannot be really sure that CurrTypeNeedsDecode + has been set - we may not have seen the Content-Type header + yet. But *usually* the Content-Type header comes first, so + this will work. And there is really no way of doing it + "right" as long as we stick with the line-by-line processing. */ + if (CurrTypeNeedsDecode) SetEncoding8bit(buf); } } - else if ((*buf == '\0') || (*buf == '\n') || (strcmp(buf, "\r\n") == 0)) - BodyState = S_BODY_DATA; + else if (strncasecmp("Content-Type:", buf, 13) == 0) { + CurrTypeNeedsDecode = CheckContentType(nxtaddr(buf)); + } *bufp = (buf + strlen(buf)); break; @@ -565,10 +609,10 @@ int UnMimeBodyline(unsigned char **bufp, int collapsedoubledot) if ((*MultipartDelimiter) && (strncmp(buf, MultipartDelimiter, strlen(MultipartDelimiter)) == 0)) { BodyState = S_BODY_HDR; - CurrEncodingIsQP = 0; + CurrEncodingIsQP = CurrTypeNeedsDecode = 0; } - if (CurrEncodingIsQP) + if (CurrEncodingIsQP && CurrTypeNeedsDecode) ret = DoOneQPLine(bufp, collapsedoubledot); else *bufp = (buf + strlen(buf)); @@ -584,6 +628,7 @@ int UnMimeBodyline(unsigned char **bufp, int collapsedoubledot) #include char *program_name = "unmime"; +int outlevel = 0; #define BUFSIZE_INCREMENT 4096 -- cgit v1.2.3