diff options
-rw-r--r-- | common/sys/string.c | 260 | ||||
-rw-r--r-- | include/cmsys.h | 37 | ||||
-rw-r--r-- | innbbsd/Makefile | 4 | ||||
-rw-r--r-- | innbbsd/str_decode.c | 291 | ||||
-rw-r--r-- | util/Makefile | 5 |
5 files changed, 301 insertions, 296 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和dst可相同, 但src 一定有?或\0結束 */ + /* Thor.980901: 注意, decode出的結果不會自己加上 \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 算是 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 */ + /* + * 這個函式會將一個字串 (src) 從 charset=fromcode 轉成 charset=tocode, + * srclen 是 src 的長度, dst 是輸出的buffer, dstlen 則指定了 dst 的大小, + * 最後會補 '\0', 所以要留一個byte給'\0'. 如果遇到 src 中有非字集的字, + * 或是 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); +} diff --git a/include/cmsys.h b/include/cmsys.h index 2b90042c..1b2b4f4e 100644 --- a/include/cmsys.h +++ b/include/cmsys.h @@ -104,6 +104,14 @@ extern unsigned StringHash(const char *s); extern int DBCS_RemoveIntrEscape(unsigned char *buf, int *len); extern int DBCS_Status(const char *dbcstr, int pos); extern char * DBCS_strcasestr(const char* pool, const char *ptr); +extern 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); +extern void str_decode_M3(unsigned char *str); /* time.c */ extern int is_leap_year(int year); @@ -166,4 +174,33 @@ extern void Vector_sublist(const struct Vector *src, struct Vector *dst, const c extern int Vector_remove(struct Vector *self, const char *name); extern int Vector_search(const struct Vector *self, const char *name); +/* telnet.c */ +struct TelnetCallback { + void (*term_resize)(int w, int h); + void (*update_client_code)(void *ccctx, unsigned char seq); +}; +#define TELNET_IAC_MAXLEN (16) + +struct TelnetCtx { + int fd; // should be blocking fd + unsigned char iac_state; + + unsigned char iac_quote; + unsigned char iac_opt_req; + + unsigned char iac_buf[TELNET_IAC_MAXLEN]; + unsigned int iac_buflen; + + const struct TelnetCallback *callback; + void *ccctx; // client code detection contex +}; +typedef struct TelnetCtx TelnetCtx; + +extern TelnetCtx *telnet_create_contex(void); +extern void telnet_ctx_init(TelnetCtx *ctx, const struct TelnetCallback *callback, int fd); +extern void telnet_ctx_set_ccctx(TelnetCtx *ctx, void *ccctx); + +extern void telnet_send_init_cmds(int fd); +extern ssize_t telnet_process(TelnetCtx *ctx, unsigned char *buf, size_t size); + #endif diff --git a/innbbsd/Makefile b/innbbsd/Makefile index 676aee46..e698e6f0 100644 --- a/innbbsd/Makefile +++ b/innbbsd/Makefile @@ -48,11 +48,11 @@ echobbslib.o: echobbslib.c innbbsd: inndchannel.o innbbsd.o connectsock.o rfc931.o daemon.o \ file.o pmain.o his.o dbz.o closeonexec.o dbztool.o \ - inntobbs.o receive_article.o echobbslib.o str_decode.o nocem.o + inntobbs.o receive_article.o echobbslib.o nocem.o ${CC} -o $@ ${LDFLAGS} $> ${LINK_UTIL_OBJS} $(LDLIBS) bbslink: bbslink.o pmain.o inntobbs.o echobbslib.o connectsock.o \ - file.o port.o str_decode.o + file.o port.o ${CC} -o $@ ${LDFLAGS} $> ${LINK_UTIL_OBJS} $(LDLIBS) bbsnnrp: bbsnnrp.o pmain.o bbslib.o connectsock.o file.o diff --git a/innbbsd/str_decode.c b/innbbsd/str_decode.c deleted file mode 100644 index 7a58439d..00000000 --- a/innbbsd/str_decode.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * 使用方法大致如下: innbbsd 中 在 SUBJECT 從 news 讀進來後, 呼叫 - * str_decode_M3(SUBJECT) 就行了 - */ - -/* - * bsd 底下使用要編譯時要加 -I/usr/local/include -L/usr/local/lib -liconv - * 並安裝 libiconv, 若真的沒有iconv就把底下的 #define USE_ICONV 1 刪了 - */ - -/*-------------------------------------------------------*/ -/* 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" */ -/* ----------------------------------------------------- */ - -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> /* isspace() */ - -#define USE_ICONV 1 -/* - * bsd 底下使用要編譯時要加 -I/usr/local/include -L/usr/local/lib -liconv - * 若真的沒有iconv就把上面這行 #define 刪了 - */ - -#ifdef USE_ICONV -#include <iconv.h> -#endif - -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 */ -/* ----------------------------------------------------- */ - -inline int -isreturn(unsigned char c) -{ - return c == '\r' || c == '\n'; -} - -#if 0 /* in glibc */ -inline int -isspace(unsigned char c) -{ - return c == ' ' || c == '\t' || isreturn(c); -} -#endif - -/* static inline */ -int -mmdecode(unsigned char *src, unsigned char encode, unsigned char *dst) -{ - /* Thor.980901: src和dst可相同, 但src 一定有?或\0結束 */ - /* Thor.980901: 注意, decode出的結果不會自己加上 \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 算是 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; -} - -#ifdef USE_ICONV -size_t -str_iconv( - const char *fromcode, /* charset of source string */ - const char *tocode, /* charset of destination string */ - char *src, /* source string */ - size_t srclen, /* source string length */ - char *dst, /* destination string */ - size_t dstlen) -{ /* destination string length */ - /* - * 這個函式會將一個字串 (src) 從 charset=fromcode 轉成 charset=tocode, - * srclen 是 src 的長度, dst 是輸出的buffer, dstlen 則指定了 dst 的大小, - * 最後會補 '\0', 所以要留一個byte給'\0'. 如果遇到 src 中有非字集的字, - * 或是 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); -} -#endif - - -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 == '?' */ -#ifdef USE_ICONV - int i = mmdecode(tmp + 3, tmp[1], dst1); - i = str_iconv((char*)charset, "big5", (char*)dst1, i, (char*)dst, - sizeof(buf) - ((int)(dst - buf))); -#else - int i = mmdecode(tmp + 3, tmp[1], dst); -#endif - 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); -} diff --git a/util/Makefile b/util/Makefile index b9bb8eb3..2570bc0b 100644 --- a/util/Makefile +++ b/util/Makefile @@ -69,9 +69,8 @@ util_${fn}.o: ${BBSBASE} $(SRCROOT)/mbbsd/${fn}.c shmctl: ${BBSBASE} shmctl.c ${UTIL_OBJS} ${CC} ${CFLAGS} ${LDFLAGS} -o shmctl ${UTIL_OBJS} shmctl.c $(LDLIBS) -bbsmail: ${BBSBASE} bbsmail.c $(SRCROOT)/innbbsd/str_decode.c $(UTIL_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -o bbsmail -DUSE_ICONV \ - bbsmail.c $(SRCROOT)/innbbsd/str_decode.c $(UTIL_OBJS) $(LDLIBS) +bbsmail: ${BBSBASE} bbsmail.c $(UTIL_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o bbsmail bbsmail.c $(UTIL_OBJS) $(LDLIBS) install: $(PROGS) install -d $(BBSHOME)/bin/ |