From a600e035d527b6e8ce1c4eeff6f5ad5abe7ee6a5 Mon Sep 17 00:00:00 2001 From: hbrain Date: Sun, 14 Jun 2026 21:10:58 +0200 Subject: [PATCH] Trace web UI troubleshooting changes --- admin.php | 19 +++++++++++++++++-- index.php | 25 +++++++++++++++++++++---- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/admin.php b/admin.php index cd02240..40b5a32 100644 --- a/admin.php +++ b/admin.php @@ -250,8 +250,21 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) { @unlink($outputPath); } -function input_dirs($base){ return glob($base.'/*', GLOB_ONLYDIR) ?: []; } -function safe_input_dir($base, $name){ $name = basename((string)$name); $path = realpath($base . '/' . $name); $root = realpath($base); if (!$path || !$root || !str_starts_with($path, $root . DIRECTORY_SEPARATOR) || !is_dir($path)) throw new RuntimeException('Invalid input directory.'); return $path; } +function ensure_input_dir_permissions($dir){ + if (!is_dir($dir) || is_link($dir)) return; + @chmod($dir, 02775); + $items = @scandir($dir); + if (!is_array($items)) return; + foreach ($items as $name) { + if ($name === '.' || $name === '..') continue; + $path = $dir . '/' . $name; + if (is_link($path)) continue; + if (is_dir($path)) @chmod($path, 02775); + elseif (is_file($path)) @chmod($path, 0664); + } +} +function input_dirs($base){ $dirs = glob($base.'/*', GLOB_ONLYDIR) ?: []; foreach ($dirs as $dir) ensure_input_dir_permissions($dir); return $dirs; } +function safe_input_dir($base, $name){ $name = basename((string)$name); $path = realpath($base . '/' . $name); $root = realpath($base); if (!$path || !$root || !str_starts_with($path, $root . DIRECTORY_SEPARATOR) || !is_dir($path)) throw new RuntimeException('Invalid input directory.'); ensure_input_dir_permissions($path); return $path; } function article_id_is_valid($id){ return is_string($id) && preg_match('/^[0-9]{14}[a-f0-9]{16}$/', $id); } function generate_article_id(){ return gmdate('YmdHis') . bin2hex(random_bytes(8)); } function read_article_id($dir){ @@ -598,6 +611,7 @@ function media_sort_datetime($path){ } function list_files($dir){ + ensure_input_dir_permissions($dir); $files = array_values(array_filter(scandir($dir), fn($f)=>editable_file($f) && is_file($dir.'/'.$f))); $orderFile = $dir . '/order.json'; @@ -1054,6 +1068,7 @@ function save_uploads($field, $dest, $allowed){ $base = preg_replace('/[^A-Za-z0-9._-]+/', '_', basename($files['name'][$i])); $target = $dest . '/' . sprintf('%03d_', count(glob($dest.'/*') ?: [])+count($saved)+1) . $base; if (!move_uploaded_file($files['tmp_name'][$i], $target)) throw new RuntimeException("Cannot save upload"); + @chmod($target, 0664); $saved[] = basename($target); } return $saved; diff --git a/index.php b/index.php index d761c21..a234328 100644 --- a/index.php +++ b/index.php @@ -64,6 +64,26 @@ function map_hidden_outputs($config){ return $hidden; } +function shown_video_paths($config){ + $videos = []; + $seen = []; + foreach (glob($config['uploads_dir'].'/*', GLOB_ONLYDIR) ?: [] as $dir) { + // Public index shows only items explicitly enabled with the admin "Show" switch. + if (is_file($dir . '/.mvlog-hidden')) continue; + $stateFile = $dir . '/.movmaker-state.json'; + if (!is_file($stateFile)) continue; + $state = json_decode((string)file_get_contents($stateFile), true); + if (!is_array($state)) continue; + $name = basename((string)($state['output'] ?? '')); + if ($name === '' || preg_match('/_preview\.(mp4|webm|mov|m4v)$/i', $name)) continue; + $path = $config['videos_dir'] . '/' . $name; + if (!is_file($path) || isset($seen[$name])) continue; + $seen[$name] = true; + $videos[] = $path; + } + return $videos; +} + function public_url_path($path){ $path = str_replace('\\', '/', trim((string)$path)); if ($path === '') return ''; @@ -269,10 +289,7 @@ function load_video_cache($videos){ $hiddenOutputs = hidden_video_outputs($config); $hiddenMapOutputs = map_hidden_outputs($config); -$allVideos = array_values(array_filter( - glob($config['videos_dir'].'/*.{mp4,webm,mov,m4v}', GLOB_BRACE) ?: [], - fn($v)=>!preg_match('/_preview\.(mp4|webm|mov|m4v)$/i', basename($v)) -)); +$allVideos = shown_video_paths($config); $videoCache = load_video_cache($allVideos);