v3.0.0.2
FlatlyPage
- <?php
- require_once __DIR__ . '/../config.php';
-
- require_login();
-
- header('Content-Type: application/json; charset=utf-8');
-
- const MEDIA_MAX_BYTES = 536870912;
- const MEDIA_LIST_LIMIT = 300;
-
- function media_respond(array $payload, int $status = 200): void
- {
- http_response_code($status);
- echo json_encode($payload);
- exit;
- }
-
- function media_ini_bytes(string $value): int
- {
- $value = trim($value);
- $unit = strtolower(substr($value, -1));
- $number = (float) $value;
- switch ($unit) {
- case 'g':
- $number *= 1024;
- case 'm':
- $number *= 1024;
- case 'k':
- $number *= 1024;
- }
- return (int) $number;
- }
-
- function media_format_bytes(int $bytes): string
- {
- if ($bytes >= 1048576) {
- return round($bytes / 1048576, 1) . ' MB';
- }
- return max(1, (int) round($bytes / 1024)) . ' KB';
- }
-
- $mediaDir = BASE_DIR . '/media';
- $types = media_types();
-
- if ($_SERVER['REQUEST_METHOD'] === 'GET') {
- $kind = $_GET['list'] ?? 'image';
- if (!isset($types[$kind])) {
- media_respond(['success' => false, 'error' => "This file type isn't supported here."], 400);
- }
-
- $items = [];
- foreach (glob($mediaDir . '/*') ?: [] as $file) {
- if (!is_file($file)) {
- continue;
- }
- $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
- if (!isset($types[$kind][$ext])) {
- continue;
- }
- $items[] = [
- 'url' => '/media/' . rawurlencode(basename($file)),
- 'name' => basename($file),
- 'size' => media_format_bytes((int) filesize($file)),
- 'mtime' => (int) filemtime($file),
- ];
- }
- usort($items, fn($a, $b) => $b['mtime'] <=> $a['mtime']);
- media_respond(['success' => true, 'items' => array_slice($items, 0, MEDIA_LIST_LIMIT)]);
- }
-
- if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- media_respond(['success' => false, 'error' => 'Method not allowed.'], 405);
- }
-
- $postMax = media_ini_bytes((string) ini_get('post_max_size'));
- if (empty($_FILES) && empty($_POST) && (int) ($_SERVER['CONTENT_LENGTH'] ?? 0) > 0 && $postMax > 0) {
- media_respond(['success' => false, 'error' => 'This file is too big for your server. The limit is ' . ini_get('post_max_size') . '.'], 413);
- }
-
- if (!verify_csrf_token((string) ($_POST['csrf_token'] ?? ''))) {
- media_respond(['success' => false, 'error' => 'Your session timed out. Refresh the page and try again.'], 403);
- }
-
- $kind = (string) ($_POST['kind'] ?? '');
- if (!isset($types[$kind])) {
- media_respond(['success' => false, 'error' => "This file type isn't supported here."], 400);
- }
-
- $file = $_FILES['file'] ?? null;
- if (!$file || !is_array($file) || is_array($file['name'] ?? null)) {
- media_respond(['success' => false, 'error' => "The file didn't arrive. Please try again."], 400);
- }
-
- if ($file['error'] !== UPLOAD_ERR_OK) {
- $messages = [
- UPLOAD_ERR_INI_SIZE => 'This file is too big for your server. The limit is ' . ini_get('upload_max_filesize') . '.',
- UPLOAD_ERR_FORM_SIZE => 'This file is too big.',
- UPLOAD_ERR_PARTIAL => "The upload was cut off. Please try again.",
- UPLOAD_ERR_NO_FILE => "The file didn't arrive. Please try again.",
- UPLOAD_ERR_NO_TMP_DIR => "Your server is missing its temporary folder. Ask your hosting provider to check it.",
- UPLOAD_ERR_CANT_WRITE => "Your server couldn't save the file. Check the folder permissions.",
- UPLOAD_ERR_EXTENSION => "Your server blocked this upload.",
- ];
- media_respond(['success' => false, 'error' => $messages[$file['error']] ?? 'Upload failed.'], 400);
- }
-
- if (!is_uploaded_file($file['tmp_name'])) {
- media_respond(['success' => false, 'error' => "The upload didn't work. Please try again."], 400);
- }
-
- if ($file['size'] > MEDIA_MAX_BYTES) {
- media_respond(['success' => false, 'error' => 'This file is bigger than ' . media_format_bytes(MEDIA_MAX_BYTES) . '.'], 413);
- }
-
- $original = (string) $file['name'];
- $ext = strtolower(pathinfo($original, PATHINFO_EXTENSION));
- if (!isset($types[$kind][$ext])) {
- media_respond(['success' => false, 'error' => '.' . $ext . ' files can\'t be used here. You can upload: ' . implode(', ', array_keys($types[$kind])) . '.'], 415);
- }
-
- if (function_exists('finfo_open')) {
- $finfo = finfo_open(FILEINFO_MIME_TYPE);
- $mime = $finfo ? (string) finfo_file($finfo, $file['tmp_name']) : '';
- unset($finfo);
- if ($mime !== '' && !in_array($mime, $types[$kind][$ext], true) && $mime !== 'application/octet-stream') {
- media_respond(['success' => false, 'error' => "This file's content doesn't match its extension."], 415);
- }
- }
-
- if ($kind === 'image' && $ext !== 'ico' && $ext !== 'avif' && @getimagesize($file['tmp_name']) === false) {
- media_respond(['success' => false, 'error' => "This file isn't a valid image."], 415);
- }
-
- if (!is_dir($mediaDir) && !mkdir($mediaDir, 0755, true) && !is_dir($mediaDir)) {
- media_respond(['success' => false, 'error' => "Couldn't create the media folder. Check the folder permissions on your server."], 500);
- }
-
- $base = slugify(pathinfo($original, PATHINFO_FILENAME));
- $base = substr($base === '' ? 'file' : $base, 0, 60);
- do {
- $name = $base . '-' . bin2hex(random_bytes(4)) . '.' . $ext;
- $target = $mediaDir . '/' . $name;
- } while (file_exists($target));
-
- if (!move_uploaded_file($file['tmp_name'], $target)) {
- media_respond(['success' => false, 'error' => "Couldn't save the file. Please try again."], 500);
- }
- @chmod($target, 0644);
-
- media_respond([
- 'success' => true,
- 'url' => '/media/' . rawurlencode($name),
- 'name' => $name,
- 'kind' => $kind,
- 'size' => media_format_bytes((int) $file['size']),
- ]);
-