CMS中文编码问题分析及解决方案

本文探讨了CMS系统在处理中文编码时遇到的问题,尤其是BIG5编码中的“許蓋功”现象,分析了其产生的原因,包括SQL注入、PHP的跳脱字符问题以及UNIX系统中的处理错误。同时,提出了通过去除STRIPSLASHES函数、使用big5_func字符串处理函数集等解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

CMS中文编码问题分析及解决方案


开题注: 有意见认为采用UTF-8编码将解决一切语言编码问题。我不同意这种意见: 其一对于中文用户,简体和繁体用户不习惯江两种编码字混排阅读;其二,目前大量网站采用GB/BIG5编码,而MB/ICONV对GB/BIG5 – UTF-8转换的支持并不理想。

CMS 的开发中必须要面对语言问题,主要是指多字节处理,包括encoding charset转换、字长计算等。一般来说,普通的多字节问题可以借助MB/ICONV等模块解决,但是对于中文来说,PHP自带的这两个模块支持不完善. XOOPS 中文版采用了xconv模块 – iconv for XOOPS。该模块使用了查找替换方法,效率低,但也是没有办法的办法。[ XOOPS 可以自由选择编码方式,如果你选择UTF-8编码,以下内容权作茶资]

本文将尝试作如下分析[按现有资料是否齐备计序,不考虑逻辑和时间顺序]: big5冲码问题简介、分析及解决方案; xconv模块介绍及使用; 多字节问题介绍及处理方案. 

一 BIG5冲码问题分析及解决方案

在处理big5编码时,有个著名的问题”許蓋功”—-BIG5冲码是必须要面对的,下边将摘录部分来自台湾的资料。


淺談許蓋功

許蓋功何許人也?
許蓋功這號人物,只要曾經用過php+mysql架站的人,無人不知無人不曉,且絕對是這些架站人心中永遠的痛….
(摘自osCommerce購物網站架設實戰)

仔細探究原因,你會發現,錯的人其實不該是許蓋功,而是通稱大五碼的BIG5碼,關於大五碼的歷史傳說眾說紛紜,無一定論。我們並不評論當初編碼的對錯與是非,對這歷史有興趣的讀者不妨到google搜尋"BIG5″,相信可以找到一堆資料。
既然大五碼聽來似乎有些問題,為何目前幾乎所有的繁體中文卻又都採用此一編碼呢?在西元1983-1984年間,個人電腦正在台灣逐漸推廣,電腦上的套裝軟體也開始盛行,為了解決電腦處理中文的問題,因而制定一套中文內碼,也就是我們通稱的"BIG5碼",又稱大五碼。而經歷過這段時間的人,一定不會忘記當初倚天中文的行銷手法,在國外軟體廠商開始引進原版軟體觀念的當時,倚天中文卻反其道而行,允許校園甚至一般使用者無條件且免費複製其中文系統,因此,讓倚天中文在當時幾乎成為中文的標準,也由於倚天中文正是採用BIG5編碼,嚴格說來,也就是BIG5碼為何一直沿用到現今的主要原因了。

大五碼錯在哪裡?
錯在編碼時沒有把美國標準資訊交換碼 ASCII(American Standard Code for Information Interchange)的控制碼排除在外,凡是唸過計算機概論的人都知道ASCII是以byte為單位,又1 byte=8 bits,所以ASCII最多可以編2^8=256個字元,對於只有26個字母的英文語系國家來說已綽綽有餘,但對於有幾萬字的中文絕對不夠,因此必須用兩個byte來代表一個中文字,如"中"字的編碼即是"A4A4″。然而,BIG5碼設計時為了避免與ASCII衝突,每個中文字的第一個byte僅使用 ASCII裡的高字元(129-255),但在第二個byte卻用到了部分低字元(1-128),這正是BIG5碼在日後應用上造成極大不便的最大幫兇了。

為何BIG5碼專找php+mysql麻煩?
原因有三:
一、sql隱碼問題:
我們知道,如果要在mysql資料庫中擷取得資料時的語法為:

select * from administrator where id=’ABC’ and passwd=’1234′ 

假設我有一個login.php的網頁,內容是用來輸入id和passwd值的表單(from),若有人直接於網址列輸入:

login.php?id=ABC&passwd=’%20or%201=1%20or%201=’

由於%20會被瀏覽器解譯為空白,因此最後丟到mysql的sql語法是:

select * from administrator where id=’ABC’ and passwd='’ or 1=1 or 1='’

這是一個恆為真的式子,騙過了驗證而取得administrator的權限。
因此,單引號變成了頭號隱形殺手。
二:php 的跳脫字元
5C在php裡面是被拿來當跳脫字元,也就是說當變數裡面的文字帶有 、單引號或雙引號時,為了要可以正確顯示這些特殊字元,通常需要多加一個 \,常見的例子如:
<?php
echo ”<table border=\"0\”>”;
?>

