Функция писалась для Yii (да, я знаю о существовании расширений и о наличии валидатора yii, вопрос в безопасности
конкретно этой функции, т.к. планируется её расширение).
а) Можно ли упростить код?
б) Достаточно ли он безопасен?
в) Предположим, хакер умудрился дать серверу возможность исполнять .jpg, .gif и .png файлы. Есть ли у него теперь шелл?
/**
* Функция заливки изображений
*
* Раскидывает изображения в папки /month/generateFilename
* Необязательные параметр - $resolution, ширина и высота. Если они не переданы, просто заливает
* Возвращает false если это не картинка или если высота, размер или ширина не верны,
* Иначе возвращает true;
*
* параметр $resolution = array('width'=>'...','height'=>'...')
*/
public function uploadImage($files,$resolution = null, $size = false)
{
# Если не передан максимальный размер картинки, берём значение из конфига
if($size === null)
$size = Yii::app()->params['imageUpload']['maxSize'];
foreach($files as $key=>$value)
{
# Если файл передан в виде $_FILES['Array']['name']['inputname']
if(is_array($files[$key]['name']))
{
foreach ($files[$key]['name'] as $k => $v)
{
$name = $k;
}
$file['name'] = $files[$key]['name'][$name];
$file['tmp_name'] = $files[$key]['tmp_name'][$name];
$file['size'] = $files[$key]['size'][$name];
}
# Иначе, обычный $_FILES['inputname']['name']
else
{
$file['name'] = $files[$key]['name'];
$file['tmp_name'] = $files[$key]['tmp_name'];
$file['size'] = $files[$key]['size'];
}
# На выходе $file с нужными данными $file = array('name'=>'...','tmp_name'=>'...','size'=>'...')
}
# Если размер превышает допустымый на сервере, возвращаем false
if($file['size'] > $size*1024)
return false;
# Белый список расширений
$whiteList = array('jpg', 'jpeg', 'png', 'gif');
# Находим расширение файла в нижнем регистре
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
# Перебираем массив с допустимыми расширениями
foreach ($whiteList as $value) {
# Если совпадение найдено, заливаем изображение
if($value == $ext)
{
# Для функции создания изображения
if($ext === 'jpg' OR $ext === 'jpeg')
$function_postfix = 'jpeg';
else
$function_postfix = $ext;
# Находим имя функции
$function_create = 'imagecreatefrom'.$function_postfix;
# Сохраняем ресур изображения
$img = $function_create($file['tmp_name']);
# Если переданы параметры ширины и высоты изображения, проверяем их
if($resolution !== null)
{
if($resolution['width'] !== imagesx($img))
return false;
if($resolution['height'] !== imagesy($img))
return false;
}
# Генерируем имя файла
$filename = mb_substr(md5(rand(0,99999999).time()), 16).'_'.time().'.'.$ext;
# текущий месяц для пути
$current_month = date("F");
# Определяем путь до изображения
$way = $_SERVER['DOCUMENT_ROOT'].'/'.Yii::app()->params['imageUpload']['url'].'/'.$current_month;
# Проверяем существование пути до изображения. Если не существует, создаём
if(!file_exists($way))
mkdir($way);
# Определяем функцию сохранения изображения
$function_save = 'image'.$function_postfix;
# Сохраняем изображение
$function_save($img,$way.'/'.$filename);
# Возвращаем путь до изображения
return $current_month.'/'.$filename;
}
}
# Если расширение не найдёно, возвращаем false
return false;
}
Про то, что картинки следует хранить на другом сервере без поддержки PHP я тоже знаю. Меня интересует простое решение для простых смертных. Спасибо