diff options
Diffstat (limited to 'common/sys')
-rw-r--r-- | common/sys/string.c | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/common/sys/string.c b/common/sys/string.c index 72c80cef..e529425c 100644 --- a/common/sys/string.c +++ b/common/sys/string.c @@ -471,3 +471,263 @@ char * qp_encode (char *s, size_t slen, const char *d, const char *tocode) return s0; } +// following code is moved from innbbsd/str_decode.c +/*-------------------------------------------------------*/ +/* lib/str_decode.c ( NTHU CS MapleBBS Ver 3.00 ) */ +/*-------------------------------------------------------*/ +/* target : included C for QP/BASE64 decoding */ +/* create : 95/03/29 */ +/* update : 97/03/29 */ +/*-------------------------------------------------------*/ +#include <iconv.h> + + +/* ----------------------------------------------------- */ +/* QP code : "0123456789ABCDEF" */ +/* ----------------------------------------------------- */ + +static int +qp_code(int x) +{ + if (x >= '0' && x <= '9') + return x - '0'; + if (x >= 'a' && x <= 'f') + return x - 'a' + 10; + if (x >= 'A' && x <= 'F') + return x - 'A' + 10; + return -1; +} + + +/* ------------------------------------------------------------------ */ +/* BASE64 : */ +/* "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" */ +/* ------------------------------------------------------------------ */ + +static int +base64_code(int x) +{ + if (x >= 'A' && x <= 'Z') + return x - 'A'; + if (x >= 'a' && x <= 'z') + return x - 'a' + 26; + if (x >= '0' && x <= '9') + return x - '0' + 52; + if (x == '+') + return 62; + if (x == '/') + return 63; + return -1; +} + + +/* ----------------------------------------------------- */ +/* judge & decode QP / BASE64 */ +/* ----------------------------------------------------- */ + +static inline int +isreturn(unsigned char c) +{ + return c == '\r' || c == '\n'; +} + +static inline +int +mmdecode(unsigned char *src, unsigned char encode, unsigned char *dst) +{ + /* Thor.980901: src�Mdst�i�ۦP, ��src �@�w��?��\0���� */ + /* Thor.980901: �`�N, decode�X�����G���|�ۤv�[�W \0 */ + unsigned char *t = dst; + int pattern = 0, bits = 0; + encode |= 0x20; /* Thor: to lower */ + switch (encode) { + case 'q': /* Thor: quoted-printable */ + while (*src && *src != '?') { /* Thor: delimiter *//* Thor.980901: + * 0 ��O delimiter */ + if (*src == '=') { + int x = *++src, y = x ? *++src : 0; + if (isreturn(x)) + continue; + if ((x = qp_code(x)) < 0 || (y = qp_code(y)) < 0) + return -1; + *t++ = (x << 4) + y, src++; + } else if (*src == '_') + *t++ = ' ', src++; +#if 0 + else if (!*src) /* Thor: no delimiter is not successful */ + return -1; +#endif + else /* Thor: *src != '=' '_' */ + *t++ = *src++; + } + return t - dst; + case 'b': /* Thor: base 64 */ + while (*src && *src != '?') { /* Thor: delimiter */ + /* + * Thor.980901: 0�]�� *//* Thor: pattern & bits are cleared + * outside + */ + int x; +#if 0 + if (!*src) + return -1; /* Thor: no delimiter is not successful */ +#endif + x = base64_code(*src++); + if (x < 0) + continue; /* Thor: ignore everything not in the + * base64,=,.. */ + pattern = (pattern << 6) | x; + bits += 6; /* Thor: 1 code gains 6 bits */ + if (bits >= 8) { /* Thor: enough to form a byte */ + bits -= 8; + *t++ = (pattern >> bits) & 0xff; + } + } + return t - dst; + } + return -1; +} + +size_t +str_iconv( + const char *fromcode, /* charset of source string */ + const char *tocode, /* charset of destination string */ + const char *src, /* source string */ + size_t srclen, /* source string length */ + char *dst, /* destination string */ + size_t dstlen) +{ /* destination string length */ + /* + * �o�Ө禡�|�N�@�Ӧr�� (src) �q charset=fromcode �ন charset=tocode, + * srclen �O src ������, dst �O��X��buffer, dstlen �h���w�F dst ���j�p, + * �̫�|�� '\0', �ҥH�n�d�@��byte��'\0'. �p�G�J�� src �����D�r�����r, + * �άO src ���������㪺 byte, ���|�屼. + */ + iconv_t iconv_descriptor; + size_t iconv_ret, dstlen_old; + + dstlen--; /* keep space for '\0' */ + + dstlen_old = dstlen; + + /* Open a descriptor for iconv */ + iconv_descriptor = iconv_open(tocode, fromcode); + + if (iconv_descriptor == ((iconv_t) (-1))) { /* if open fail */ + strncpy(dst, src, dstlen); + return dstlen; + } + /* Start translation */ + while (srclen > 0 && dstlen > 0) { + iconv_ret = iconv(iconv_descriptor, &src, &srclen, + &dst, &dstlen); + if (iconv_ret != 0) { + switch (errno) { + /* invalid multibyte happened */ + case EILSEQ: + /* forward that byte */ + *dst = *src; + src++; + srclen--; + dst++; + dstlen--; + break; + /* incomplete multibyte happened */ + case EINVAL: + /* forward that byte (maybe wrong) */ + *dst = *src; + src++; + srclen--; + dst++; + dstlen--; + break; + /* dst no rooms */ + case E2BIG: + /* break out the while loop */ + srclen = 0; + break; + } + } + } + *dst = '\0'; + /* close descriptor of iconv */ + iconv_close(iconv_descriptor); + + return (dstlen_old - dstlen); +} + + +/** + * inplace decode mime header string (rfc2047) to big5 encoding + * + * @param str [in,out] string, assume buffer size 512 + * + * TODO rewrite, don't hardcode 512 + */ +void +str_decode_M3(unsigned char *str) +{ + int adj; + int i; + unsigned char *src, *dst; + unsigned char buf[512]; + unsigned char charset[512], dst1[512]; + + + src = str; + dst = buf; + adj = 0; + + while (*src && (dst - buf) < sizeof(buf) - 1) { + if (*src != '=') { /* Thor: not coded */ + unsigned char *tmp = src; + while (adj && *tmp && isspace(*tmp)) + tmp++; + if (adj && *tmp == '=') { /* Thor: jump over space */ + adj = 0; + src = tmp; + } else + *dst++ = *src++; + /* continue; *//* Thor: take out */ + } else { /* Thor: *src == '=' */ + unsigned char *tmp = src + 1; + if (*tmp == '?') { /* Thor: =? coded */ + /* "=?%s?Q?" for QP, "=?%s?B?" for BASE64 */ + tmp++; + i = 0; + while (*tmp && *tmp != '?') { + if (i + 1 < sizeof(charset)) { + charset[i] = *tmp; + charset[i + 1] = '\0'; + i++; + } + tmp++; + } + if (*tmp && tmp[1] && tmp[2] == '?') { /* Thor: *tmp == '?' */ + int i = mmdecode(tmp + 3, tmp[1], dst1); + i = str_iconv((char*)charset, "big5", (char*)dst1, i, (char*)dst, + sizeof(buf) - ((int)(dst - buf))); + if (i >= 0) { + tmp += 3; /* Thor: decode's src */ +#if 0 + while (*tmp++ != '?'); /* Thor: no ? end, mmdecode + * -1 */ +#endif + while (*tmp && *tmp++ != '?'); /* Thor: no ? end, + * mmdecode -1 */ + /* Thor.980901: 0 �]�� decode ���� */ + if (*tmp == '=') + tmp++; + src = tmp; /* Thor: decode over */ + dst += i; + adj = 1;/* Thor: adjcent */ + } + } + } + while (src != tmp) /* Thor: not coded */ + *dst++ = *src++; + } + } + *dst = 0; + strcpy((char*)str, (char*)buf); +} |