如果沒加,立刻會出現錯誤訊息:

Parse error: parse error, unexpected T_LNUMBER, expecting ‘,’ or ‘;’ in c:appservwwwcode.php on line 2

這樣,問題就來了,當我們要插入一筆資料到資料庫如:

INSERT INTO mytable VALUES (’許蓋功’);

由於功的第二個byte是 5C ,加上後面接的是單引號,因此經過解譯之後,最後面的單引號卻認定為文字,因而導致sql語法少了最後那個單引號,當然就寫不進資料庫而發生錯誤了。
三、addslashes與stripslashes函數:
為了解決單引號可能被用來當成攻擊資料庫的工具,一般在寫php程式時會利用addslashes函數將變數裡的單引號前加入一個跳脫字元,如上述原本在passwd輸入:
‘ or 1=1 or 1=’
可以騙過驗證,在經過addslashes函數處理後變成:
\‘ or 1=1 or 1=\’
這樣便可以避免單引號被用來當成攻擊資料庫的工具了。但是,如此一來,跳脫字元會被當成輸入文字直接寫入資料庫內,因此,當我們寫入資料庫時若用了 addslashes函數,從資料庫取出該筆資料時就必須使用stripslashes將刪去,否則顯示出來的資料就會多一個的跳脫字元了。

BIG5不只找php麻煩,連unix都倖免於難
7C 是 ASCII 裡的 pipe ‘|’ 用過 unix 的應該知道它是作什麼的,舉一個簡單的例子,如果你用 ftp 上傳一個 “四.doc” 的檔名到 unix ,傳完後立刻變成 “北.doc’,我想太多人有過這種經驗,原因無他,中文字 “四” 的 BIG5 碼是"A57C",當 unix 看到 7C 時會覺得莫名其妙,上傳一個 “|” 給我做什麼?於是就自己處理掉了…
因此,你可以想像只要是中文字第二個byte是 “7C” 的,保證也都難逃BIG5的魔掌。

許蓋功的解決之道
一、去除程式裡出現問題那段程式碼裡的STRIPSLASHES函數,如此,除了顯示"許蓋功"時可能變成"許蓋功"之外,似乎沒有太大的問題,但是,MYSQL server的隱碼及跳脫字元問題還是存在的。
二、使用big5_func字串處理函數集
如果你曾經仔細研究筆者在OSC裡處理許蓋功的方法,你應該就會發現[webroot] /catalog/includes/languages/tchinese 目錄下有一個叫big5_func的資料夾,其實就是網路上的高人為了解決BIG5的問題而寫的函數集,我們稱之為"big5 字串處理函數集"。

後記
由於BIG5所造成的問題幾乎無所不在,筆者認為除非BIG5有一個完整的補救計劃,否則許蓋功將會一直困擾著所有架站人。在此,筆者也試圖透過這樣的說明,讓每一位想架站卻又遭受此一問題困擾的人自己找到解決的辦法。最後在此也特別聲明,BIG5的問題可能不只這些,也可能相當棘手,甚至超出筆者所能解決的範圍,但,如果你有任何問題,也歡迎你到 網路甘仔店 社群提出,相信我們有許多熱心的人可以一同來解決BIG5的問題。


Big5碼中容易衝碼的文字
— garylee
 
Big5中由於當初設計上的疏失,導致一些屬於控制字元的資料容易引起一些程式環境的誤判。造成顯示出來的中文字不是我們想要的結果。所以我們在寫程式的時候對於中文的處理要特別小心。下面列出了一些容易引發衝碼的文字,寫程式的人,最好都能夠測試下面的字在你的程式中可以正確無誤的被使用。

ASCII(5C) == “/”
A45C么AE5C娉B85C稞C25C擺A55C功
AF5C珮B95C鈾C35C黠A65C吒B05C豹
BA5C暝C45C孀A75C吭B15C崤BB5C蓋
C55C髏A85C沔B25C淚BC5C墦C65C躡
A95C坼B35C許BD5C穀AA5C歿B45C廄
BE5C閱AB5C俞B55C琵BF5C璞AC5C枯
B65C跚C05C餐AD5C苒B75C愧C15C縷

ASCII(7C) == “|”

AA7C泜B47C揉A87C育BE7C魯B27C琍
BC7C慝C67C鸛A97C尚B37C逖BD7C罵
A77C坑B17C悴BB7C誡C57C疊A67C帆
B07C院BA7C漏C47C辮AB7C咽B57C稅
BF7C糕AC7C洱B67C閏C07C嚐AD7C迢
B77C會C17C舉A47C弋AE7C徑B87C腮
C27C甕A57C四AF7C砝B97C頌C37C牘


解决方案

PHP Big5 Function 指令集 方案

RAP 方案

待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值