检查文件是否存在于文件夹中

5

我的脚本:

$secret = check_input($_GET['secret']);
if(isset($_POST['register'])) {
    if (isset($secret) || !empty($secret)) {
        if (file_exists(ROOT . '/intl/codes/' . $secret)) {
            unlink(ROOT . '/intl/codes/' . $secret);
            $trusted = 'yes';
        } else {
            $trusted = 'no';
        }
    }
//$_POST['register'] register details...
}
  1. 有没有其他方法可以做到这一点(更简单等)?
  2. 如果$secret/codes/文件夹中不存在,则会产生警告:unlink是目录。如何摆脱它?
  3. 为什么即使文件不存在,$trusted始终给出yes?
5个回答

6

删除目录时,应使用rmdir()而不是unlink()

$secret = check_input($_GET['secret']);
if(isset($_POST['register'])) {
    if (!empty($secret)) {
        if(file_exists(ROOT . '/intl/codes/' . $secret)) {
            rmdir(ROOT . '/intl/codes/' . $secret);
            $trusted = 'yes';
        } else {
            $trusted = 'no';
        }
    }
    //$_POST['register'] register details...
}

虽然这里存在严重的安全风险!如果你的check_input()没有正确地对$secret进行过滤,你可能会执行rmdir('/intl/codes/../'),这将导致删除/intl/目录。 尝试使用以下代码:

$allowed = ROOT. '/intl/codes/';
$path = realpath($allowed . check_input($_GET['secret']));

if(strpos($path, $allowed) === 0) {  //Check that $path is within allowed directory
    if(is_dir($path)) {
        rmdir($path);
    } else if(file_exists($path)) {
        unlink($path);
    } else {
        echo "File/folder not found";
    }
} else {
    echo "Untrusted user tried to delete outside of allowed directory";
}

1
  1. 你可以使用 if (!empty($secret)) - empty() 函数也会返回 TRUE,即使是 NULL 值。

  2. 使用 if (file_exists(ROOT . '/intl/codes/' . $secret) && !is_dir(ROOT . '/intl/codes/' . $secret)) 来检查文件是否不是目录,并消除警告。如果你仍想删除目录,请使用 rmdir() 函数。

  3. file_exists() 函数同样会返回 TRUE,即使是目录。所以,你应该像我之前说的那样,使用 is_dir() 函数来检查参数是否为目录。


1
    if (file_exists(ROOT . '/intl/codes/' . $secret)) {
        unlink(ROOT . '/intl/codes/' . $secret);
        $trusted = 'yes';
    } else {
        $trusted = 'no';
    }

有没有其他更简单的方法来做这件事情?
没有,唯一的方法是使用file_exists 如果在/codes/文件夹中不存在$secret,它会产生警告:unlink是一个目录。如何摆脱这个问题?
看起来$secret指向一个目录。执行路径到达unlink,因为if部分返回true。所以它存在。要删除一个目录,请使用rmdir() 为什么$trusted总是给出yes,即使文件不存在?
因为unlink将其删除并将$trusted设置为yes。当你在删除后搜索时,你会发现它不存在,但$trusted包含yes

1

显然你的$secret是一个空字符串,但它通过了你的isset()测试。 所以目录ROOT . '/intl/codes/'确实存在(因此通过了file_exists()检查),但你不能unlink()目录(这也不是你的意图)。

确保在$_GET['secret']中有非空内容,并验证你的check_input()函数。

P.S. 你可能应该删除条件中的isset($secret)部分。 !empty($secret)就足够了,它将修复你的脚本。


1
根据 PHP 文档关于 file_exists() 的说明:
Checks whether a file or directory exists

我对第三个问题的唯一猜测是:您检查文件是否存在,而实际上它不是文件,而是目录。
至于第二个问题,正如错误消息所述,您可以执行以下操作: $file_to_check = ROOT . '/intl/codes/' . $secret;
if (file_exists($file_to_check)) {
    if( !is_dir( $file_to_check ) )
        unlink($file_to_check);
    else
        rmdir( $file_to_check );
    $trusted = 'yes';
}

至于你的第一个问题,你可能想要做类似这样的事情:

$secret = input_get($_GET['secret']);
if(isset($_POST['register']) && !empty($secret)) {

    $file_to_check = ROOT . '/intl/codes/' . $secret;
    if (file_exists($file_to_check)) {
        if( !is_dir( $file_to_check ) )
            unlink($file_to_check);
        else
            rmdir( $file_to_check );
        $trusted = 'yes';
    } else {
        $trusted = 'no';
    }
}

function input_get($key, $default = ""){

    if(!isset($_GET[$key])){
        return $default;
    } else {
        //do input cleanup first, if you want
        return $_GET[$key];
    }
}

一点解释:
  1. 我不知道 check_input() 做了什么,所以我创建了一个包装函数 input_get() 来处理 $_GET[]。它消除了使用 isset() 的需要,并填充默认值。
  2. 我将 ROOT . '/intl/codes/' . $secret; 放入变量 $file_to_check 中,这样您就不必一遍又一遍地输入它了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接