From 72f72d64a422d6628c4796f5c0bf2e508f134214 Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:05:14 +0900 Subject: Adding upstream version 0.5.1 --- mimehead.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100644 mimehead.c (limited to 'mimehead.c') 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 +#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; +} -- cgit v1.2.3 From 1d0ba25a660483da1272a31dd077ed94441e3d9f Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Sat, 2 Jan 2021 09:20:37 +0900 Subject: New upstream version 0.5.3+git20210102 --- mimehead.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 14 deletions(-) (limited to 'mimehead.c') diff --git a/mimehead.c b/mimehead.c index 78997e0..d16270c 100644 --- a/mimehead.c +++ b/mimehead.c @@ -63,13 +63,23 @@ ha2d(char x, char y) Str decodeB(char **ww) +{ + struct growbuf gb; + + growbuf_init(&gb); + decodeB_to_growbuf(&gb, ww); + return growbuf_to_Str(&gb); +} + +void +decodeB_to_growbuf(struct growbuf *gb, char **ww) { unsigned char c[4]; char *wp = *ww; char d[3]; int i, n_pad; - Str ap = Strnew_size(strlen(wp)); + growbuf_reserve(gb, strlen(wp) + 1); n_pad = 0; while (1) { for (i = 0; i < 4; i++) { @@ -93,39 +103,50 @@ decodeB(char **ww) for (i = 0; i < 4; i++) { c[i] = c2e(c[i]); if (c[i] == BAD_BASE64) { - *ww = wp; - return ap; + goto last; } } 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]); + GROWBUF_ADD_CHAR(gb, d[i]); } if (n_pad || *wp == '\0' || *wp == '?') break; } +last: + growbuf_reserve(gb, gb->length + 1); + gb->ptr[gb->length] = '\0'; *ww = wp; - return ap; + return; } Str decodeU(char **ww) +{ + struct growbuf gb; + + growbuf_init(&gb); + decodeU_to_growbuf(&gb, ww); + return growbuf_to_Str(&gb); +} + +void +decodeU_to_growbuf(struct growbuf *gb, char **ww) { unsigned char c1, c2; char *w = *ww; int n, i; - Str a; if (*w <= 0x20 || *w >= 0x60) - return Strnew_size(0); + return; n = *w - 0x20; - a = Strnew_size(n); + growbuf_reserve(gb, n + 1); 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))); + gb->ptr[gb->length++] = (c1 << i) | (c2 >> (6 - i)); if (i == 6) { w += 2; i = 2; @@ -135,7 +156,8 @@ decodeU(char **ww) i += 2; } } - return a; + gb->ptr[gb->length] = '\0'; + return; } /* RFC2047 (4.2. The "Q" encoding) */ @@ -164,10 +186,20 @@ decodeQ(char **ww) /* RFC2045 (6.7. Quoted-Printable Content-Transfer-Encoding) */ Str decodeQP(char **ww) +{ + struct growbuf gb; + + growbuf_init(&gb); + decodeQP_to_growbuf(&gb, ww); + return growbuf_to_Str(&gb); +} + +void +decodeQP_to_growbuf(struct growbuf *gb, char **ww) { char *w = *ww; - Str a = Strnew_size(strlen(w)); + growbuf_reserve(gb, strlen(w) + 1); for (; *w != '\0'; w++) { if (*w == '=') { w++; @@ -180,15 +212,16 @@ decodeQP(char **ww) else { if (*w == '\0' || *(w + 1) == '\0') break; - Strcat_char(a, ha2d(*w, *(w + 1))); + gb->ptr[gb->length++] = ha2d(*w, *(w + 1)); w++; } } else - Strcat_char(a, *w); + gb->ptr[gb->length++] = *w; } + gb->ptr[gb->length] = '\0'; *ww = w; - return a; + return; } #ifdef USE_M17N -- cgit v1.2.3