file_exists 和包含相对路径的路径(“/../”)
Posted
技术标签:
【中文标题】file_exists 和包含相对路径的路径(“/../”)【英文标题】:file_exists and paths that include relative paths ("/../") 【发布时间】:2014-03-30 00:38:35 【问题描述】:当我在像/a/path/to/a/../file.php
这样的路径上使用file_get_contents
时,它得到的内容就好了。如果我先调用file_exists
(或is_file
或realpath
),则返回值表明该文件不存在。似乎是什么问题?
编辑:以下是从 cmets 浓缩到答案的一些附加信息:
我正在运行带有 php 5.5.6 的 Mac OS X 10.9,所以 安全模式应该不是问题 (it was removed in version 5.4) 我尝试通过调用clearstatcache(true, $dir1)
清除文件现金
有问题的文件大小为 362 字节,但我用几个不同的文件在多个位置复制了这个问题。
open_basedir
在 php.ini 中被注释掉
文件是本地的(我尝试的第一个文件与脚本在同一目录中)
命令行 (phpUnit) 和浏览器中存在问题。
有问题的文件的权限是 -rwxrwxrwx
(我 sudo-chmod-777ed 文件)
这是一个创建行为的代码 sn-p:
$dir1 = '/a/path/to/a/../file.php';
$dir2 = '/a/path/to/file.php';
echo "File content dir1:\n";
echo file_get_contents($dir1);
echo "\ndir1 exists: ".(int)file_exists($dir1);
echo "\n\nFile content dir2:\n";
echo file_get_contents($dir2);
echo "\ndir2 exists: ".(int)file_exists($dir2);
输出是:
File content dir1:
The actual content of the file. I promise!
dir1 exists: 0
File content dir2:
The actual content of the file. I promise!
dir2 exists: 1
【问题讨论】:
您可以在此处发布您要比较的具体代码吗?file_exists()
应该可以很好地处理这样的路径。
我无法重现这种行为——我尝试了相对路径和绝对路径,都包括'..'
@谁投票结束“不清楚你在问什么”,请说明你觉得不清楚的地方,我很乐意解决你的问题。
【参考方案1】:
听起来您打开了安全模式,并试图访问在安全模式下运行时 PHP 会认为不安全的文件。 From the manual:
警告
对于由于安全模式限制而无法访问的文件,此函数返回 FALSE。但是,如果这些文件位于 safe_mode_include_dir 中,仍然可以包含这些文件。
编辑:如果/a/path/to/a/
不是真实路径,您也可以重现此行为。例如:
<?php
$dir1 = '/realDir/realDir2/filetoinclude.php';
echo "File content dir1:\n";
echo file_get_contents($dir1); // outputs file contents
echo "\ndir1 exists: ".(int)file_exists($dir1); // outputs 1
$dir2 = '/realDir/realDir2/realDir3/../filetoinclude.php';
echo "\n\nFile content dir2:\n";
echo file_get_contents($dir2); // outputs file contents
echo "\ndir2 exists: ".(int)file_exists($dir2); // outputs 1
$dir3 = '/realDir/realDir2/NotARealDirectory/../filetoinclude.php';
echo "\n\nFile content dir3:\n";
echo file_get_contents($dir3); // outputs file contents
echo "\ndir3 exists: ".(int)file_exists($dir3); // outputs 0
这是因为 file_exists 需要遍历整个路径,从字面上看,它会查找丢失的目录并失败。我不确定 file_get_contents 到底有什么不同,我在 Google 上也找不到太多,但它显然对路径进行了一些解析,这与 file_exists 所做的不同。
【讨论】:
嗯...你在 php.ini 中设置了 open_basedir 吗? 是的,关闭 open_basedir ——它可能会干扰您的代码,这就是我问的原因。 file_exists 的结果被缓存。您是否尝试过仅清除缓存? us1.php.net/manual/en/function.clearstatcache.php 我唯一的其他理论是文件大小或权限问题。文件有多大?有时,由于 *nixstat
的工作方式,这可能会导致失败。
这是一个本地文件,不是远程文件或符号链接,而是一个真实文件?【参考方案2】:
如果其他人有同样的问题,我将提供我使用正则表达式开发的解决方法。我讨厌使用这个 hack,我仍然不明白为什么我会遇到这个问题,但希望有人能提出一个实际的解决方案。
在调用file_exists
之前我现在调用这个函数:
function resolve($path)
$regex = "/(.?)(\/[^\/]*\/\.\.)(.*)/";
$result = preg_replace($regex, "$1$3", $path);
if ($result != $path)
$result = resolve($result);
return $result;
【讨论】:
realpath
不适用于类 Unix 系统上相对路径中不存在的文件。与Windows相反,路径中的每个文件都必须存在。
您可能误解了我遇到的问题。文件存在。 realpaht
、is_file
或 file_exists
无法识别相对路径,就像我原来的帖子中的那样。 file_get_contents
成功检索到内容。
在这种情况下,您至少应该使用经过验证的算法,例如remove dot segments algorithm used for URIs。以上是关于file_exists 和包含相对路径的路径(“/../”)的主要内容,如果未能解决你的问题,请参考以下文章
file_exists 函数的 PHP 说明,它是检查实际文件还是仅检查路径