この記事は最後に更新してから1年以上経過しています。

フォーム内のエスケープ処理を考える

説明

WordPressにはエスケープ処理を行う esc_html関数と esc_attr関数がある。HTML要素(タグ)の属性値ならesc_attr関数を、それ以外はesc_html関数を使うことがほとんどだが、今回esc_html関数が適していないと思われるケースに遭遇した。

HTMLエンティティを含んだ文章をそのまま保持したい

これまで何等かの文章を編集するフォームを作る場合、TEXTAREA要素を使い、文章部分はクロスサイトスクリプティング(XSS)の要因にならないようesc_html関数でエスケープ処理したものを表示していた。

<textarea name="content"><?php echo esc_html( $content ); ?></textarea>

いつもならこれで問題なかったのだが、文章部分にHTMLエンティティを含む場合はそのHTMLエンティティが見た目上は実体になってしまう。例えば上記の$contentの内容が'©'の場合、esc_html関数は'&'を'&amp;'には変換されず、上記のコードは次のように出力される。

<textarea name="content">&copy;</textarea>

仮にこの内容を変更せずにサブミットすると、$_RQUEST['content']の内容は©(UTF-8: 0xC2A9)になってしまい、HTMLエンティティを保持する場合は何等かの前処理が必要になる。

esc_html関数の機能

これまで何気なく使ってきたesc_html関数だが、esc_html関数とPHPのhtmlspecialchars関数(ENT_QUOTESを指定)を比較し、機能を再確認することにした。次の表が2つの関数の返り値の違いとなる。

入力パラメータesc_html関数htmlspecialchars関数
&&amp;&amp;
<&lt;&lt;
>&gt;&gt;
"&quot;&quot;
'''
&lt;&lt;&amp;lt;
&copy;&copy;&amp;copy;
&rsquo;&rsquo;&amp;rsquo;
&amp;#8217;
&amp;#008220;

2つの関数とも上側の5文字はエスケープ処理されるが、下側のHTMLエンティティについてはesc_html関数の方はエスケープ処理されず、htmlspecialchars関数の方はエスケープ処理されるところが大きな違いである。またesc_html関数ではHTMLエンティティに対して余分な0を取り除いている。

今回はhtmlspecialchars関数を使う

TEXTAREA要素の内容や文字を扱うINPUT要素のvalue属性にはHTMLエンティティが含まれる場合があり、それらに変数の内容を設定する際はHTMLエンティティがエスケープ処理されないesc_html関数は適していない場合がある。今作っているプラグインのフォーム内では、HTML要素やHTMLエンティティを含んだ文字列を扱い、HTMLエンティティは常に維持しておきたいため、エスケープ処理はhtmlspecialchars関数を使うことにした。


最終更新 : 2018年10月19日 16:39


お勧め

wp_reset_postdata(2014年11月16日 更新)

void wp_reset_postdata( )
投稿記事をリセットする。

excerpt_remove_blocks(2022年2月8日 更新)

string excerpt_remove_blocks( string $content )
コンテンツ内の抜粋に適したブロックをレンダリングする。

wp_set_comment_status(2013年9月6日 更新)

mixed wp_set_comment_status( int $comment_id, string $comment_status [ , bool $wp_error = false ] )
コメントのステータスを設定する。

wp_is_site_protected_by_basic_auth(2021年2月5日 更新)

bool wp_is_site_protected_by_basic_auth( [ string $context = '' ] )
サイトがベーシック認証で保護されているか調べる。

send_origin_headers(2018年5月27日 更新)

mixed send_origin_headers()
リクエスト元に応じてAccess-Control-Allow-Originヘッダーを送信する。