JezK
Edit File: grep.php
<?php /** * grep-license.php — Search "license not valid" across all files/folders. * - Default base path: current directory * - Optional: ?path=/var/www/site (browser) or --path=/var/www/site (CLI) * - Ignores common big/vendor folders and binary/large files */ ini_set('memory_limit', '512M'); set_time_limit(0); $isCli = (php_sapi_name() === 'cli'); function arg($k, $def=null){ global $isCli; if ($isCli) { foreach ($GLOBALS['argv'] ?? [] as $a) { if (preg_match('/^--'.preg_quote($k,'/').'(=(.*))?$/', $a, $m)) return $m[2] !== '' ? $m[2] : true; } return $def; } return $_GET[$k] ?? $_POST[$k] ?? $def; } $query = 'license not valid'; // fixed phrase $basePath = rtrim((string) arg('path', getcwd()), DIRECTORY_SEPARATOR); $maxBytes = (int) arg('max_file_bytes', 5*1024*1024); // 5 MB $skipDirs = ['.git','.hg','.svn','.idea','.vscode','node_modules','vendor','storage','cache','logs']; if (!is_dir($basePath)) { $msg = "Path not found or not a directory: $basePath"; if ($isCli) { fwrite(STDERR, $msg.PHP_EOL); exit(1); } header('Content-Type: text/plain; charset=utf-8'); echo $msg; exit; } // quick binary check function isBinarySample(string $s): bool { if (strpos($s, "\0") !== false) return true; $len = strlen($s); if ($len===0) return false; $non = 0; for ($i=0; $i<$len; $i++) { $o = ord($s[$i]); if ($o===9||$o===10||$o===13) continue; if ($o<32 || $o>126) $non++; if ($non > $len*0.3) return true; } return false; } function shouldScan(string $file, int $maxBytes): bool { if (!is_file($file)) return false; if ($maxBytes>0 && @filesize($file) > $maxBytes) return false; $fp = @fopen($file,'rb'); if (!$fp) return false; $s = fread($fp, 4096); fclose($fp); if ($s===false) return false; return !isBinarySample($s); } $start = microtime(true); $hits = 0; $dirIt = new RecursiveDirectoryIterator($basePath, FilesystemIterator::SKIP_DOTS); $filter = new RecursiveCallbackFilterIterator($dirIt, function($cur) use ($skipDirs){ if ($cur->isDir()) return !in_array($cur->getFilename(), $skipDirs, true); return true; }); $it = new RecursiveIteratorIterator($filter); header('Content-Type: text/plain; charset=utf-8'); echo "Searching for: \"{$query}\" (case-insensitive)\nPath: {$basePath}\n\n"; foreach ($it as $info) { $file = $info->getPathname(); if (!shouldScan($file, $maxBytes)) continue; $lineNo = 0; $fh = @fopen($file, 'r'); if (!$fh) continue; while (($line = fgets($fh)) !== false) { $lineNo++; if (stripos($line, $query) !== false) { $hits++; // Trim line to avoid massive output $snippet = rtrim($line, "\r\n"); // Optional shorten long lines if (strlen($snippet) > 300) $snippet = substr($snippet, 0, 300) . '…'; echo $file . ':' . $lineNo . ' ' . $snippet . "\n"; } } fclose($fh); } $elapsed = round(microtime(true)-$start, 3); echo "\nDone. Matches: {$hits}. Time: {$elapsed}s\n";