作者LHD.bbs@bbs.cs.nctu.edu.tw (不務正業) 看板: plan
標題[修正] 正常讀取非 Big5 中文編碼
時間次世代BS2 (2005/11/25 Fri 02:32:13) Updated: 2005/11/25
精華區現有的文件有一些不完善的地方:
1. Subject 只做 decode 但沒有 conv
解決方法是把 PaulLiu 大大當初 po 的 patch 放進去
2. 目前內文只有在被 QP 或 base64 編碼時,才會做 conv 的動作
原因應該是 mm_getencode 把 8bit 視而不見
解決方法是 mm_getencode 把 8bit 也算一個 encode
然後在 mmdecode 時,case '8' 回傳 strlen(src) + 1;
當然若是想把沒寫 encode 的都當做 8bit,就不用動到 str_decode.c
而是分別在 bbsmail/rec_article.c 改,但 code 也改比較多
以下的寫法是後者,但我希望前者能成為正式 release @@~
3. bbsmail/brdmail 不支援多行 header (上次才加上 RFC2047 Subcect 多行支援)
所以 charset 可能會抓不到,如
Content-Type: text/plain;
charset="utf-8";
innbbsd 本來就有支援,就不用改了。
下面是依最新的程式碼 + 精華區再 patch
PS. bmtad 我很久沒用,就懶得寫了
: lib/str_decode.c::str_decode() 移到 str_conv() 後並修改
+#ifndef MYCHARSET
+#define MYCHARSET "big5"
+#endif
void
str_decode(str)
unsigned char *str;
{
int adj;
+ int i;
unsigned char *src, *dst;
unsigned char buf[512];
+ unsigned char charset[32];
.....
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 != '?')
+ {
+ /* PaulLiu: 把 =?%s? 中的 %s 存到 charset 裡 */
+ if (i + 1 < sizeof(charset))
+ charset[i++] = *tmp;
tmp++;
+ }
+ charset[i] = '\0';
if (*tmp && tmp[1] && tmp[2] == '?') /* Thor: *tmp == '?' */
{
! i = mmdecode_header(tmp + 3, tmp[1], dst);
+ str_conv(charset, MYCHARSET, dst, i);
if (i >= 0)
: util/bbsmail.c 及 brdmail.c
else if (!memcmp(buf, "Content-Type: ", 14))
{
str = buf + 14;
#ifdef ANTI_HTMLMAIL
....
#endif
+ if (!strstr(str, "charset=") && fgets(buf, sizeof(buf), stdin))
+ {
+ if (*buf == ' ' || *buf == '\t') /* charset 在下一列 */
+ str = buf;
+ else
+ goto start;
+ }
mm_getcharset(str, charset, sizeof(charset));
#ifdef ANTI_NOTMYCHARSETMAIL
...
...
while (fgets(buf, sizeof(buf), stdin) && buf[0])
{
if (decode && ((fd = mmdecode(buf, decode, buf)) > 0))
buf[fd] = '\0';
+ else /* 8bit 或根本沒註明 encode */
+ fd = strlen(buf) + 1; /* 包括 '\0' */
+ if (*charset)
+ str_conv(charset, MYCHARSET, buf, fd);
fputs(buf, fp);
}
: innbbsd/rec_article.c::receive_article()
/* 轉 charset */
mm_getencode(CONTENTENCODE, &decode);
cc = mmdecode(BODY, decode, BODY);
mm_getcharset(CONTENTTYPE, charset, sizeof(charset));
if (!*charset)
strcpy(charset, nf->charset);
/* 雖然 str_conv 會判斷 charset 相同時就不做
但因為 BODY 可能很長,所以就先判斷 charset 是否相等
免得做 strlen 的白工 */ /* 這個註解只是在此說明 應該不用加.. */
+ if (str_cmp(charset, MYCHARSET))
+ {
+ if (cc < 0)
+ cc = strlen(BODY) + 1;
str_conv(charset, MYCHARSET, BODY, cc);
+ }
if (!str_cmp(charset, "gb2312"))
{
gb2b5(FROM);
gb2b5(SUBJECT);
if (SITE)
gb2b5(SITE);
}
---
其實還是有一些小問題
如標題為 GB2312 + RFC2047
就會多做一次 gb2b5 反而變亂碼
但大陸 BBS 幾乎不依 RFC2047,連OE送出GB2312信件時也不會做(UTF-8會)
所以應該還好~
--
▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄▄ <telnet://bbs.cs.nctu.edu.tw>
█▄▄▄▄█ █ ▄▄▄▄▄█ Player: LHD
▄█▄▄▄▄█ ▄▄▄█ █▄▄▄▄▄ From: bsd3.cis.nctu.edu.tw
☆ 次世代BS2 ☆ 可申請個人板 150MB 超大相簿 http://pic.bs2.to 資訊人 250MB精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