php -S {$_SERVER['SERVER_NAME']}:{$_SERVER['SERVER_PORT']} system/router.php"); } } if (PHP_SAPI !== 'cli') { if (!isset($_SERVER['argv']) && !ini_get('register_argc_argv')) { $queryString = $_SERVER['QUERY_STRING'] ?? ''; $_SERVER['argv'] = $queryString !== '' ? [$queryString] : []; $_SERVER['argc'] = $queryString !== '' ? 1 : 0; } $requestUri = $_SERVER['REQUEST_URI'] ?? ''; $scriptName = $_SERVER['SCRIPT_NAME'] ?? ''; $path = parse_url($requestUri, PHP_URL_PATH) ?? '/'; $path = str_replace('\\', '/', $path); $scriptDir = str_replace('\\', '/', dirname($scriptName)); if ($scriptDir && $scriptDir !== '/' && $scriptDir !== '.') { if (strpos($path, $scriptDir) === 0) { $path = substr($path, strlen($scriptDir)); $path = $path === '' ? '/' : $path; } } // Fast static asset serving for plugins that bundle SPA apps. // Checks for a plugin-asset-map.php file that maps route prefixes to // physical directories, serving files directly without booting Grav. $assetMapFile = __DIR__ . '/user/config/plugin-asset-map.php'; if (is_file($assetMapFile)) { $assetMap = require $assetMapFile; foreach ($assetMap as $routePrefix => $diskPath) { if (str_starts_with($path, $routePrefix)) { $relPath = substr($path, strlen($routePrefix)); $filePath = __DIR__ . '/' . ltrim($diskPath, '/') . $relPath; $realFile = realpath($filePath); $realBase = realpath(__DIR__ . '/' . ltrim($diskPath, '/')); if ($realFile && $realBase && str_starts_with($realFile, $realBase) && is_file($realFile)) { $ext = strtolower(pathinfo($realFile, PATHINFO_EXTENSION)); $mimeMap = [ 'js' => 'text/javascript', 'mjs' => 'text/javascript', 'css' => 'text/css', 'json' => 'application/json', 'svg' => 'image/svg+xml', 'png' => 'image/png', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'webp' => 'image/webp', 'avif' => 'image/avif', 'woff2' => 'font/woff2', 'woff' => 'font/woff', 'ico' => 'image/x-icon', ]; header('Content-Type: ' . ($mimeMap[$ext] ?? 'application/octet-stream')); header('Content-Length: ' . filesize($realFile)); header('Cache-Control: ' . (str_contains($relPath, '/immutable/') ? 'public, max-age=31536000, immutable' : 'public, max-age=3600')); readfile($realFile); exit; } } } } if ($path === '/___safe-upgrade-status') { $statusEndpoint = __DIR__ . '/user/plugins/admin/safe-upgrade-status.php'; if (!\defined('GRAV_ROOT')) { // Minimal bootstrap so the status script has the expected constants. require_once __DIR__ . '/system/defines.php'; } header('Content-Type: application/json; charset=utf-8'); if (is_file($statusEndpoint)) { require $statusEndpoint; } else { http_response_code(404); echo json_encode([ 'status' => 'error', 'message' => 'Safe upgrade status endpoint unavailable.', ]); } exit; } } // Maintenance mode during core upgrade if (file_exists(__DIR__ . '/.upgrading')) { if (time() - filemtime(__DIR__ . '/.upgrading') > 300) { @unlink(__DIR__ . '/.upgrading'); // Stale flag (>5 min), remove it } else { http_response_code(503); header('Retry-After: 60'); echo '
Please try again in a moment.
'; exit; } } // Ensure vendor libraries exist $autoload = __DIR__ . '/vendor/autoload.php'; if (!is_file($autoload)) { die('Please run: bin/grav install'); } // Register the auto-loader. $loader = require $autoload; // Set timezone to default, falls back to system if php.ini not set date_default_timezone_set(@date_default_timezone_get()); // Set internal encoding. @ini_set('default_charset', 'UTF-8'); mb_internal_encoding('UTF-8'); // Use getcwd() for paths to support symlinked index.php (GRAV_ROOT uses getcwd()) $gravRoot = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', getenv('GRAV_ROOT') ?: getcwd()), '/'); // Helper function to check if recovery mode is enabled in config (updates.recovery_mode) $isRecoveryEnabled = static function () use ($gravRoot) { $userConfig = $gravRoot . '/user/config/system.yaml'; if (!is_file($userConfig)) { return true; // Default enabled } $content = file_get_contents($userConfig); if ($content === false) { return true; } if (preg_match('/^\s*updates:\s*\n(?:\s+\w+:.*\n)*?\s+recovery_mode:\s*(true|false|1|0)\s*$/m', $content, $matches)) { return in_array(strtolower($matches[1]), ['true', '1'], true); } return true; // Default enabled }; $recoveryFlag = $gravRoot . '/user/data/recovery.flag'; if (PHP_SAPI !== 'cli' && is_file($recoveryFlag) && $isRecoveryEnabled()) { if (!defined('GRAV_ROOT')) { define('GRAV_ROOT', $gravRoot); } require __DIR__ . '/system/recovery.php'; return 0; } use Grav\Common\Grav; use RocketTheme\Toolbox\Event\Event; // Get the Grav instance $grav = Grav::instance(['loader' => $loader]); // Process the page try { $grav->process(); } catch (\Error|\Exception $e) { $grav->fireEvent('onFatalException', new Event(['exception' => $e])); if (PHP_SAPI !== 'cli' && is_file($recoveryFlag) && $isRecoveryEnabled()) { require __DIR__ . '/system/recovery.php'; return 0; } throw $e; }