将普通字符转换为HTML转义字符
作者:James Zhu ([email protected])
创建日期:2018-03-22
引言
这个问题来源于线上反馈的一个问题,类似AABC-EFGH-IJKL-MNOP的卡密,在某些手机上会显示为ĀBC-EFGH-IJKL-MNOP。目前尚未得知具体重现的场景,但根据经验,考虑将卡密显示转换为HTML转义字符,如将A
转为A
,应该可以避免这个问题。
正文
查阅PHP手册,我们发现 htmlentities() 和 htmlspecialchars() 可以对特殊字符进行转义,但普通字符(A-Z/0-9)仍然保持原样。那么如何将普通字符转换为HTML转义字符呢?
方法一
根据ASCII码输出,代码如下:
$str = 'AABC-EFGH-IJKL-MNOP';
for($i=0; $i < strlen($str); $i++) {
echo '&#'.ord($str[$i]).';';
}
方法二
有没有其它更简洁的方法呢?答案当然是有的,可以使用 preg_replace(),代码如下:
$str = 'AABC-EFGH-IJKL-MNOP';
echo preg_replace('/(.)/e', '"&#".ord("$1").";"', $str);
方法三
但是,不管在哪里,使用eval始终是不推荐的,可能存在被黑客攻击的漏洞。还有没有其它方法呢?还是有的,可以使用 mb_encode_numericentity(),代码如下:
$str = 'AABC-EFGH-IJKL-MNOP';
echo mb_encode_numericentity($str, array(0x20, 0x7E, 0, 0xFF));
mb_encode_numericentity
(PHP 4 >= 4.0.6, PHP 5, PHP 7)
mb_encode_numericentity — Encode character to HTML numeric string reference
string mb_encode_numericentity( string $str , array $convmap [, string $encoding = mb_internal_encoding() [, bool $is_hex = FALSE ]] )
其它参数就不赘述了,这里主要说一下第2个参数$convmap
,手册里有一段对于$convmap
的示例:
$convmap = array (
int start_code1, int end_code1, int offset1, int mask1,
int start_code2, int end_code2, int offset2, int mask2,
........
int start_codeN, int end_codeN, int offsetN, int maskN );
// Specify Unicode value for start_codeN and end_codeN
// Add offsetN to value and take bit-wise 'AND' with maskN, then
// it converts value to numeric string reference.
$convmap
必须以4个元素一组的形式出现,4个参数含义如下:
- start_code: The map affects items starting from this character code.
- end_code: The map affects items up to this character code.
- offset: Add a specific offset amount (positive or negative) for this character code.
- mask: Value to be used for mask operation (character code bitwise AND mask value).
前2个元素比较好理解,就是要进行转义的范围。后2个参数我感觉是用来进行输出混淆,避免某些场景下明文输出。例如:
$str = 'AABC-EFGH-IJKL-MNOP';
echo mb_encode_numericentity($str, array(0x20, 0x7E, 7, 0xFF));
以上代码运行会后输出HHIJ4LMNO4PQRS4TUVW,即所有字符的ASCII码加7后输出的内容,这种混淆是可逆的。
最后个mask参数是对待转义的字符与mask进行AND的位运算,例如:
$str = 'AABC-EFGH-IJKL-MNOP';
echo mb_encode_numericentity($str, array(0x20, 0x7E, 0, 0xEE));
以上代码运行会后输出@@BB,DFFH,HJJL,LNN@,这种混淆是不可逆的,上例中的B/C都输出了B、F/G都输出了F。
以上就是mb_encode_numericentity()
这个方法的简单说明,本文只起抛砖引玉的作用,实际应用中如何使用,大家自由发挥吧。