[摘自師大資訊白色情迷 smart版]
處理含 ASCII 92 字元之文字輸入值
問題說明
中文字係由兩個字元所組成,第一個字元大於 ASCII 127,第二個字元則不限。
在許多程式語言之中,ASCII 92()被當作是跳脫(escape)字元,在程式中需要輸出特定字元時,
先加上 ,才能被系統所辨識出來。
例如:在指定字串變數值時,$Str = "PHP 是一種程式語言",
前後都會用到 " 這個字元,如果希望在字串中使用 " 的話,則可以這麼寫:$Str = ""PHP" 是一種程式語言"。
如此一來,「PHP」前後的雙引號就可以被視為字串的一部份了。
問題就出在這裡!假如使用者在文字框中輸入「成功」二字,
我們來看看傳到伺服器端的資料是什麼(以下一併顯示中文與十六進位的 ASCII 碼):
使用者端傳送:成(A6 A8)功(A5 5C)
伺服器端接收:成(A6 A8)功(A5 5C 5C)
有什麼不同?「功」字的後半部是 5C,轉成十進位是 92,剛好就是上述的跳脫字元。
為了正確地傳送此一字串,PHP 會自動在該字元之前多加個 。
顯示在畫面上的是「成功」,只是有點礙眼,沒啥影響。如果要存入資料庫的話,問題就來了:
$SQL = "INSERT INTO mytable VALUES ('$Str');";
對資料庫而言,它將收到一個這樣的命令:
INSERT INTO mytable VALUES ('成功');
原本「成功」前後的單引號是用來標示字串的,但後面那個單引號加上 之後,就被視為字串的一部份,
而該命令就少了一個單引號了。不正確的命令,當然不能期待它會產生正確的執行結果。
做法:
只要可供使用者輸入文字的元件(如 Text、Textarea...),當php.ini裡的magic_quote_gpc 的值為on時
對於特殊符號像,",$,&等,會自動多加上一個
所以都需要經過下列函數的過濾,才能組成對資料庫執行存取動作的 SQL 敘述句。
01 function Fix_Backslash($org_str) {
02 $tmp_length = strlen($org_str);
03 for ( $tmp_i=0; $tmp_i<$tmp_length; $tmp_i++ ) {
04 $ascii_str_a = substr($org_str, $tmp_i , 1);
05 $ascii_str_b = substr($org_str, $tmp_i+1, 1);
06 $ascii_value_a = ord($ascii_str_a);
07 $ascii_value_b = ord($ascii_str_b);
08 if ( $ascii_value_a > 127 ) {
09 if ( $ascii_value_b == 92 ) {
10 $org_str = substr($org_str, 0, $tmp_i+2) . substr($org_str,$tmp_i+3);
11 $tmp_length = strlen($org_str);
12 }
13 $tmp_i++;
14 }
15 }
16 $tmp_length = strlen($org_str);
17 if ( substr($org_str, ($tmp_length-1), 1) == "" ) $org_str .= chr(32);
18 $org_str = str_replace("", " 0", $org_str);
19 return $org_str;
20 }
程式說明
02 先計算整個字串的總長度,以便後續的迴圈執行「逐字元檢查」的動作。
04 - 05 依序挑出每個字元,與它的下一個字元,意即連續擷取兩個字元。
06 - 07 將挑出的兩個字元分別轉成 ASCII 碼。
若所得的第一個字元大於 ASCII 127 的話(是中文字),執行 09 - 12 之間的程式;
否則,將迴圈的指標多加 1,這個中文字(兩個字元)算是過關了。所得的第二個字元恰好是 ASCII 92 的話(如:許、功、俞、餐等字),
10 可以將被多加上去的 移除。假如被檢查的字串是「成功了」,請看做法:
檢查到「功」時 $tmp_i 是 2,substr($org_str, 0, $tmp_i+2) 可以擷取「成功」二字
,再用 substr($org_str, $tmp_i+3) 擷取「了」字,並組合起來就行了。
11 重算整個字串的總長度,因為字串長度改變了。
16 重算整個字串的總長度,供第 17 行使用。
17 在上述的處理程序之後,如果在字串末尾還有 的話,在其後加個空白。
由於前後文字之間可能組合出 字元(Null),它也會干擾程式的正常運作,
所在第 18 行利用 str_replace 函數,將所有的 改成 0(中間加個空白)。
19 大功告成了。
處理含 ASCII 92 字元之文字輸入值
問題說明
中文字係由兩個字元所組成,第一個字元大於 ASCII 127,第二個字元則不限。
在許多程式語言之中,ASCII 92()被當作是跳脫(escape)字元,在程式中需要輸出特定字元時,
先加上 ,才能被系統所辨識出來。
例如:在指定字串變數值時,$Str = "PHP 是一種程式語言",
前後都會用到 " 這個字元,如果希望在字串中使用 " 的話,則可以這麼寫:$Str = ""PHP" 是一種程式語言"。
如此一來,「PHP」前後的雙引號就可以被視為字串的一部份了。
問題就出在這裡!假如使用者在文字框中輸入「成功」二字,
我們來看看傳到伺服器端的資料是什麼(以下一併顯示中文與十六進位的 ASCII 碼):
使用者端傳送:成(A6 A8)功(A5 5C)
伺服器端接收:成(A6 A8)功(A5 5C 5C)
有什麼不同?「功」字的後半部是 5C,轉成十進位是 92,剛好就是上述的跳脫字元。
為了正確地傳送此一字串,PHP 會自動在該字元之前多加個 。
顯示在畫面上的是「成功」,只是有點礙眼,沒啥影響。如果要存入資料庫的話,問題就來了:
$SQL = "INSERT INTO mytable VALUES ('$Str');";
對資料庫而言,它將收到一個這樣的命令:
INSERT INTO mytable VALUES ('成功');
原本「成功」前後的單引號是用來標示字串的,但後面那個單引號加上 之後,就被視為字串的一部份,
而該命令就少了一個單引號了。不正確的命令,當然不能期待它會產生正確的執行結果。
做法:
只要可供使用者輸入文字的元件(如 Text、Textarea...),當php.ini裡的magic_quote_gpc 的值為on時
對於特殊符號像,",$,&等,會自動多加上一個
所以都需要經過下列函數的過濾,才能組成對資料庫執行存取動作的 SQL 敘述句。
01 function Fix_Backslash($org_str) {
02 $tmp_length = strlen($org_str);
03 for ( $tmp_i=0; $tmp_i<$tmp_length; $tmp_i++ ) {
04 $ascii_str_a = substr($org_str, $tmp_i , 1);
05 $ascii_str_b = substr($org_str, $tmp_i+1, 1);
06 $ascii_value_a = ord($ascii_str_a);
07 $ascii_value_b = ord($ascii_str_b);
08 if ( $ascii_value_a > 127 ) {
09 if ( $ascii_value_b == 92 ) {
10 $org_str = substr($org_str, 0, $tmp_i+2) . substr($org_str,$tmp_i+3);
11 $tmp_length = strlen($org_str);
12 }
13 $tmp_i++;
14 }
15 }
16 $tmp_length = strlen($org_str);
17 if ( substr($org_str, ($tmp_length-1), 1) == "" ) $org_str .= chr(32);
18 $org_str = str_replace("", " 0", $org_str);
19 return $org_str;
20 }
程式說明
02 先計算整個字串的總長度,以便後續的迴圈執行「逐字元檢查」的動作。
04 - 05 依序挑出每個字元,與它的下一個字元,意即連續擷取兩個字元。
06 - 07 將挑出的兩個字元分別轉成 ASCII 碼。
若所得的第一個字元大於 ASCII 127 的話(是中文字),執行 09 - 12 之間的程式;
否則,將迴圈的指標多加 1,這個中文字(兩個字元)算是過關了。所得的第二個字元恰好是 ASCII 92 的話(如:許、功、俞、餐等字),
10 可以將被多加上去的 移除。假如被檢查的字串是「成功了」,請看做法:
檢查到「功」時 $tmp_i 是 2,substr($org_str, 0, $tmp_i+2) 可以擷取「成功」二字
,再用 substr($org_str, $tmp_i+3) 擷取「了」字,並組合起來就行了。
11 重算整個字串的總長度,因為字串長度改變了。
16 重算整個字串的總長度,供第 17 行使用。
17 在上述的處理程序之後,如果在字串末尾還有 的話,在其後加個空白。
由於前後文字之間可能組合出 字元(Null),它也會干擾程式的正常運作,
所在第 18 行利用 str_replace 函數,將所有的 改成 0(中間加個空白)。
19 大功告成了。
文章標籤
全站熱搜
