php中fopen错误的应急计划

时间:2009-05-09 15:05:01

标签: php fopen

我正在编写一个PHP应用程序,它有一个'控制面板',用于写入带有某些变量的prefs文件。在每个POST上,如果文件不存在,则创建该文件。如果确实存在,则为unlinked,新文件为touched,文件名和新变量相同。然后,此文件将包含在另一个页面上,并根据其中的变量显示内容。

$file = "phpsettings.php";

if (!file_exists($file)) {
   touch($file);
  $handle = fopen ($file, 'r+'); 
$str = "<?php \$pref1 = \"$mypref\"; ?>";

} else {

unlink($file);
   touch($file);
   $handle = fopen ($file, 'r+'); 
   $str = "<?php \$pref1 = \"$mypref\"; ?>";

}

fwrite ($handle, $str); 
fclose ($handle); 

如果这个文件每天会被覆盖多次,这是一种安全的写作首选方式吗?如果文件没有正确保存,那么警告用户控制面板的好方法是什么,在这种情况下,除了定义一个文件之外,还有一个很好的应急计划可以避免破坏页面这个prefs文件。要填充的默认变量集!(file_exists)

3 个答案:

答案 0 :(得分:2)

如果将设置存储在数组中,可以序列化()它们并写入文本文件,而不是将原始php写入php文件并包含它。

如果您没有清理那些偏好的输入,并且说$ mypref1代表某人的名字,那么就没有什么可以阻止他们在表单字段中填写:

\"; echo \"PWNED

并且您生成的PHP将成为

<?php \$pref1 = \"$mypref\"; echo \"PWNED\"; ?>

首先,将首选项存储在数组中并使用serialize()更加安全:

$prefs = array('mypref1' => 'somethingorother');
$handle = fopen ($file, 'w'); 
fwrite($handle, serialize($prefs));
fclose($h);

// example code demonstrating unserialization
$prefs2 = unserialize(file_get_contents($file));
var_dump($prefs == $prefs2); // should output "(bool) true"

在您的问题中,您还提到如果文件存在,则取消链接。您可以通过将“w”作为第二个参数传递给fopen来简单地将其截断为零长度 - 您不需要手动删除它。这应该设置mtime,否则需要调用touch()。

如果写入文件的值是首选项,那么每个首选项肯定都有默认值,除非有数百个? array_merge允许你在每个键的基础上覆盖,所以如果你做这样的事情:

// array of defaults
$prefs = array(
    'mypref1' => 'pants',
    'mypref2' => 'socks',
);
if (file_exists($file)) {
    // if this fails, an E_NOTICE is raised. are you checking your server error
    // logs regularly?
    if ($userprefs = unserialize(file_get_contents($file))) {
        $prefs = array_merge($prefs, $userprefs);
    }
}

如果问题是有堆,而你不想全部初始化它们,你可以使用get_preference方法将isset调用包装到prefs数组。

function get_preference($name, &$prefs) {
    if (isset($pref[$name]))
        return $pref[$name];
    return null;
}
var_dump(get_preference('mypref1', $prefs));

除了所提出的所有问题之外,现实情况是,使用你的应用程序,在不太可能发生的事情 错误的情况下,它应该被认为是一个严重的失败,如果出现问题,您可能会使用此功能的少数用户会非常快速地与您联系。

答案 1 :(得分:0)

为什么不直接使用fopen()的截断功能?我相信不是“r +”,你需要传递“w +”......然后如果文件存在,它将被截断,如果不存在,你只需要创建一个新文件。所以代码变成了:

$file = "phpsettings.php";
$handle = fopen( $file, 'w+' );
$str = "<?php \$pref1 = \"$mypref\"; ?>";
fwrite ($handle, $str); 
fclose ($handle);

答案 2 :(得分:0)

最好将用户状态存储在会话中,并且只在需要时保持该状态。