Несколько правил которые необходимо соблюдать:
- 1. НИКОГДА НЕ ДОВЕРЯЙТЕ ПОЛЬЗОВАТЕЛЯМ
- 2. Файлы никогда не должны исполнятся на сервере ( 644 )
- 3. Нельзя доверять $_FILES[][‘type’]
Если коротко то недавний холивар в php@conference.jabber.ru на тему загрузок файлов заставил меня пересмотреть мой алгоритм проверки файлов. Исходом явилось то что я написал более или менее нормальную функцию проверки файлов. Но не идеальную, так что не пренебрегайте настройкой прав доступа на загружаемые файлы 😉
Все довольно просто и умещается на 74 строчек, хотя все зависит только от количества разрешенных к загрузке файлов, итак:
upload.php
<?php
include_once("function.php");
if (@$_POST['upload_file']) {
if ($_FILES['upload_file']['error'] === UPLOAD_ERR_OK) {
if (file_check($_FILES)) {
copy($_FILES['upload_file']['tmp_name'],"file/".$_FILES['upload_file']['name']);
}
} else {
$messages[] = 'При загрузке произошла ошибка, возможно вы не выбрали файл';
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Safe Upload File</title>
</head>
<body>
<?php
if (isset($messages)) {
displayErrors($messages);
}
?>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="upload_file" id="" />
<input type="submit" value="Upload" name="upload_file" />
</form>
</body>
</html>
function.php
<?php
# Вывод сообщений об ошибках
function displayErrors($messages) {
global $messages;
print("<b>Ошибочка вышла!</b><br/>");
foreach($messages as $msg){
print("<b>→</b> $msg<br />");
}
}
function file_check($_FILES) {
global $messages;
$expansion = strtolower(pathinfo($_FILES['upload_file']['name'], PATHINFO_EXTENSION));
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['upload_file']['tmp_name']);
$allow_expansion = array (
"bmp" => "image/bmp",
"gif" => "image/gif",
"ief" => "image/ief",
"jpeg" => "image/jpeg",
"jpg" => "image/jpeg",
"jpe" => "image/jpeg",
"png" => "image/png"
);
if ($mime !== $_FILES['upload_file']['type']) {
$messages[] = 'Ваш файл не прошел проверку';
return false;
} else {
foreach ($allow_expansion as $key => $value) {
if($value == $mime){
if ($key == $expansion) {
return true;
}
}
}
$messages[] = 'Ваш файл не прошел проверку';
}
}
?>
Начнем пожалуй с upload.php. Для начала подключаем файл с функциями. По нажатию на кнопочку делаем проверку на то что был выбран файл ( строка 4 ) и если все нормально на пятой строке проверяем какой результат вернула функция file_check. Ну и в конце на 21-23 строчке выводим ошибки если таковые есть.
Ну и самое интересное в function.php. Первой идет функция вывода ошибок, ее я использовал и раньше, нас интересует проверка.
1. Мы получаем расширение файла из $_FILES ( строка 15 ) и сразу переводим его в нижний регистр ( вдруг было в верхнем? )
2. Далее мы получаем mime type, но не из $_FILES[‘upload_file’][‘type’] а из самого файла, на случай если нам таки подсунули $_FILES.
3. Делаем массив разрешенных mime type для загрузки ( позже дам ссылки на ресурсы где можно подсмотреть какие они бывают еще ).
4. Сравниваем полученный нами mime type с тем что пришел от пользователя в $_FILES и если они разные сразу даем сообщение о ошибке и возвращаем false
5. Проходим по массиву разрешенных разрешений и ищем совпадении расширения файла с mime type в нашем массиве.
6. Если все хорошо то возвращаем true — проверка прошла успешно.
Следует сказать так же что если у Вас разрешена загрузка только изображений то следует так же проверять это функцией getimagesize() (если изображение то возвращается массив).
Ну и напоследок довольно большой список mime type
Добавить комментарий