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

説明

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


お勧め

flush_rewrite_rules(2015年9月24日 更新)

void flush_rewrite_rules( [ bool $hard = true ] )
リライトルールを更新する。

shortcode_atts(2018年5月27日 更新)

array shortcode_atts( array $pairs, array $atts )
ショートコードの無効な属性値を除外する。属性が省略されている場合は、デフォルト値を設定する。

the_weekday(2012年1月16日 更新)

void the_weekday( )
投稿日の曜日を表示する。

wp_loginout(2018年5月27日 更新)

void wp_loginout( [ string $redirect = '' ] )
閲覧者がログインしているかどうかを調べ、ログインしていなければログインページのリンクを、ログイン済みならばログアウトページのリンクを表示する。

has_term(2012年1月17日 更新)

bool has_term( [ mixed $term = '' [ , string $taxonomy = '' [ , mixed $post = null ] ] ] )
投稿記事にタクソノミーが付属しているか調べる。