XOOPSとMySQLとPHPと(INSERT編 その2)

XOOPSからMySQLを使用する際のつまらないミスとか失敗を書いてみるシリーズ

先週作成した大会結果一覧機能をCrazy Pugに設置してみた
そして実際に使用してみたら大きなミスをやらかしていることが発覚
直ぐに発覚したのは不幸中の幸いだと思っておこう (--;

まず、うちのサイトで使用しているPHPは利用環境のハードルを下げる為MySQLを一切使用していません
その為、入力された文字列を変換する際は、後からデータを使用する際の都合で、

$str = htmlspecialchars($str)

簡単にこれだけで済ませていました

string htmlspecialchars ( string string, int [quote_style] [, string charset] )

の機能は、

&& に変換する
<&lt; に変換する
>&gt; に変換する

さらに、二番目の引数"quote_style"はシングルクオート・ダブルクオートをどう扱うかを指定するもので

ENT_COMPAT なら、ダブルクオートは変換する、シングルクオートは変換しない
ENT_QUOTES なら、どちらも変換する
ENT_NOQUOTES なら、どちらも変換しない
"quote_style"の指定が無い場合はデフォルトの"ENT_COMPAT"になります
'&#039; に変換されます
"&quot; に変換されます

さて、今回はSQLを扱ったわけですが、いつも通り

$str = htmlspecialchars($str)

と書いていました
そして、始めは問題なく動作しているように見えたのですが次の様な文字列が入力されて発覚

$str1 = "初心者's CUP"
$str2 = "優勝"

この時に生成されたクエリが、

INSERT INTO xoops_table_name (text1, text2) VALUES ('初心者's CUP', '優勝')

"quote_style"を指定していなかった為、入力されたシングルクオートが残ってしまいました
これ、場合によっては意図的にクエリを変更できるとんでも無い失敗です orz
管理者しか登録出来ないとはいえ直ぐに気付いてよかった…
修正自体は簡単です、

$str = htmlspecialchars($str, ENT_QUOTES)

のように第二引数を指定してやれば完了です
生成されるクエリは、

INSERT INTO xoops_table_name (text1, text2) VALUES ('初心者&#039;s CUP', '優勝')

こんな感じになります
今回は使用しませんでしたが、変換された文字列を元の文字列に戻したい時は次の様な関数を用意しています

function unhtmlspecialchars( $str ){
 $entry=array_flip(get_html_translation_table(HTML_SPECIALCHARS));
 return strtr( $str, $entry );
}

PHPのバージョンによっては"htmlspecialchars_decode()"や"html_entity_decode()"を使用してデコードすることも出来ます
"htmlspecialchars_decode()"はPHP5.10RC1以降で使用可能
"html_entity_decode()"はPHP4.30以降かPHP5で使用可能です

ちなみに、"htmlspecialchars()"のままでも良かったのですが、実際には"htmlentities()"に変更しました

string htmlentities ( string string, int [quote_style], string [charset] )

"htmlentities()"は適用可能な文字を全てHTMLエンティティに変換します
第二引数で"quote_style"、第三引数で"charset"を指定するのは"htmlspecialchars()"と同じです
という訳で最終的には、

$str = htmlentities($str, ENT_QUOTES, 'EUC-JP');

になりましたとさ、めでたしめでたし?
いやしかし、素でこんな失敗をするとはまだまだ修行が足りんなぁ…

2007/01/27 01:45