Tommy 碎碎念

Tommy Wu's blog

« 上一篇 | 下一篇 »

修正 LifeType 中無法儲存 backslash [\] 字元的問題
post by tommy @ 04 三月, 2006 23:40
上次在 LifeType 中貼了一段 php 的程式碼, 發現 backslash \ 這個字元, 在貼上的時候看的到, 預覽的時候也看的到, 但是只要儲存後, 這個字元就消失了.

原本一直以為是 TinyMCE 把這個字元吃掉了, 一直在檢查 TinyMCE 的 JavaScript 程式碼, 但是一直查不出為什麼. 今天晚上, 正打算到 TinyMCE 的專案去 submit 這個 bug, 在 submit 之前, 想說到 TinyMCE 的網站 demo 程式去試看看, 結果.... 居然存檔後, 所顯示的畫面與 html code 都是正常的. 看來, 真的是誤會 TinyMCE 了, 這應該是 LifeType 本身的問題.

為了測試這個問題,  怕是我自己測試或修改時, 不小心動了 LifeType 的程式碼所造成的, 特地安裝了另一套完整的 LifeType 1.0.3 來測試, 結果, 不管我使用 HTMLArea 或 TinyMCE 或內建的非 WYSIWYG 編輯器, 都會有相同的結果: 如果直接打 \ 字元, 或使用 HTML 編輯器打入 \ (應該沒有空白, 不過會被轉成 \ 字元, 所以留下空白, 本文所出現的這個字串都應該沒有空白才對, 之後發現並不會有這問題, 非 TinyMCE 造成的) 這個碼, 都會在存檔時消失. 只有在 WYSIWYG 編輯器上頭打入 \ 這個碼的時候, 才會轉換成 \ 字元存入. 但是重新編輯時, 載入的又是 \ 字元, 所以再存一次又消失了.

這兒有幾個問題點:

  1. 在 WYSIWYG 編輯器內, 應該把 \ 存成 \ (應該非硬性規定, 不過這樣後續作業比較不會有問題).
  2. 在 WYSIWYG 編輯器內, 照說打入 \ 這個字串, 應該就表示要顯示這個字串才對, 不應該在存檔之後, 被轉換成 \ 字元.
  3. LifeType 在儲存時, 不應該把 \ 字元移除.

前兩個應該就與 TinyMCE 有關了, 不過應該很少會有這樣的需求, 就先不管了 (其實是 JavaScript 的程式碼又臭又長, 本人沒心情去看). 後來發現在 TinyMCE 送回給 php 的內容中, 並沒有這個問題. 但是在LifeType 中, 如果打開 xhtml 轉換, 就會造成 \ 與 \ 這兩個應該是不同的字串, 因為 & 被轉換成 &, 就變成都是 \, 所以存入資料庫時就變成一樣的, 後來顯示出來當然就錯了.

至於 LifeType 把 \ 字元移除的問題, 我就可能常碰到, 所以就動手查看看.

PHP 有個 magic_quotes_gpc 的設定, 如果這個設定為 On 時, PHP 會自動在 Get/Post 的資料上頭, 在 ', ", \ 這三個字元前自動再加上一個 \ 字元. 所以, LifeType 在產生 SQL 指令時, 會檢查這個參數有沒有被啟用, 如果有, 就會把字串用 stripslashes() 來把 \ 字元移除. 不過, 奇怪的是, 如果不是新增的文章, 而是修改舊有的文章時, 並沒有檢查是否有啟用 magic_quotes_gpc 這個參數, 而是直接就用 stripslashes() 來移除 \ 字元. (這點應該會有問題吧?)

而使用 stripslashes() 應該不是一個好主意, 因為這個函式是為了還原 addslashes() 這個函式所產生的字串. 而 magic_quotes_gpc 只有針對那三個字元 (其實還有一個 NUL 字元) 才會多加一個 \ 字元. 直接使用 addslashes() 來處理的結果, 就是造成目前這樣的情形: 只要有 \ 字元就會被移除.

