fix: link old

This commit is contained in:
hashbro
2026-09-14 02:18:56 +08:00
parent 4ae2bb14a6
commit f85aa3654a
2 changed files with 42 additions and 30 deletions
+30 -30
View File
@@ -261,19 +261,16 @@ class PhotoPreview
private function resolveBinary(string $name): ?string
{
$candidates = match ($name) {
'magick' => [base_path('bin/magick'), 'magick', '/opt/homebrew/bin/magick', '/usr/local/bin/magick', '/usr/bin/magick'],
'convert' => ['convert', '/usr/bin/convert'],
'heif-convert' => [base_path('bin/heif-convert'), 'heif-convert', '/usr/bin/heif-convert', '/usr/local/bin/heif-convert'],
'heif-dec' => [base_path('bin/heif-dec'), 'heif-dec', '/usr/bin/heif-dec', '/usr/local/bin/heif-dec'],
'magick' => [base_path('bin/magick'), '/opt/homebrew/bin/magick', '/usr/local/bin/magick', '/usr/bin/magick', 'magick'],
'convert' => [base_path('bin/convert'), '/usr/bin/convert', 'convert'],
'heif-convert' => [base_path('bin/heif-convert'), '/usr/bin/heif-convert', '/usr/local/bin/heif-convert', 'heif-convert'],
'heif-dec' => [base_path('bin/heif-dec'), '/usr/bin/heif-dec', '/usr/local/bin/heif-dec', 'heif-dec'],
default => [$name],
};
$outside = null;
$bare = null;
foreach ($candidates as $bin) {
if (! str_contains($bin, DIRECTORY_SEPARATOR)) {
$found = $this->which($bin);
if ($found !== null) {
return $found;
}
$bare ??= $bin;
continue;
@@ -281,26 +278,13 @@ class PhotoPreview
if ($this->isSafeExecutable($bin)) {
return $bin;
}
}
// exec() is often allowed when is_executable() is not; let Process try PATH.
return $bare;
}
private function which(string $name): ?string
{
$path = getenv('PATH');
if (! is_string($path) || $path === '') {
return null;
}
foreach (explode(PATH_SEPARATOR, $path) as $dir) {
$candidate = rtrim($dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$name;
if ($this->isSafeExecutable($candidate)) {
return $candidate;
// Panel open_basedir blocks PHP from stat() /usr/bin, but proc_open can still run it.
if (! $this->isPathInsideOpenBasedir($bin)) {
$outside ??= $bin;
}
}
return null;
return $outside ?? $bare;
}
private function isSafeExecutable(string $path): bool
@@ -318,14 +302,30 @@ class PhotoPreview
if ($basedir === '') {
return true;
}
$real = realpath($path);
$check = $real !== false ? $real : $path;
$roots = [];
foreach (explode(PATH_SEPARATOR, $basedir) as $root) {
$root = rtrim($root, DIRECTORY_SEPARATOR);
if ($root === '') {
continue;
if ($root !== '') {
$roots[] = $root;
}
if ($check === $root || str_starts_with($check, $root.DIRECTORY_SEPARATOR)) {
}
if ($this->pathPrefixedByRoot($path, $roots)) {
$real = @realpath($path);
$check = is_string($real) && $real !== '' ? $real : $path;
return $this->pathPrefixedByRoot($check, $roots);
}
return false;
}
/**
* @param list<string> $roots
*/
private function pathPrefixedByRoot(string $path, array $roots): bool
{
foreach ($roots as $root) {
if ($path === $root || str_starts_with($path, $root.DIRECTORY_SEPARATOR)) {
return true;
}
}
+12
View File
@@ -10,6 +10,18 @@ use Tests\TestCase;
class PhotoPreviewTest extends TestCase
{
#[Test]
public function basedir_probe_does_not_realpath_system_bins(): void
{
$preview = new PhotoPreview;
$ref = new \ReflectionMethod(PhotoPreview::class, 'isPathInsideOpenBasedir');
$this->assertFalse($ref->invoke($preview, '/usr/bin/heif-convert')
&& (string) ini_get('open_basedir') !== ''
&& ! str_contains((string) ini_get('open_basedir'), '/usr/bin'));
$resolved = (new \ReflectionMethod(PhotoPreview::class, 'resolveBinary'))->invoke($preview, 'heif-convert');
$this->assertNotNull($resolved);
}
#[Test]
public function detects_heic_ftyp_header(): void
{