diff options
author | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:18:09 +0000 |
---|---|---|
committer | Tatsuya Kinoshita <tats@vega.ocn.ne.jp> | 2011-05-04 07:18:09 +0000 |
commit | 5f8e0f8ef9a422691dd72e8a953a42a41478fcb4 (patch) | |
tree | 4b2df4796a534793648b3c4fc532fc36bd0cd525 /mimehead.c | |
parent | Releasing debian version 0.3-2.4 (diff) | |
download | w3m-debian/0.5.1-1.tar.gz w3m-debian/0.5.1-1.zip |
Releasing debian version 0.5.1-1debian/0.5.1-1
Diffstat (limited to '')
-rw-r--r-- | mimehead.c | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/mimehead.c b/mimehead.c new file mode 100644 index 0000000..78997e0 --- /dev/null +++ b/mimehead.c @@ -0,0 +1,367 @@ +/* $Id: mimehead.c,v 1.10 2003/10/05 18:52:51 ukai Exp $ */ +/* + * MIME header support by Akinori ITO + */ + +#include <sys/types.h> +#include "fm.h" +#include "myctype.h" +#include "Str.h" + +#define MIME_ENCODED_LINE_LIMIT 80 +#define MIME_ENCODED_WORD_LENGTH_OFFSET 18 +#define MIME_ENCODED_WORD_LENGTH_ESTIMATION(x) \ + (((x)+2)*4/3+MIME_ENCODED_WORD_LENGTH_OFFSET) +#define MIME_DECODED_WORD_LENGTH_ESTIMATION(x) \ + (((x)-MIME_ENCODED_WORD_LENGTH_OFFSET)/4*3) +#define J_CHARSET "ISO-2022-JP" + +#define BAD_BASE64 255 + +static + unsigned char +c2e(char x) +{ + if ('A' <= x && x <= 'Z') + return (x) - 'A'; + if ('a' <= x && x <= 'z') + return (x) - 'a' + 26; + if ('0' <= x && x <= '9') + return (x) - '0' + 52; + if (x == '+') + return 62; + if (x == '/') + return 63; + return BAD_BASE64; +} + +static + int +ha2d(char x, char y) +{ + int r = 0; + + if ('0' <= x && x <= '9') + r = x - '0'; + else if ('A' <= x && x <= 'F') + r = x - 'A' + 10; + else if ('a' <= x && x <= 'f') + r = x - 'a' + 10; + + r <<= 4; + + if ('0' <= y && y <= '9') + r += y - '0'; + else if ('A' <= y && y <= 'F') + r += y - 'A' + 10; + else if ('a' <= y && y <= 'f') + r += y - 'a' + 10; + + return r; + +} + +Str +decodeB(char **ww) +{ + unsigned char c[4]; + char *wp = *ww; + char d[3]; + int i, n_pad; + Str ap = Strnew_size(strlen(wp)); + + n_pad = 0; + while (1) { + for (i = 0; i < 4; i++) { + c[i] = *(wp++); + if (*wp == '\0' || *wp == '?') { + i++; + for (; i < 4; i++) { + c[i] = '='; + } + break; + } + } + if (c[3] == '=') { + n_pad++; + c[3] = 'A'; + if (c[2] == '=') { + n_pad++; + c[2] = 'A'; + } + } + for (i = 0; i < 4; i++) { + c[i] = c2e(c[i]); + if (c[i] == BAD_BASE64) { + *ww = wp; + return ap; + } + } + d[0] = ((c[0] << 2) | (c[1] >> 4)); + d[1] = ((c[1] << 4) | (c[2] >> 2)); + d[2] = ((c[2] << 6) | c[3]); + for (i = 0; i < 3 - n_pad; i++) { + Strcat_char(ap, d[i]); + } + if (n_pad || *wp == '\0' || *wp == '?') + break; + } + *ww = wp; + return ap; +} + +Str +decodeU(char **ww) +{ + unsigned char c1, c2; + char *w = *ww; + int n, i; + Str a; + + if (*w <= 0x20 || *w >= 0x60) + return Strnew_size(0); + n = *w - 0x20; + a = Strnew_size(n); + for (w++, i = 2; *w != '\0' && n; n--) { + c1 = (w[0] - 0x20) % 0x40; + c2 = (w[1] - 0x20) % 0x40; + Strcat_char(a, (c1 << i) | (c2 >> (6 - i))); + if (i == 6) { + w += 2; + i = 2; + } + else { + w++; + i += 2; + } + } + return a; +} + +/* RFC2047 (4.2. The "Q" encoding) */ +Str +decodeQ(char **ww) +{ + char *w = *ww; + Str a = Strnew_size(strlen(w)); + + for (; *w != '\0' && *w != '?'; w++) { + if (*w == '=') { + w++; + Strcat_char(a, ha2d(*w, *(w + 1))); + w++; + } + else if (*w == '_') { + Strcat_char(a, ' '); + } + else + Strcat_char(a, *w); + } + *ww = w; + return a; +} + +/* RFC2045 (6.7. Quoted-Printable Content-Transfer-Encoding) */ +Str +decodeQP(char **ww) +{ + char *w = *ww; + Str a = Strnew_size(strlen(w)); + + for (; *w != '\0'; w++) { + if (*w == '=') { + w++; + if (*w == '\n' || *w == '\r' || *w == ' ' || *w == '\t') { + while (*w != '\n' && *w != '\0') + w++; + if (*w == '\0') + break; + } + else { + if (*w == '\0' || *(w + 1) == '\0') + break; + Strcat_char(a, ha2d(*w, *(w + 1))); + w++; + } + } + else + Strcat_char(a, *w); + } + *ww = w; + return a; +} + +#ifdef USE_M17N +Str +decodeWord(char **ow, wc_ces * charset) +#else +Str +decodeWord0(char **ow) +#endif +{ +#ifdef USE_M17N + wc_ces c; +#endif + char *p, *w = *ow; + char method; + Str a = Strnew(); + Str tmp = Strnew(); + + if (*w != '=' || *(w + 1) != '?') + goto convert_fail; + w += 2; + for (; *w != '?'; w++) { + if (*w == '\0') + goto convert_fail; + Strcat_char(tmp, *w); + } +#ifdef USE_M17N + c = wc_guess_charset(tmp->ptr, 0); + if (!c) + goto convert_fail; +#else + if (strcasecmp(tmp->ptr, "ISO-8859-1") != 0 && strcasecmp(tmp->ptr, "US_ASCII") != 0) + /* NOT ISO-8859-1 encoding ... don't convert */ + goto convert_fail; +#endif + w++; + method = *(w++); + if (*w != '?') + goto convert_fail; + w++; + p = w; + switch (TOUPPER(method)) { + case 'B': + a = decodeB(&w); + break; + case 'Q': + a = decodeQ(&w); + break; + default: + goto convert_fail; + } + if (p == w) + goto convert_fail; + if (*w == '?') { + w++; + if (*w == '=') + w++; + } + *ow = w; +#ifdef USE_M17N + *charset = c; +#endif + return a; + + convert_fail: + return Strnew(); +} + +/* + * convert MIME encoded string to the original one + */ +#ifdef USE_M17N +Str +decodeMIME(Str orgstr, wc_ces * charset) +#else +Str +decodeMIME0(Str orgstr) +#endif +{ + char *org = orgstr->ptr, *endp = org + orgstr->length; + char *org0, *p; + Str cnv = NULL; + +#ifdef USE_M17N + *charset = 0; +#endif + while (org < endp) { + if (*org == '=' && *(org + 1) == '?') { + if (cnv == NULL) { + cnv = Strnew_size(orgstr->length); + Strcat_charp_n(cnv, orgstr->ptr, org - orgstr->ptr); + } + nextEncodeWord: + p = org; + Strcat(cnv, decodeWord(&org, charset)); + if (org == p) { /* Convert failure */ + Strcat_charp(cnv, org); + return cnv; + } + org0 = org; + SPCRLoop: + switch (*org0) { + case ' ': + case '\t': + case '\n': + case '\r': + org0++; + goto SPCRLoop; + case '=': + if (org0[1] == '?') { + org = org0; + goto nextEncodeWord; + } + default: + break; + } + } + else { + if (cnv != NULL) + Strcat_char(cnv, *org); + org++; + } + } + if (cnv == NULL) + return orgstr; + return cnv; +} + +/* encoding */ + +static char Base64Table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +Str +encodeB(char *a) +{ + unsigned char d[3]; + unsigned char c1, c2, c3, c4; + int i, n_pad; + Str w = Strnew(); + + while (1) { + if (*a == '\0') + break; + n_pad = 0; + d[1] = d[2] = 0; + for (i = 0; i < 3; i++) { + d[i] = a[i]; + if (a[i] == '\0') { + n_pad = 3 - i; + break; + } + } + c1 = d[0] >> 2; + c2 = (((d[0] << 4) | (d[1] >> 4)) & 0x3f); + if (n_pad == 2) { + c3 = c4 = 64; + } + else if (n_pad == 1) { + c3 = ((d[1] << 2) & 0x3f); + c4 = 64; + } + else { + c3 = (((d[1] << 2) | (d[2] >> 6)) & 0x3f); + c4 = (d[2] & 0x3f); + } + Strcat_char(w, Base64Table[c1]); + Strcat_char(w, Base64Table[c2]); + Strcat_char(w, Base64Table[c3]); + Strcat_char(w, Base64Table[c4]); + if (n_pad) + break; + a += 3; + } + return w; +} |