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_filerealpath),则返回值表明该文件不存在。似乎是什么问题?


编辑:以下是从 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 我唯一的其他理论是文件大小或权限问题。文件有多大?有时,由于 *nix stat 的工作方式,这可能会导致失败。 这是一个本地文件,不是远程文件或符号链接,而是一个真实文件?【参考方案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相反,路径中的每个文件都必须存在。 您可能误解了我遇到的问题。文件存在。 realpahtis_filefile_exists 无法识别相对路径,就像我原来的帖子中的那样。 file_get_contents 成功检索到内容。 在这种情况下,您至少应该使用经过验证的算法,例如remove dot segments algorithm used for URIs。

以上是关于file_exists 和包含相对路径的路径(“/../”)的主要内容,如果未能解决你的问题,请参考以下文章

file_exists 函数的 PHP 说明,它是检查实际文件还是仅检查路径

vs2010 相对路径中附加包含目录 不好用,请帮忙看看

如何修复 PHP 警告:file_exists():文件名超过此平台上允许的最大路径长度 (260)?

相对路径和绝对路径的区别是啥?

如何在不包含上下文根名称的情况下使用相对路径?

AJAX 和相对路径范围