addslashes及stripslashes 前言

我們知道長期以來PHP對於中文(尤其是以BIG5為主的繁體中文)這種雙位元字元,一直存在許多在使用上的問題。許多由國外來的PHP程式,不論其使用習 慣是否符合中國人使用習慣,在許多亂碼字問題不斷產生之下,造成舊的問題仍然存在,而隨著新的編碼格式 - UTF-8逐漸普及之後,更存有許多UTF-8編碼下的中文字新的問題。在新舊編碼格式交互存在的環境之下,我常常搜索是否有更佳的解決方案,但網路上留 有的文章大部份是僅能滿足某些特別情況之下的解決方案,能把所有常見的問題與解決方式一一提出的文章不多。這篇文章的目的即在此,希望能匯集我在這近兩年 以來,遇見的許多中文編碼與PHP、MySQL、瀏覽器中的衝突與想法,把許多心得或收集得來的經驗寫下來。提供給對此種問題困擾已久的網友們作參考。
BIG5的老問題

BIG5是一個 十分有歷史的中文編碼方式,在微軟公司佔去了絕大部份的桌上型電腦的作業系統優勢之後,事實上因為BIG5中的字數不足,微軟公司自行建立稱為CP950 的編碼標準,當然這也是目前通用的繁體中文編碼標準。在繁體中文中,使用不論是BIG5或CP950編碼,在PHP的問題絕對比大陸所使用的GB編碼的簡 體中文來得多。

PHP語言除了在某些特殊字串運算函式會對BIG5的某些字元感冒外,在正規敘述式時,也會發生判斷錯誤而跳逸字元的錯誤 訊息。一些文章通稱這個問題為"許功蓋"問題,其原因是在"許功蓋"等字的雙位元的第二位元,恰巧與PHP用來跳逸符號的"\"相同,都是ASCII碼的 92(16進位碼5C)編號。這個問題不是PHP語言特殊的現象,在其它的程式語言中,一樣對這個問題頭痛。BIG5的"許功蓋"問題,也不止這三個字而 已,根據PHP程式在Windows上特別跑出的結果,約有80多個字,其中比較常見的有"許功蓋俞枯淚閱餐琵愧擺穀么"這幾個字。當然發生在這些字上已 經相當嚴重,有些字十分常用。

常見的解決方案

在 這個情況之下,在許多以前就有對PHP提出解決方案的函式庫出現。其中現存我能找得到的是一個我之前常用來取代PHP語言中的addslashes及 scriptslashes函式的big5_func。這個函式庫出現的時間約在西元2001年到2003年初,最後正逢PHP語言發展到4.3.x第一 個版本出現之時。原作者為Pigo Chu。除了提供big5_addslashes、big5_stripslashes之外對於中文截字的方法,提供了big5_substr、big5_strlen、big5_strpos的 各對應函式,可說是對BIG5的問題提出相對的解決方法。雖然2003年後就不再見到新版發佈的消息,在現今許多程式還是使用BIG5作為編碼的情況之 下,這個函式還是有一定的用處。其它對於BIG5問題的解決方案,大概都脫不了和big5_func同樣的方式,所以我以下就這個函式庫的解決方式深究其 方法。

big5_func的解決方案深究

big5_func 對於addslashes及stripslashes這兩個會影響"\"符號的PHP函式,有兩種不同的方式,其一是在PHP環境中無iconv這個預裝 函式庫時,採行了先查表轉換為Unicode碼,作完addslashes及stripslashes之後,再行轉碼回來。如果有iconv,則使用 iconv作為轉碼為UTF-16的方式,作完addslashes及stripslashes之後,再用iconv轉回BIG5碼。讀者可能會發現,為 什麼要轉為UTF-16而不是UTF-8?原因是UTF-16的字節長度是固定的,而UTF-8是變動的,如果要使用計算字數或比對的方式,只有固定的編 碼格式才能用這種方法。而UTF-8也是最近幾年才開始盛行的Unicode中的一支。

big5_func中的big5_isBig5、big5_strposbig5_substr、big5_strlen 大多是用比對十六進位碼及計算完成的,比較特殊的是big5_stroke這個函式,這個是計算中文字筆劃的函式,用查表對應出來的,這個函式大概在算命的時候可以派得上用場,作者的用心可見一斑。

這個函式庫在歷經時間的考驗,在各大PHP程式系統中還是可以找得到有人在尋求或討論,可見這個函式庫的好用。但在以下幾種情況之下,還是會有需要增進之處或無法達到效果的地方:
  • PHP的環境中magic_quotes_gpc設為On時:此時PHP會啟動類似一種制,在GET/POST/COOKIE時,會自動幫\符號再加上\,此時"許功蓋"的"\"除之不盡,一不小心就加了一大堆,又產生錯誤。
  • iconv在PHP 4.3.8或9時,突然失靈: 關於失靈的原因,是PHP採用了比較新版(2.0以上)的iconv函式庫作為預設加入的函式庫,至於為何會失靈,我就沒有再深入研究了。遭遇失靈的 iconv,big5_func仍會判別使用iconv的解決方式,造成big5_addslashes及big5_stripslashes失效。這個 新版的iconv,在之後PHP發佈的版本,都有使用者向PHP官方報告錯誤資訊,造成有些主機廠商不願意提供iconv這個本來是預裝的函式庫。
  • 查表轉成UTF-16,解決"\"的問題再轉回來的方式,事實上速度非常慢:這個當然是非常慢,在我電腦上測的結果,速度比用mbstring或iconv轉,之後再轉回來的方式,需要多花幾百倍時間。
  • 連字時,mysql會頻頻錯誤:在許功蓋連字時,有三個"\"要處理,使用函式不當,會造成mysql頻頻錯誤。
以上是提供在運用時需要再仔細思考的方向。在日本,相對於big5_func,也有一套類似的函式庫,稱之為Jcode
只不過從程式碼看起來沒有像BIG5中特別悲慘的"許功蓋"問題。
原文網站: Eddy Chang