c-什么时候使用PHP strtolow()函数是安全的


c - When is it safe to use the PHP strtolower() function?

PHP strtolower()函数应该将字符串转换为小写。但是,它在PHP手册中说(增加了重点):

返回所有字母字符都转换为小写的字符串

请注意,"字母"由当前区域设置决定。这意味着在默认的"C"语言环境中,元音变音符-A(É)等字符将不会转换。

手册中没有提及编码,但众所周知,strtolower()会破坏UTF-8字符串,而应该使用mb_strtolower()

我正在寻找mbstring扩展不可用的情况下的解决方案,我想知道什么时候使用strtolower()是安全的。

多亏了评论这个问题的人给我的指针,PHP源代码的相关部分似乎是对ctype.h库中tolower()函数的调用。图书馆文件上写着(重点加上):

如果tolower()的参数表示一个大写字母,并且存在对应的小写字母(由程序语言环境类别LC_CTYPE),结果应为小写字母。

根据我的测试,在带有set_locale( LC_CTYPE, 'C' );字符的PHP中,比如Ä(在ISO-8859-1中编码)是不受影响的。但在其他一些区域设置中,该函数返回小写ä(同样在ISO-8859-1中)。无论如何,将语言环境更改为使用UTF-8字符集的语言环境并不能使PHP strtolower()处理UTF-8字符Ä

考虑到越来越多的I18N相关问题和多语言环境,这些信息可能至关重要。许多应用程序依赖strtolower()进行简单的不区分大小写的检查。考虑:

$_POST['username'] = 'Michèlle';
if ( strtolower( $_POST['username'] ) == $database['username'] ) ...

现在,根据编码、区域设置以及可能的其他一些变量,上面的代码将在某些环境中工作,但在其他环境中不工作。

问题是:假设PHP strtolower()函数使用ctype.h库的tolower函数,这取决于"程序区域设置类别",那么什么时候可以安全地使用此函数?在以下情况下,这种行为可以指望吗?

  1. 字符串为ASCII
  2. 该字符串在ISO-8859-1中编码
  3. 该字符串以其他一些编码方式进行编码,并带有相应的区域设置

编辑:问题于2013年11月26日完全改写。)

strtolower() PHP函数在其实现中确实使用了tolower() C函数,该函数对传递的字符串参数的每个单字节(八位字节)进行操作。

这就是setlocale(LC_CTYPE, 'C' );不会损坏UTF-8编码字符串的原因,因为它不会更改字节>127.也就是说,它只改变了US-ASCII字符A-Z的大小写。

";CCD_ 20";locale是默认设置的,您不需要用setlocale()显式设置它,只有当应用程序的其他部分将它设置为不同的值时。

这也解释了为什么将CCD_ 22设置为UTF8语言环境;CCD_ 23";不会转换";CCD_ 24";至";ä〃:该字母由两个字节0xC3 0x84编码,其中两个字节都作为单个字符(八位位组)传递给tolower() C函数,因此它们没有变化,因为在单个字节上,UTF-8到更低的处理只能处理字符<128,其同样有效地仅为A-Z。这实际上就像C语言环境。

因此将CCD_ 27设置为"0";CCD_ 28";防止与strtolower()一起使用时中断UTF-8字符串。

它使用C函数tolower(参考:http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.2.html)来自ctype.h库。

您可以在此处查看来源的相关部分:

  • 其中CCD_ 31被定义为:http://lxr.php.net/xref/PHP_TRUNK/ext/standard/string.c#1393
  • 其中CCD_ 32在CCD_http://lxr.php.net/xref/PHP_TRUNK/ext/standard/string.c#1376