首页  > 计算机 >

htmlentities/htmlspecialchars在php5.2.5会检测多字节的字符的完整性

本文按署名·非商业用途·保持一致授权
作者:  ,发表于2007年12月08日18时35分 

PHP5.2.5里有个很吐血的更新。

Fixed htmlentities/htmlspecialchars not to accept partial multibyte sequences.

也就是htmlentities/htmlspecialchars不再允许有不完整的多字节字符输入。(根据我的测试,如果有这个情况发生,那么函数就返回一个长度为0的字符串,而不是摈弃那些不完整的字符)

我拿utf-8来说吧。为了兼容旧的ansi编码文档,utf-8的编码格式是分范围来编码的。下面是utf-8的编码规则,第一个字段是unicode范围(十六进制),第二个字段其对应的编码格式(二进制)。关于utf-8和unicode的详细说明请看我的wiki:iso10646。(不过这个wiki准备要迁移了)

0000-007F | 0xxxxxxx
0080-07FF | 110xxxxx 10xxxxxx
0800-FFFF | 1110xxxx 10xxxxxx 10xxxxxx
10000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

在调用htmlentities的时候,函数会对输入的字符串进行检查。当发现一个以0,110,1110或者11110开头的字节(二进制),程序会认为这是一个utf-8字符的开始。假设这里检测到110开头,则下一个字节必须为10开头。否则110开头的这个字节将会被判定为一个不完整的utf-8字节。

再来看php的代码:

$text='a'.chr(220).chr(127).'b';
$text=htmlentities($text,ENT_COMPAT,'UTF-8');
var_dump($text);

这段代码,在php5.2.3是返回一个4字节的字符串。而在php5.2.5,会返回一个长度为0的字符串。如果把代码的127改为129,那么在php5.2.5下就会返回正确的结果——4个字节的字符串。

至于为什么,大家可以结合我上面所说自己想想吧。

为什么我在开头会说吐血呢。因为…..这个更新会导致一些php程序返回错误的结果。例如:Text_Wiki在对字符串进行parse和render的时候,使用了一个chr(255).chr(4x).chr(255)的字符串作为delimiter。它在进行Xhtml格式的输出的时候,会用htmlentities进行过滤,如果指定了编码为UTF-8,那么这个delimiter的每个字节都会被认为是一个非法的utf-8字符串(从上面的utf-8表可以看出,编码为十进制的255的字节不可能成为任何一个utf-8字符串的一部分),导致最后的输出会是一个空字符串。

ps:这个更新是php爸爸做的修改
ps2:最近有一个更吐血的事情。就是我的苹果机器的硬盘坏了。很多脚本,wiki,各种软件的配置,还有一个写了三周的周末项目没有备份出来。在尝试了几个修复和备份方法之后,终于放弃了,打算送修。不过今天和几个同事去打球,太累了,明天再送修了。吐血了。



6个评论

  1. lucas:

    老乡,对postgresql有研究吗?
    遇到个棘手的问题,
    ERROR: could not read block 17 of relation 1663/16385/16489: Input/output error

    用磁盘检测
    fsck -y -C -V
    检查数据所在的分区,没有错误。但是在其他分区有错误。
    :(

    google了半天,找不到解决办法。
    可以的话,加我msn: lucas_fmg@hotmail.com;

  2. SurfChen:

    to lucas:
    抱歉了,我没使用过postgresql

  3. lucas:

    呵呵,没关系,我也是病急乱投医。
    谢谢你了。

  4. vêtements femmes:

    也学了不少的东西,呵呵

  5. gros vêtements:

    支持一下。。。。

  6. Chaussures femmes:

    好东西,顶!!!!

发表评论

  本站文章若无注明,则以署名·非商业用途·保持一致授权
  桂ICP备05004302号 感谢WordPress提供本程序 本模板下载