summaryrefslogtreecommitdiffstats
path: root/lib/str_decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/str_decode.c')
-rw-r--r--lib/str_decode.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/lib/str_decode.c b/lib/str_decode.c
new file mode 100644
index 0000000..d2c2ab4
--- /dev/null
+++ b/lib/str_decode.c
@@ -0,0 +1,374 @@
+/*-------------------------------------------------------*/
+/* 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 */
+/*-------------------------------------------------------*/
+
+
+/* ----------------------------------------------------- */
+/* QP code : "0123456789ABCDEF" */
+/* ----------------------------------------------------- */
+
+
+static int
+qp_code(x)
+ register 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(x)
+ register 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;
+}
+
+
+/* ----------------------------------------------------- */
+/* �� encode / charset */
+/* ----------------------------------------------------- */
+
+
+static inline int
+isreturn(c)
+ unsigned char c;
+{
+ return c == '\r' || c == '\n';
+}
+
+
+static inline int
+isspace(c)
+ unsigned char c;
+{
+ return c == ' ' || c == '\t' || isreturn(c);
+}
+
+
+/* ��Content-Transfer-Encode ���Ĥ@�Ӧr��, �̷Ӽзǥu�i��O q,b,7,8 �o�|�� */
+char *
+mm_getencode(str, code)
+ unsigned char *str;
+ char *code;
+{
+ if (str)
+ {
+ /* skip leading space */
+ while (isspace(*str))
+ str++;
+
+ if (!str_ncmp(str, "quoted-printable", 16))
+ {
+ *code = 'q';
+ return str + 16;
+ }
+ if (!str_ncmp(str, "base64", 6))
+ {
+ *code = 'b';
+ return str + 6;
+ }
+ }
+
+ *code = 0;
+ return str;
+}
+
+
+/* �� charset */
+void
+mm_getcharset(str, charset, size)
+ const char *str;
+ char *charset;
+ int size; /* charset size */
+{
+ char *ptr, delim;
+ int i;
+
+ *charset = '\0';
+
+ if (!str)
+ return;
+
+ if (!(ptr = (char *) strstr(str, "charset=")))
+ return;
+
+ ptr += 8;
+ delim = '\0';
+ i = 0;
+ size--; /* �O�d�Ŷ��� '\0' */
+
+ for (; *ptr && *ptr != delim && !isspace(*ptr); ptr++)
+ {
+ if (*ptr == '\"')
+ {
+ delim = *ptr;
+ continue;
+ }
+
+ charset[i] = *ptr;
+ if (++i >= size)
+ break;
+ }
+ charset[i] = '\0';
+
+ if (!str_cmp(charset, "iso-8859-1")) /* ���v�]�񤣥i�� */
+ *charset = '\0';
+}
+
+
+/* ----------------------------------------------------- */
+/* judge & decode QP / BASE64 */
+/* ----------------------------------------------------- */
+
+
+/* PaulLiu.030410:
+ RFC 2047 (Header) QP �����A�̭��W�w '_' ���� ' ' (US_ASCII���ť�)
+ �� RFC 2045 (Body) QP �����A'_' �٬O '_'�A�S���S���γ~
+ �ҥH�b�� mmdecode ���G���g
+*/
+
+static int
+mmdecode_header(src, encode, dst) /* �� Header �� mmdecode */
+ unsigned char *src; /* Thor.980901: src�Mdst�i�ۦP, ��src�@�w��?��\0���� */
+ unsigned char encode; /* Thor.980901: �`�N, decode�X�����G���|�ۤv�[�W \0 */
+ unsigned char *dst;
+{
+ unsigned char *t;
+ int pattern, bits;
+ int ch;
+
+ t = dst;
+ encode |= 0x20; /* Thor: to lower */
+
+ switch (encode)
+ {
+ case 'q': /* Thor: quoted-printable */
+
+ while ((ch = *src) && ch != '?') /* Thor: Header �̭� 0 �M '?' ���O delimiter */
+ {
+ if (ch == '=')
+ {
+ int x, y;
+
+ 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;
+ }
+ else if (ch == '_') /* Header �n�� '_' ���� ' ' */
+ {
+ *t++ = ' ';
+ }
+ else
+ {
+ *t++ = ch;
+ }
+ src++;
+ }
+ return t - dst;
+
+ case 'b': /* Thor: base 64 */
+
+ /* Thor: pattern & bits are cleared outside while() */
+ pattern = 0;
+ bits = 0;
+
+ while ((ch = *src) && ch != '?') /* Thor: Header �̭� 0 �M '?' ���O delimiter */
+ {
+ int x;
+
+ x = base64_code(*src++);
+ if (x < 0) /* Thor: ignore everything not in the base64,=,.. */
+ continue;
+
+ 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;
+}
+
+
+int
+mmdecode(src, encode, dst) /* �� Header �� mmdecode */
+ unsigned char *src; /* Thor.980901: src�Mdst�i�ۦP, ��src�@�w��?��\0���� */
+ unsigned char encode; /* Thor.980901: �`�N, decode�X�����G���|�ۤv�[�W \0 */
+ unsigned char *dst;
+{
+ unsigned char *t;
+ int pattern, bits;
+ int ch;
+
+ t = dst;
+ encode |= 0x20; /* Thor: to lower */
+
+ switch (encode)
+ {
+ case 'q': /* Thor: quoted-printable */
+
+ while (ch = *src) /* Thor: 0 �O delimiter */
+ {
+ if (ch == '=')
+ {
+ int x, y;
+
+ 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;
+ }
+ else
+ {
+ *t++ = ch;
+ }
+ src++;
+ }
+ return t - dst;
+
+ case 'b': /* Thor: base 64 */
+
+ /* Thor: pattern & bits are cleared outside while() */
+ pattern = 0;
+ bits = 0;
+
+ while (ch = *src) /* Thor: 0 �O delimiter */
+ {
+ int x;
+
+ x = base64_code(*src++);
+ if (x < 0) /* Thor: ignore everything not in the base64,=,.. */
+ continue;
+
+ 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;
+}
+
+
+void
+str_decode(str)
+ unsigned char *str;
+{
+ int adj;
+ unsigned char *src, *dst;
+ unsigned char buf[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++;
+ }
+ else /* Thor: *src == '=' */
+ {
+ unsigned char *tmp = src + 1;
+ if (*tmp == '?') /* Thor: =? coded */
+ {
+ /* "=?%s?Q?" for QP, "=?%s?B?" for BASE64 */
+ tmp++;
+ while (*tmp && *tmp != '?')
+ tmp++;
+ if (*tmp && tmp[1] && tmp[2] == '?') /* Thor: *tmp == '?' */
+ {
+ int i = mmdecode_header(tmp + 3, tmp[1], dst);
+ if (i >= 0)
+ {
+ tmp += 3; /* Thor: decode's src */
+ while (*tmp && *tmp++ != '?'); /* Thor: no ? end, mmdecode_header -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(str, buf);
+}
+
+
+#if 0
+int
+main()
+{
+ char buf[1024] = "=?Big5?B?pl7C0CA6IFtNYXBsZUJCU11UbyB5dW5sdW5nKDE4SzRGTE0pIFtWQUxJ?=\n\t=?Big5?B?RF0=?=";
+
+ str_decode(buf);
+ puts(buf);
+
+ buf[mmdecode("=A7=DA=A4@=AA=BD=B8I=A4=A3=A8=EC=A7=DA=BE=C7=AA=F8", 'q', buf)] = '\0';
+ puts(buf);
+}
+#endif