我创建了这个:
$path_canonicalize = function($str, $started = false) use(&$path_canonicalize)
{
$str = str_replace('/', DIRECTORY_SEPARATOR, $str).DIRECTORY_SEPARATOR;
if (!$started)
$str = preg_replace("/".preg_quote(DIRECTORY_SEPARATOR, "'".DIRECTORY_SEPARATOR."'")."{2,}/", DIRECTORY_SEPARATOR, $str);
$pos = strpos($str, '..'.DIRECTORY_SEPARATOR);
if ($pos !== false)
{
$part = trim(substr($str, 0, $pos), DIRECTORY_SEPARATOR);
$str = $path_canonicalize(trim(substr($part, 0, strrpos($part, DIRECTORY_SEPARATOR)), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.trim(substr($str, $pos+3), DIRECTORY_SEPARATOR), true);
}
return rtrim($str, DIRECTORY_SEPARATOR);
};
/*
Try those cases to check the consistency:
$str = __DIR__.'/template//////../header//..';
$str = __DIR__.'/template///..///../header//..';
$str = __DIR__.'/template/../header/..';
$str = __DIR__.'/template/../header/../';
$str = __DIR__.'/template/../header/..//';
$str = __DIR__.'/template/../header/..///';
$str = __DIR__.'/template/../header/..///..';
$str = __DIR__.'/template/../header/..///../';
$str = __DIR__.'/template\\..\\header\\..';
*/
$str = __DIR__.'/template/../header/..///..//';
echo 'original: '.$str.PHP_EOL;
echo 'normalized: '.$path_canonicalize($str).PHP_EOL;
一些担忧:
- 该例程不检查给定路径是相对的还是绝对的。
- 建议通知绝对路径,但也适用于相对路径。该例程将所有内容视为字符串而不是文件系统。
- 最终结果从字符串的开头和结尾删除目录分隔符。
- 不支持单点
./
或/.