針對這個問題, 我們可以用下列的方式來處理, 而不使用 addslashes() 來處理:

$string = str_replace('\\\\', '\\', $string);
$string = str_replace("\\'", "'", $string);
$string = str_replace('\\"', '"', $string); 

就只針對 \ 字元後面有帶那三個字元的情形來處理. 然後在 Add/Post 兩個動作抓取傳入的資料時, 都檢查 magic_quotes_gpc 參數, 如果有啟用, 就用上述的方式移除. 把這個動作保留在 qstr() 中處理, 理論上所有的 SQL 指令應該都會做類似的處理才對. 不用在 Add/Post 的地方做特別的處理.

在這樣子的處理後, 我以為就可以把 \ 字元正常存入資料庫了, 不過發現.... 似乎不是這樣, 在組成的 SQL 指令中, 似乎不把這個字元當成一個字元, 而是與後續的字元組合, 像 \n 就變成換行字元了. 所以為了避免麻煩, 就在抓取 postTopic 及 postText 時, 如果有啟用 magic_quotes_gpc 時, 就把 \ 字元換成 \ 再存入, 如果沒有啟用 magic_quotes_gpc 時, 就把 \ 字元換成 \\ 再存入. 這樣子似乎就解決了這個問題. 所以在 qstr() 中, 也必須對 \ 字元特別處理, 要把 \ 改成 \\ 才可以.

這個 patch 可以由 http://www.teatime.com.tw/~tommy/mypatch/lifetype_backslash.patch 抓取. 我也會 submit 到 bugs.lifetype.net.

下面就是上述的 patch 內容:

diff -Nur class.orig/action/admin/adminupdatepostaction.class.php class/action/admin/adminupdatepostaction.class.php
--- class.orig/action/admin/adminupdatepostaction.class.php 2006-03-04 22:21:01.434358824 +0800
+++ class/action/admin/adminupdatepostaction.class.php 2006-03-05 14:13:59.971805184 +0800
@@ -88,9 +88,9 @@
}

// if we got it, update some fields
- $post->setTopic( stripslashes($this->_postTopic));
$postText = $this->_postText.POST_EXTENDED_TEXT_MODIFIER.$this->_postExtendedText;
- $post->setText( stripslashes($postText));
+ $post->setTopic( $this->_postTopic );
+ $post->setText( $postText );
$post->setCategoryIds( $this->_postCategories );
$post->setStatus( $this->_postStatus );
$post->setDateObject( $this->_postTimestamp );
diff -Nur class.orig/database/db.class.php class/database/db.class.php
--- class.orig/database/db.class.php 2006-03-04 22:19:56.205520124 +0800
+++ class/database/db.class.php 2006-03-05 14:13:05.191183578 +0800
@@ -93,9 +93,13 @@
function qstr($string) {

if (get_magic_quotes_gpc()) {
- $string = stripslashes($string);
+ //$string = stripslashes($string);
+ $string = str_replace('\\\\', '\\', $string);
+ $string = str_replace("\\'", "'", $string);
+ $string = str_replace('\\"', '"', $string);
}

+ $string = str_replace("\\", "\\\\", $string);
$string = str_replace("'", "''", $string);

return $string; 

PS. 在這個修正後, 建議在執行 LifeType 時, 不要開啟 magic_quotes_gpc, 以避免執行 stripslashes() 之類的動作. 如果你的網站有其他的系統必須要使用 magic_quotes_gpc, 你可以在 LifeType 所在路徑的 .htaccess 中使用:

php_flag magic_quotes_gpc off 

把 magic_quotes_gpc 的功能關閉. (這個必須在 Apache 的 AllowOverride 設定中至少有 Options 才有作用)

 

Del.icio.us Furl HEMiDEMi Technorati MyShare
迴響
暱稱:
標題:
個人網頁:
電子郵件:
authimage

迴響

  

Bad Behavior 已經阻擋了 92 個過去 7 天試圖闖關的垃圾迴響與引用。
Power by LifeType. Template design by JamesHuang. Valid XHTML and CSS