gpt4 book ai didi

具有多字节 UTF-8 文件名的 PHP basename() 和 pathinfo()

转载 作者:可可西里 更新时间:2023-11-01 13:25:40 26 4
gpt4 key购买 nike

我发现 PHP 函数 basename() 以及 pathinfo() 对于多字节 utf-8 名称有一种奇怪的行为。他们删除所有非拉丁字符,直到第一个拉丁字符或标点符号。然而,在那之后,后续的非拉丁字符被保留。

basename("àxà"); // returns "xà", I would expect "àxà" or just "x" instead
pathinfo("àyà/àxà", PATHINFO_BASENAME); // returns "xà", same as above

但奇怪的是 pathinfo() 的 dirname 部分工作正常:

pathinfo("àyà/àxà", PATHINFO_DIRNAME); // returns "àyà"

PHP 文档警告 basename()pathinfo()函数是区域设置感知的,但这并不能证明 pathinfo(..., PATHINFO_BASENAME)pathinfo(..., PATHINFO_DIRNAME) 之间的不一致,更不用说事实了相同的非拉丁字符要么被丢弃,要么被接受,具体取决于它们相对于拉丁字符的位置。

这听起来像是一个 PHP 错误。

由于“basename”检查对于避免 directoy 遍历的安全问题非常重要,是否有任何可靠的 basename 过滤器可以很好地处理 unicode 输入?

最佳答案

我发现更改语言环境可以解决所有问题。

虽然默认情况下 Apache 使用“C”区域设置运行,但默认情况下 cli 脚本使用 utf-8 区域设置运行,例如“en_US.UTF-8”(或者在我的例子中为“it_IT.UTF-8”)。在这些条件下,不会发生此问题。

因此,Apache 上的解决方法是在调用这些函数之前将语言环境从“C”更改为“C.UTF-8”。

setlocale(LC_ALL,'C.UTF-8');
basename("àxà"); // now returns "àxà", which is correct
pathinfo("àyà/àxà", PATHINFO_BASENAME); // now returns "àxà", which is correct

或者更好的是,如果你想备份当前语言环境并在完成后恢复它:

$lc = new LocaleManager();
$lc->doBackup();
$lc->fixLocale();
basename("àxà/àyà");
$lc->doRestore();


class LocaleManager
{
/** @var array */
private $backup;


public function doBackup()
{
$this->backup = array();
$localeSettings = setlocale(LC_ALL, 0);
if (strpos($localeSettings, ";") === false)
{
$this->backup["LC_ALL"] = $localeSettings;
}
// If any of the locales differs, then setlocale() returns all the locales separated by semicolon
// Eg: LC_CTYPE=it_IT.UTF-8;LC_NUMERIC=C;LC_TIME=C;...
else
{
$locales = explode(";", $localeSettings);
foreach ($locales as $locale)
{
list ($key, $value) = explode("=", $locale);
$this->backup[$key] = $value;
}
}
}


public function doRestore()
{
foreach ($this->backup as $key => $value)
{
setlocale(constant($key), $value);
}
}


public function fixLocale()
{
setlocale(LC_ALL, "C.UTF-8");
}
}

关于具有多字节 UTF-8 文件名的 PHP basename() 和 pathinfo(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45268499/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com