作成日: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';
}