2009-05-09 3 views
0

Я пишу PHP-приложение с «панелью управления», которое записывает файл prefs с определенными переменными. В каждом POST, если файл не существует, он создается. Если он существует, это unlinked, а новый файл - touched с тем же именем и новыми переменными. Этот файл затем включается на другую страницу с отображением содержимого на основе переменных внутри него.План непредвиденных обстоятельств для ошибки fopen в php

$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)?

+0

Итак, ваш вопрос: «Безопасно ли использовать файл для хранения состояния моих пользователей в моем приложении?« –

+0

Подумайте о добавлении вызовов flock после вызовов fopen. Http://www.php.net/flock – Powerlord

ответ

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)); 

За все вопросы этой связи возникает, хотя, реальность такова, что с вашим приложением, в маловероятном случае, что-то делает ошибетесь с FOPEN, следует рассматривать как серьезную неудачу в любом случае, и горстка пользователей, с которыми вы, вероятно, будете пользоваться этой функцией, скоро свяжется с вами довольно быстро, если что-то пойдет не так.

+0

Это решение по-прежнему необходимо, если (а) параметры - это переключатели, а не текстовые поля - да, они все еще манипулируют, но (б) я доверяю небольшой группе людей, которые будут использовать эта форма? –

+0

Не совсем, но это может быть хорошим упражнением по формированию привычки, если ничего другого, и хорошей практикой при использовании методов для смягчения проблем с инъекциями. – Shabbyrobe

0

Почему бы не просто использовать функции усечения fopen()? Я верю вместо «r +», вам нужно передать «w +» ... Тогда, если файл существует, он будет усечен, если нет, вы просто создадите новый файл. Таким образом, код становится следующим:

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

Всегда лучше сохранять состояние пользователя в сеансе и сохранять его только при необходимости.

+0

Я должен был уточнить - это не префизы для отдельных пользователей, это префикс для того, как страница будет выглядеть для всех, кто приходит к этой странице, они являются «предпочтениями редакторов». –

+0

Таким образом, каждый пользователь может установить другой вид страницы? –

+0

Нет, один авторизованный пользователь устанавливает страницу из набора предопределенных параметров. как этот один пользователь определяет. –

Смежные вопросы