原創作品author流水孟春,轉載請注明出處lib.cublog.cn
閱讀前提:你必須看過php手冊上的"第IV部分安全"的"第10章魔術引号"。如果沒看過,也沒問題,現在馬上花10分鐘先看一下php手冊上的這東西。
<code>魔術引号(Magic Quote)是一個自動将進入 PHP 腳本的資料進行轉義的過程 你可能想讓你的程式相容多個資料庫,但你使用的不同的資料庫可能使用不同的轉義符,而我們的程式又有可能運作在不同的php.ini配置的主機上,關于magic_quotes的配置又可能不一樣,是以編寫不受魔術引号影響的php應用是高相容性的php應用所必須的。</code>
<code>php.ini中有三個魔術引号配置選項:</code>
魔術引号配置選項
描述
運作時改變
在 PHP中的預設值為
magic_quotes_gpc
如果打開的話,影響到 HTTP 請求資料(GET,POST 和 COOKIE)。
不能
On
magic_quotes_runtime
如果打開的話,大部份從外部來源取得資料并傳回的函數,包括從資料庫和文本檔案,所傳回的資料都會被反斜線轉義。(前提是magic_quotes_gpc = On)
能
Off
magic_quotes_sybase
當關閉時,所有的 '(單引号),"(雙引号),/(反斜線)和 NULL 字元都會被自動加上一個反斜線進行轉義。這和 addslashes() 作用完全相同。
如果打開的話,将會使用單引号對單引号進行轉義而非反斜線。此選項會完全覆寫 magic_quotes_gpc。如果同時打開兩個選項的話,單引号将會被轉義成 ''。而雙引号、反斜線 和 NULL 字元将不會進行轉義。
(前提是magic_quotes_gpc = On)
<code> 但是要處理外部傳來的全局變量就比較麻煩了。</code>
<code>要處理外部超級變量,我們要看magic_quotes_gpc是否已經打開(如果magic_quotes_gpc沒打開,而magic_quotes_sybase打開,magic_quotes_sybase也不起作用),還要看magic_quotes_sybase是否打開,再看我們的程式需要對外部變量用addslashes轉義方式還是使用magic_quotes_sybase式的轉義方式。下面的代碼是一個具體的實作。</code>
<code> 有人可能說,當magic_quotes_gpc設成On,而magic_quotes_sybase設成Off,那麼直接用ini_set('magic_quotes_sybase', 1);就能讓系統用'來對addslashes式的轉義進行覆寫。這樣是不行的。你用ini_get('magic_quotes_sybase')輸出看下配置,magic_quotes_sybase的确被改變了,但是你的代碼就是不能用'轉義符覆寫addslashes式的自動轉義。這是因為系統擷取外部變量的時候,是在你的ini_set('magic_quotes_sybase', 1);之前完成的。</code>
<code></code>
<code><?php /** * 解決不受magic_quotes影響的php應用 * * 使用這個處理辦法需要配置是否使用magic_quotes_sybase, 以适應不同的DBMS * * 設定方法: * $useQuotesSybase[資料庫名] = 1; * 如:使用sqlite,則定義并初始化 $useQuotesSybase['sqlite'] = 1; * 如果使用mysql,可以定義并初始化 $useQuotesSybase['sqlite'] = 0; 也可以不定義 * * CONFIG_DB_DBMS 為所用的DBMS的常量, 在别處定義。比如 define('CONFIG_DB_DBMS', 'mysql'); * * @author 流水孟春 cmpan(at)qq.com * @link http://lib.cublog.cn * $date 2007.11.18 */ error_reporting(E_ALL); set_magic_quotes_runtime(0); define('CONFIG_DB_DBMS', 'sqlite'); // 測試用 // 使用 ' 做轉義符的資料庫 $useQuotesSybase = array(); $useQuotesSybase['sqlite'] = 1; $useQuotesSybase['sybase'] = 1; if(!empty($_POST)) $_POST = array_map('quotesOuterVars', $_POST); if(!empty($_GET)) $_GET = array_map('quotesOuterVars', $_GET); $_COOKIE = array_map('quotesOuterVars', $_COOKIE); $_REQUEST = array_map('quotesOuterVars', $_REQUEST); function quotesOuterVars($var) { if (is_array($var)) { return array_map('quotesOuterVars',$var); } else { if (get_magic_quotes_gpc()) { if (isset($GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) && $GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) { // 目前需要以 ' 為轉義符 // 如果 magic_quotes_sybase = Off, 系統将把外部變量 addslashes, 我們得先 stripslashes // 否則系統自動把 ' 換成 '', if (!ini_get('magic_quotes_sybase')) { $var = stripslashes($var); $var = str_replace("'", "''", $var); } } else { // 目前需要以 / 為轉義符 // 如果 magic_quotes_sybase = On, 我們先把 '' 替換成 ', 然後在 addslashes // 否則系統自動quotes if (ini_get('magic_quotes_sybase')) { $var = str_replace("'", "''", $var); $var = addslashes($var); } } } else{ if (isset($GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) && $GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) { $var = str_replace("'", "''", $var); } else { $var = addslashes($var); } }</code>
<code> return trim($var); } }</code>
<code></code><code> 從上面的表我們可以看出,對于magic_quotes_runtime,我在程式中用 ini_set('magic_quotes_runtime', 0);就可以把它關掉,然後可以用自己的方法來處理來自資料庫或檔案的資料。</code>