[PHP] 文字列のエスケープ処理:HTMLやURLのエンコード、デコード

HTMLのエスケープ

htmlspecialchars()

デフォルトでは、「& < > "」の4つのみ変換する。

シングルクオートは変換されないので、このままではセキュリティ上、問題がある。

以下のように、第2引数で「ENT_QUOTES」を指定する。

htmlspecialchars($s, ENT_QUOTES, 'UTF-8');

第3引数は文字コードの指定。デフォルト値は、PHP 5.4.0未満では「ISO-8859-1(Latin-1)」、以上では「UTF-8」と異なるので、きちんと明示的に指定しておいたほうがいい。

なお、第4引数の「double_encode」は、すでに変換された「&amp;」などの文字をさらに変換するかどうか。

デフォルトはtrue。よって「&amp;&amp;」のようになる。

すでに変換済みの文字列と、これから変換したい文字列が混在している場合は、falseにする。

htmlentities()

機能的には「htmlspecialchars()」と同じだが、上記の文字だけでなく実体参照として定義されているほとんどの文字を変換する。

HTMLのエスケープの場合、明らかにオーバースペックなので普通は「htmlspecialchars()」を使う。

データベースに格納する際に使う場合もあるが、SQLインジェクションを防ぐ目的ならば、通常プリペアード・ステートメントを使うはずなので、「htmlentities()」を使う機会はめったにない。

get_html_translation_table()

それぞれどういった文字を変換するかを示す連想配列を返す。

第1引数に「HTML_ENTITIES」、もしくは「HTML_SPECIALCHARS」を指定。

デコード(元に戻す)処理

それぞれ、「htmlspecialchars_decode()」と「html_entity_decode()」。

URLエンコード

英数字と一部の単純な記号(-_.)以外のすべての文字を「%」につづく16進数の文字列に変換する。

urlencode()

HTMLのformから送信される場合と同じ形式「application/x-www-form-urlencoded」で変換。よって、基本的にこちらを使う。

半角スペースを「+」に変換する。

rawurlencode()

基本、「urlencode()」と同じ。RFC 3986に基づく。

半角スペースを「+」に変換しない。

バージョンごとの違い

PHP 5.3.0未満:RFC 1738

チルダ (~)をエンコードする。

PHP 5.3.0以降:RFC 3986

チルダ (~)をエンコードしない。

対策

PHP 5.3.0未満でRFC 3986に準拠するためには、以下のようにチルダを元に戻す必要がある。

str_replace('%7E', '~', rawurlencode($str));

Tips

AmazonウェブサービスのProduct Advertising APIなどは、RFC 3986に基づいたデータしか受け取ってくれない。

こうした場合は、「urlencode()」ではなく「rawurlencode()」を使う必要がある。

デコード

それぞれ、「urldecode()」と「rawurldecode()」。

なお、スーパーグローバル変数「$_POST」と「$_GET」の値はすでに「urldecode()」されたものなので、formなどから受け取った値をいちいちデコード処理する必要はない。

PHP

Posted by takasho