$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); ?> Админка галереи

Админка загрузки

Создать папку (категорию)

Разрешены буквы/цифры/пробел/._- (остальное отфильтруется).

Загрузка фотографий

Ограничения: только JPG/PNG/WEBP/GIF, максимум 3 МБ на файл.

Текущие категории

Пока нет категорий.

$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; }