作成日:2023-08-18, 更新日:2023-08-18
概要
「<b>A&B</b>」をエスケープしてHTML出力すると「<b>A&B</b>」と出力されるのは困る
「<b>A&B</b>」とHTML出力して欲しい
htmlspecialchars()には特定の文字のみ除外とかは無いので自作する必要がある…
「&」をエスケープしない場合
「&」のみエスケープ処理をしない場合、
・「<」「>」はエスケープ処理するのでscriptタグとして認識されないので問題無し
しかし、「URLエンコード」「クエリ文字列の解釈」にはセキュリティ的に問題が発生する可能性がある
サンプルソース
function custom_escape($str, $charAsIs_ary = array()) { if ( !is_array($charAsIs_ary) ) { if ( $charAsIs_ary != '' ) { $charAsIs_ary = array($charAsIs_ary); } else { $charAsIs_ary = array(); } } $flg_replace = false; if ( 0 < count($charAsIs_ary) ) { $flg_replace = true; } $pairChar_ary = array(); $rev_pairChar_ary = array(); if ( $flg_replace ) { $tmp_wordAsIs = '_'; // いったん別の文字に置き換えるための使う基本になる文字 $wordAsIs = $tmp_wordAsIs; // 置き換えるための文字 $maxAttempts = 100; $currentAttempt = 1; while ($currentAttempt <= $maxAttempts) { if (strpos($str, $wordAsIs) === false) { break; } $wordAsIs .= $tmp_wordAsIs; $currentAttempt++; } if ($maxAttempts < $currentAttempt) { // 指定回数を超えたらエラーにする return array(false, $str); } foreach ($charAsIs_ary as $k => $row_char) { $rev_word = $wordAsIs . $k . $wordAsIs; $pairChar_ary[$row_char] = $rev_word; $rev_pairChar_ary[$rev_word] = $row_char; } $str = strtr($str, $pairChar_ary); } $fix_str = htmlspecialchars($str, ENT_COMPAT | ENT_HTML5); if ( $flg_replace ) { $fix_str = strtr($fix_str, $rev_pairChar_ary); } return array(true, $fix_str); } // エスケープせずにそのままにしておきたい文字 $charAsIs_ary = array( '&', ); // エスケープ処理したい文字列 $str = '<>&abc"'; list($sts, $esc_str) = custom_escape($str, $charAsIs_ary); if ($sts) { echo $esc_str; } else { echo 'error'; }