0x00 basename() 处理中文时的异常现象

这个问题是我在使用imagevue X3这个PHP相册程序时遇到的,问题体现为某些时候如果遇到中文字符时会显示为上一层英文目录的目录名(当前目录名返回为空),如果为中文与其他非中文字符混杂的目录名时,会自己丢弃中文部分,同时中文文件名的图片文件消失在展示页面,刷新页面后可能正常也可能不正常。但是Path路径中的中文显示完全正常。

0x01 setlocale()函数设置区域

我与X3作者取得联系后,发现X3在对文件夹名称和文件名进行处理时依赖于basename()这个函数,并且他确认在我的服务器上basename()函数返回为空值,他认为我是我的服务器没有安装PHP-Intl扩展导致的。诡异的就在这里,我安装PHP-Intl之后,basename()确实正常了,什么问题都没有。我突然想到再卸载这个扩展测试下,但是basename()也正常,一点问题没有的样子。我持续做了长时间测试之后发现,一段时间后basename()又对中文自符没有任何输出,所以PHP-Intl扩展没有用。但是每次出现basename()输出为空的时候,重启PHP又能正常一段时间。

实际上在PHP文档中就提到了

basename() is locale aware, so for it to see the correct basename with multibyte character paths, the matching locale must be set using the setlocale() function.

但是测试setlocale()是不是的确有用有点困难。要等没有设置setlocale()basename()出现问题时,再设置setlocale()进行测试。经过我的耐心等待,setlocale()确实有用,并且设置为

setlocale(LC_ALL,"zh_CN.UTF8");

或者

setlocale(LC_ALL,"en_US.UTF8");
setlocale(LC_ALL,'C.UTF-8');

时都能正确处理中文路径,只是遍历当前目录中文文件夹时顺序有些不同。

0x02 反馈和修改程序

但是我将这些解决办法反馈给X3作者时,作者表示他的设置是能适应多国语言(包括中文的)

UTF-8 would support ANY characters, and as far as I know, this is now the default for all servers in any language.

并且希望我自己在PHP.ini中设置全局的区域信息。

求人不行只有自己改了,我发现setlocale(),无法进行全局设置,只能影响当前文件。所以简单粗暴的方法就是对X3程序中所有调用basename()方法的位置/index.php/panel/x3.php使用setlocale()设置区域信息,从而使其能够正常处理中文。至此问题解决。

但是依然不清楚为什么在没有对setlocale()设置时,basename()方法也能随机的对中文字符有输出,估计要看下PHP的实现才能搞懂了。