MIME iso-8859-1 extensions for mail headers.

RFC 2047 defines

Examples:

Subject: =?iso-8859-1?B?zvLi5fI6ICAgICAgTVBMQUIzLjQw?=

Subject:      =?iso-8859-1?B?zvLi5fI6ICAgICAgUElDcyBhbmQgYmF0dGVyeS1iYWNrdXAgU1
 JBTQ==?=

Subject:      =?iso-8859-1?Q?=CE=F2=E2=E5=F2:______Re:_PCB_AutoRouting_=28is_it
 _smart_w?=
              ay ? / really Dumb )

Subject:      Re: [PIC]: RSA =?iso-8859-1?Q?encryption=B7=B7?=

Subject:      [PICLIST] =?Iso-8859-1?Q?[ot]:_Strain_Gauges=3F?=

Subject:      [PICLIST] =?iso-8859-1?Q?_Re:_=5BPIC=5D:_RSA_encryption=B7=B7?=

Subject:      [PICLIST] =?iso-8859-1?Q?=5BEE=5D:TV_&_video_IC=B4s_!!?=

Subject:      [PICLIST] =?iso-8859-1?Q?=5BOT=5D:Scales_&_balances=B7?=


see also:

sample code:

iso8859.pl
/*
** RFC 2047 defines MIME extensions for mail headers.
**
** This function decodes that into binary/8bit data.
**
** Example:
**   =?iso-8859-1?q?I'm_called_?= =?iso-8859-1?q?Daniel?=
**
** Should result in "I'm called Daniel", but:
**
**   =?iso-8859-1?q?I'm_called?= Daniel
**
** Should result in "I'm called Daniel" too.
**
** Returns the newly allcated string, or the previous if nothing changed 
*/

static char *mdecodeRFC2047(char *string, int length)
{
    char *iptr = string;
    char *oldptr;
    char *storage = (char *)emalloc(length + 1);

    char *output = storage;

    char charset[129];
    char encoding[33];
    char blurb[129];
    char equal;
    int value;

    char didanything = FALSE;

    while (*iptr) {
	if (!strncmp(iptr, "=?", 2) &&
	    (3 == sscanf(iptr + 2, "%128[^?]?%32[^?]?%128[^ ]",
			 charset, encoding, blurb))) {
	    /* This is a full, valid 'encoded-word'. Decode! */
	    char *ptr = blurb;

	    ptr = strstr(blurb, "?=");
	    if (ptr) {
		*ptr = 0;
	    }
	    else {
		*output++ = *iptr++;
		/* it wasn't a real encoded-word */
		continue;
	    }
	    ptr = blurb;

	    didanything = TRUE;	/* yes, we decode something */

	    /* we could've done this with a %n in the sscanf, but we know all
	       sscanfs don't grok that */

	    iptr +=
		2 + strlen(charset) + 1 + strlen(encoding) + 1 +
		strlen(blurb) + 2;

	    if (!strcasecmp("q", encoding)) {
		/* quoted printable decoding */

		for (; *ptr; ptr++) {
		    switch (*ptr) {
		    case '=':
			sscanf(ptr + 1, "%02X", &value);
			*output++ = value;
			ptr += 2;
			break;
		    case '_':
			*output++ = ' ';
			break;
		    default:
			*output++ = *ptr;
			break;
		    }
		}
	    }
	    else if (!strcasecmp("b", encoding)) {
		/* base64 decoding */
		int len;
		base64Decode(ptr, output, &len);
		output += len - 1;
	    }
	    else {
		/* unsupported encoding type */
		strcpy(output, "<unknown>");
		output += 9;
	    }

	    oldptr = iptr;	/* save start position */

	    while (*iptr && isspace(*iptr))
		iptr++;		/* pass all whitespaces */

	    /* if this is an encoded word here, we should skip the passed
	       whitespaces. If it isn't an encoded-word, we should include the
	       whitespaces in the output. */

	    if (!strncmp(iptr, "=?", 2) &&
		(4 == sscanf(iptr + 2, "%128[^?]?%32[^?]?%128[^?]?%c",
			     charset, encoding, blurb, &equal)) &&
		('=' == equal)) {
		continue;	/* this IS an encoded-word, continue from here */
	    }
	    else
		/* this IS NOT an encoded-word, move back to the first whitespace */
		iptr = oldptr;
	}
	else
	    *output++ = *iptr++;
    }
    *output = 0;

    if (didanything) {
	/* this check prevents unneccessary strsav() calls if not needed */
	free(string);		/* free old memory */

#if DEBUG_PARSE
	/* debug display */
	printf("NEW: %s\n", storage);

	{
	    unsigned char *f;
	    puts("NEW:");
	    for (f = storage; f < output; f++) {
		if (isgraph(*f))
		    printf("%c", *f);
		else
		    printf("%02X", (unsigned char)*f);
	    }
	    puts("");
	}
#endif
	return storage;		/* return new */
    }
    else {
	free(storage);
	return string;
    }
}