diff --git a/scripts/scan-files.php b/scripts/scan-files.php index 6bd939c..39de3ac 100755 --- a/scripts/scan-files.php +++ b/scripts/scan-files.php @@ -128,6 +128,30 @@ $filesScanned = 0; $skippedLinks = 0; $walkErrors = 0; +// Silence open_basedir E_WARNINGs during the walk. cPanel cpmove tarballs +// frequently contain symlinks pointing at the SOURCE server's absolute +// paths (db.php -> /home///wp-content/db.php, access-logs -> +// /usr/local/apache/domlogs/, etc.). PHP's open_basedir check +// normalizes via realpath() even for is_link/is_file; when the symlink +// target lies outside the container's allow-list (it does — there's no +// /home or /usr/local in the container), PHP emits a Warning per call. +// Our filter callback STILL returns the right answer (is_link returns +// true even when warning), so the skip-symlink logic works regardless +// of the noise — but the noise floods 100k+ lines into the import log +// for a typical customer account, drowning the actually-useful +// quarantine actions. +// +// set_error_handler limited to E_WARNING with a needle filter is +// narrower than `error_reporting(0)` (we still surface non-open_basedir +// warnings) and narrower than `@`-prefixing every call site (covers +// PHP-internal callbacks invoked deep inside the iterator). +$prevHandler = set_error_handler(function ($errno, $errstr) { + if ($errno === E_WARNING && strpos($errstr, 'open_basedir restriction') !== false) { + return true; // suppress + } + return false; // let PHP handle (or chain to previous handler) +}, E_WARNING); + $rdi = new RecursiveDirectoryIterator( $extractDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::CURRENT_AS_PATHNAME @@ -154,6 +178,8 @@ foreach ($it as $pathname) { $walkErrors++; } } + +restore_error_handler(); fwrite(STDERR, sprintf( "scan-files: file walk: counted=%d, symlinks-skipped=%d, walk-errors=%d\n", $filesScanned, $skippedLinks, $walkErrors