将普通字符转换为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都输出了BF/G都输出了F

以上就是mb_encode_numericentity()这个方法的简单说明,本文只起抛砖引玉的作用,实际应用中如何使用,大家自由发挥吧。

results matching ""

    No results matching ""