diff --git a/index.php b/index.php index 103b4e62fd2..f1e17b576e7 100644 --- a/index.php +++ b/index.php @@ -56,22 +56,6 @@ $request = Request::createFromGlobals(); $maintenanceFile = env('ECCUBE_MAINTENANCE_FILE_PATH', __DIR__.'/.maintenance'); - -if (file_exists($maintenanceFile)) { - $pathInfo = \rawurldecode($request->getPathInfo()); - $adminPath = env('ECCUBE_ADMIN_ROUTE', 'admin'); - $adminPath = '/'.\trim($adminPath, '/').'/'; - if (\strpos($pathInfo, $adminPath) !== 0) { - $locale = env('ECCUBE_LOCALE'); - $templateCode = env('ECCUBE_TEMPLATE_CODE'); - $baseUrl = \htmlspecialchars(\rawurldecode($request->getBaseUrl()), ENT_QUOTES); - - header('HTTP/1.1 503 Service Temporarily Unavailable'); - require __DIR__.'/maintenance.php'; - return; - } -} - $kernel = new Kernel($env, $debug); $response = $kernel->handle($request); $response->send(); diff --git a/src/Eccube/EventListener/MaintenanceListener.php b/src/Eccube/EventListener/MaintenanceListener.php new file mode 100644 index 00000000000..925bc7c9913 --- /dev/null +++ b/src/Eccube/EventListener/MaintenanceListener.php @@ -0,0 +1,125 @@ +context = $context; + $this->systemService = $systemService; + } + + public static function getSubscribedEvents() + { + return [ + KernelEvents::REQUEST => 'onRequest', + ]; + } + + public function onRequest(GetResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + if ($this->context->isAdmin() || !$this->systemService->isMaintenanceMode()) { + return; + } + + $request = $event->getRequest(); + if ($this->isAdminAuthenticated($request)) { + return; + } + + $locale = \env('ECCUBE_LOCALE'); + $templateCode = \env('ECCUBE_TEMPLATE_CODE'); + $baseUrl = htmlspecialchars(\rawurldecode($request->getBaseUrl()), ENT_QUOTES); + + \ob_start(); + require __DIR__ . '/../../../maintenance.php'; + $response = new Response(\ob_get_clean(), 503); + $event->setResponse($response); + } + + private function isAdminAuthenticated(Request $request): bool + { + $session = $request->hasPreviousSession() ? $request->getSession() : null; + + if ($session === null || ($serializedToken = $session->get(self::SESSION_KEY)) === null) { + return false; + } + + $unserializedToken = $this->safelyUnserialize($serializedToken); + $user = ($unserializedToken instanceof TokenInterface) + ? $unserializedToken->getUser() + : null; + + return $user instanceof Member; + } + + private function safelyUnserialize($serializedToken) + { + $e = $token = null; + $prevUnserializeHandler = \ini_set('unserialize_callback_func', __CLASS__ . '::handleUnserializeCallback'); + $prevErrorHandler = \set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler) { + if (__FILE__ === $file) { + throw new \UnexpectedValueException($msg, 0x37313bc); + } + + return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false; + }); + + try { + $token = \unserialize($serializedToken); + } catch (\Error $e) { + } catch (\Exception $e) { + } + \restore_error_handler(); + \ini_set('unserialize_callback_func', $prevUnserializeHandler); + if ($e) { + if (!$e instanceof \UnexpectedValueException || 0x37313bc !== $e->getCode()) { + throw $e; + } + } + + return $token; + } + + /** + * @internal + */ + public static function handleUnserializeCallback($class) + { + throw new \UnexpectedValueException('Class not found: ' . $class, 0x37313bc); + } +}