$config */
$config = require $configPath;
$tokenExpected = (string)($config['token'] ?? '');
$tokenIncoming = (string)($_REQUEST['token'] ?? '');
if ($tokenExpected === '' || !hash_equals($tokenExpected, $tokenIncoming)) {
http_response_code(403);
header('Content-Type: text/plain; charset=utf-8');
echo "Forbidden: invalid token\n";
exit;
}
$photosDir = __DIR__ . '/photos';
if (!is_dir($photosDir)) {
mkdir($photosDir, 0775, true);
}
$message = '';
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = (string)($_POST['action'] ?? '');
if ($action === 'create_category') {
$rawName = trim((string)($_POST['category_name'] ?? ''));
$safeName = sanitizeCategoryName($rawName);
if ($safeName === '') {
$errors[] = 'Введите корректное имя папки.';
} else {
$dir = $photosDir . '/' . $safeName;
if (is_dir($dir)) {
$message = 'Папка уже существует.';
} elseif (mkdir($dir, 0775, true)) {
$message = 'Папка создана: ' . $safeName;
} else {
$errors[] = 'Не удалось создать папку.';
}
}
}
if ($action === 'upload') {
$selectedCategory = sanitizeCategoryName((string)($_POST['category'] ?? ''));
if ($selectedCategory === '') {
$errors[] = 'Выберите папку для загрузки.';
} else {
$categoryDir = $photosDir . '/' . $selectedCategory;
if (!is_dir($categoryDir)) {
$errors[] = 'Выбранная папка не существует.';
} else {
if (!isset($_FILES['photos'])) {
$errors[] = 'Файлы не переданы.';
} else {
$result = handleUploads($_FILES['photos'], $categoryDir);
$errors = array_merge($errors, $result['errors']);
if ($result['ok'] > 0) {
$message = 'Загружено файлов: ' . $result['ok'];
}
}
}
}
}
}
$categories = listCategories($photosDir);
$tokenForUrl = urlencode($tokenIncoming);
?>
Админка галереи
Админка загрузки
= htmlspecialchars($message, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>
= htmlspecialchars($err, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>
Создать папку (категорию)
Разрешены буквы/цифры/пробел/._- (остальное отфильтруется).
Загрузка фотографий
Ограничения: только JPG/PNG/WEBP/GIF, максимум 3 МБ на файл.
Текущие категории
Пока нет категорий.
- = htmlspecialchars($cat, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>
$files
* @return array{ok:int,errors:string[]}
*/
function handleUploads(array $files, string $targetDir): array
{
$allowedMime = [
'image/jpeg',
'image/png',
'image/webp',
'image/gif',
];
$allowedExt = ['jpg', 'jpeg', 'png', 'webp', 'gif'];
$ok = 0;
$errors = [];
$names = $files['name'] ?? [];
$tmpNames = $files['tmp_name'] ?? [];
$sizes = $files['size'] ?? [];
$errs = $files['error'] ?? [];
if (!is_array($names)) {
$names = [$names];
$tmpNames = [$tmpNames];
$sizes = [$sizes];
$errs = [$errs];
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
foreach ($names as $i => $originalName) {
$errCode = (int)($errs[$i] ?? UPLOAD_ERR_NO_FILE);
if ($errCode !== UPLOAD_ERR_OK) {
$errors[] = "Файл {$originalName}: ошибка загрузки ({$errCode}).";
continue;
}
$size = (int)($sizes[$i] ?? 0);
if ($size < 1 || $size > MAX_UPLOAD_BYTES) {
$errors[] = "Файл {$originalName}: превышен лимит 3 МБ.";
continue;
}
$tmp = (string)($tmpNames[$i] ?? '');
if ($tmp === '' || !is_uploaded_file($tmp)) {
$errors[] = "Файл {$originalName}: некорректный источник загрузки.";
continue;
}
$mime = $finfo ? (string)finfo_file($finfo, $tmp) : '';
if (!in_array($mime, $allowedMime, true)) {
$errors[] = "Файл {$originalName}: недопустимый тип ({$mime}).";
continue;
}
$ext = strtolower(pathinfo((string)$originalName, PATHINFO_EXTENSION));
if (!in_array($ext, $allowedExt, true)) {
$errors[] = "Файл {$originalName}: недопустимое расширение.";
continue;
}
$base = pathinfo((string)$originalName, PATHINFO_FILENAME);
$safeBase = preg_replace('/[^\p{L}\p{N}._-]+/u', '_', $base) ?? 'photo';
$safeBase = trim($safeBase, '._-');
if ($safeBase === '') {
$safeBase = 'photo';
}
$finalName = uniqueFileName($targetDir, $safeBase, $ext);
$dest = $targetDir . '/' . $finalName;
if (!move_uploaded_file($tmp, $dest)) {
$errors[] = "Файл {$originalName}: не удалось сохранить.";
continue;
}
@chmod($dest, 0664);
$ok++;
}
if ($finfo) {
finfo_close($finfo);
}
return ['ok' => $ok, 'errors' => $errors];
}
function uniqueFileName(string $dir, string $base, string $ext): string
{
$candidate = $base . '.' . $ext;
$n = 1;
while (file_exists($dir . '/' . $candidate)) {
$candidate = $base . '_' . $n . '.' . $ext;
$n++;
}
return $candidate;
}
/**
* @return string[]
*/
function listCategories(string $photosDir): array
{
$out = [];
$items = @scandir($photosDir) ?: [];
foreach ($items as $item) {
if ($item === '.' || $item === '..') {
continue;
}
if (is_dir($photosDir . '/' . $item)) {
$out[] = $item;
}
}
sort($out, SORT_NATURAL | SORT_FLAG_CASE);
return $out;
}