Trace web UI troubleshooting changes

This commit is contained in:
hbrain 2026-06-14 21:10:58 +02:00
parent eed092d872
commit a600e035d5
2 changed files with 38 additions and 6 deletions

View file

@ -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;

View file

@ -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);