/** * Processes a generic exception into an HTTP 500 response. * * @param \Symfony\Component\Debug\Exception\FlattenException $exception * Metadata about the exception that was thrown. * @param \Symfony\Component\HttpFoundation\Request $request * The request object that triggered this exception. * * @return \Symfony\Component\HttpFoundation\Response * A response object. */ public function on500Html(FlattenException $exception, Request $request) { $error = $this->decodeException($exception); // Because the kernel doesn't run until full bootstrap, we know that // most subsystems are already initialized. $headers = array(); // When running inside the testing framework, we relay the errors // to the tested site by the way of HTTP headers. if (DRUPAL_TEST_IN_CHILD_SITE && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) { // $number does not use drupal_static as it should not be reset // as it uniquely identifies each PHP error. static $number = 0; $assertion = array($error['!message'], $error['%type'], array('function' => $error['%function'], 'file' => $error['%file'], 'line' => $error['%line'])); $headers['X-Drupal-Assertion-' . $number] = rawurlencode(serialize($assertion)); $number++; } watchdog('php', '%type: !message in %function (line %line of %file).', $error, $error['severity_level']); // Display the message if the current error reporting level allows this type // of message to be displayed, and unconditionnaly in update.php. if (error_displayable($error)) { $class = 'error'; // If error type is 'User notice' then treat it as debug information // instead of an error message. // @see debug() if ($error['%type'] == 'User notice') { $error['%type'] = 'Debug'; $class = 'status'; } // Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path // in the message. This does not happen for (false) security. $root_length = strlen(DRUPAL_ROOT); if (substr($error['%file'], 0, $root_length) == DRUPAL_ROOT) { $error['%file'] = substr($error['%file'], $root_length + 1); } // Should not translate the string to avoid errors producing more errors. $message = String::format('%type: !message in %function (line %line of %file).', $error); // Check if verbose error reporting is on. $error_level = $this->container->get('config.factory')->get('system.logging')->get('error_level'); if ($error_level == ERROR_REPORTING_DISPLAY_VERBOSE) { $backtrace_exception = $exception; while ($backtrace_exception->getPrevious()) { $backtrace_exception = $backtrace_exception->getPrevious(); } $backtrace = $backtrace_exception->getTrace(); // First trace is the error itself, already contained in the message. // While the second trace is the error source and also contained in the // message, the message doesn't contain argument values, so we output it // once more in the backtrace. array_shift($backtrace); // Generate a backtrace containing only scalar argument values. $message .= '<pre class="backtrace">' . Error::formatFlattenedBacktrace($backtrace) . '</pre>'; } drupal_set_message(SafeMarkup::set($message), $class, TRUE); } $content = $this->t('The website has encountered an error. Please try again later.'); $output = DefaultHtmlPageRenderer::renderPage($content, $this->t('Error')); $response = new Response($output); $response->setStatusCode(500, '500 Service unavailable (with message)'); return $response; }
} case 'info': $regions['sidebar_first'] = update_task_list('info'); $output = update_info_page(); break; case 'results': $regions['sidebar_first'] = update_task_list(); $output = update_results_page(); break; // Regular batch ops : defer to batch processing API. // Regular batch ops : defer to batch processing API. default: $regions['sidebar_first'] = update_task_list('run'); $output = _batch_page($request); break; } } else { $output = update_access_denied_page(); } if (isset($output) && $output) { // Explicitly start a session so that the update.php token will be accepted. \Drupal::service('session_manager')->start(); // We defer the display of messages until all updates are done. $progress_page = ($batch = batch_get()) && isset($batch['running']); if ($output instanceof Response) { $output->send(); } else { drupal_add_http_header('Content-Type', 'text/html; charset=utf-8'); print DefaultHtmlPageRenderer::renderPage($output, $output['#title'], 'maintenance', $regions + array('#show_messages' => !$progress_page)); } }
if (is_array($results['tasks'])) { $links += $results['tasks']; } else { $links = array_merge($links, array(\Drupal::l(t('Administration pages'), new Url('system.admin')), \Drupal::l(t('Front page'), new Url('<front>')))); } $item_list = array('#theme' => 'item_list', '#items' => $links, '#title' => t('Next steps')); $output .= drupal_render_root($item_list); } elseif ($request->query->has('batch')) { $output = _batch_page($request); } else { if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_info'])) { $output = t('It appears you have reached this page in error.'); } elseif (!($batch = batch_get())) { // We have a batch to process, show the filetransfer form. $elements = \Drupal::formBuilder()->getForm('Drupal\\Core\\FileTransfer\\Form\\FileTransferAuthorizeForm'); $output = drupal_render_root($elements); } } // We defer the display of messages until all operations are done. $show_messages = !(($batch = batch_get()) && isset($batch['running'])); } else { $response->setStatusCode(403); \Drupal::logger('access denied')->warning('authorize.php'); $page_title = t('Access denied'); $output = t('You are not allowed to access this page.'); } if (!empty($output)) { $response->headers->set('Content-Type', 'text/html; charset=utf-8'); $response->setContent(DefaultHtmlPageRenderer::renderPage($output, $page_title, 'maintenance', array('#show_messages' => $show_messages))); $response->send(); }
/** * Handles any exception as a generic error page for HTML. * * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event * The event to process. */ protected function onHtml(GetResponseForExceptionEvent $event) { $exception = $event->getException(); $error = Error::decodeException($exception); $flatten_exception = FlattenException::create($exception, 500); // Display the message if the current error reporting level allows this type // of message to be displayed, and unconditionally in update.php. if (error_displayable($error)) { $class = 'error'; // If error type is 'User notice' then treat it as debug information // instead of an error message. // @see debug() if ($error['%type'] == 'User notice') { $error['%type'] = 'Debug'; $class = 'status'; } // Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path // in the message. This does not happen for (false) security. $root_length = strlen(DRUPAL_ROOT); if (substr($error['%file'], 0, $root_length) == DRUPAL_ROOT) { $error['%file'] = substr($error['%file'], $root_length + 1); } // Do not translate the string to avoid errors producing more errors. unset($error['backtrace']); $message = String::format('%type: !message in %function (line %line of %file).', $error); // Check if verbose error reporting is on. if ($this->getErrorLevel() == ERROR_REPORTING_DISPLAY_VERBOSE) { $backtrace_exception = $flatten_exception; while ($backtrace_exception->getPrevious()) { $backtrace_exception = $backtrace_exception->getPrevious(); } $backtrace = $backtrace_exception->getTrace(); // First trace is the error itself, already contained in the message. // While the second trace is the error source and also contained in the // message, the message doesn't contain argument values, so we output it // once more in the backtrace. array_shift($backtrace); // Generate a backtrace containing only scalar argument values. $message .= '<pre class="backtrace">' . Error::formatFlattenedBacktrace($backtrace) . '</pre>'; } drupal_set_message(SafeMarkup::set($message), $class, TRUE); } $content = $this->t('The website has encountered an error. Please try again later.'); $output = DefaultHtmlPageRenderer::renderPage($content, $this->t('Error')); $response = new Response($output); if ($exception instanceof HttpExceptionInterface) { $response->setStatusCode($exception->getStatusCode()); } else { $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR, '500 Service unavailable (with message)'); } $event->setResponse($response); }
$links = array(); if (is_array($results['tasks'])) { $links += $results['tasks']; } else { $links = array_merge($links, array(l(t('Administration pages'), 'admin'), l(t('Front page'), '<front>'))); } $item_list = array('#theme' => 'item_list', '#items' => $links, '#title' => t('Next steps')); $output .= drupal_render($item_list); } elseif ($request->query->has('batch')) { $output = _batch_page($request); } else { if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_info'])) { $output = t('It appears you have reached this page in error.'); } elseif (!($batch = batch_get())) { // We have a batch to process, show the filetransfer form. $elements = \Drupal::formBuilder()->getForm('Drupal\\Core\\FileTransfer\\Form\\FileTransferAuthorizeForm'); $output = drupal_render($elements); } } // We defer the display of messages until all operations are done. $show_messages = !(($batch = batch_get()) && isset($batch['running'])); } else { drupal_add_http_header('Status', '403 Forbidden'); \Drupal::logger('access denied')->warning('authorize.php'); $page_title = t('Access denied'); $output = t('You are not allowed to access this page.'); } if (!empty($output)) { drupal_add_http_header('Content-Type', 'text/html; charset=utf-8'); print DefaultHtmlPageRenderer::renderPage($output, $page_title, 'maintenance', array('#show_messages' => $show_messages)); }
/** * Prevents page redirection so that the developer can see the intermediate debug data. * @param FilterResponseEvent $event */ public function onResponse(FilterResponseEvent $event) { $response = $event->getResponse(); if ($response instanceof RedirectResponse && !devel_silent()) { if ($this->account->hasPermission('access devel information') && $this->config->get('redirect_page')) { $output = t_safe('<p>The user is being redirected to <a href="@destination">@destination</a>.</p>', array('@destination' => $response->getTargetUrl())); // Replace RedirectResponse with a fresh Response that includes our content. // We pass array() as last param in order to avoid adding regions which would add queries, etc. $response = new Response(DefaultHtmlPageRenderer::renderPage($output, 'Devel Redirect', '', array()), 200); $event->setResponse($response); } else { $GLOBALS['devel_redirecting'] = TRUE; } } }
/** * Returns the site maintenance page if the site is offline. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The event to process. */ public function onKernelRequestMaintenance(GetResponseEvent $event) { $route_match = RouteMatch::createFromRequest($event->getRequest()); if ($this->maintenanceMode->applies($route_match)) { if (!$this->maintenanceMode->exempt($this->account)) { // Deliver the 503 page if the site is in maintenance mode and the // logged in user is not allowed to bypass it. drupal_maintenance_theme(); $content = Xss::filterAdmin(String::format($this->config->get('system.maintenance')->get('message'), array('@site' => $this->config->get('system.site')->get('name')))); // @todo Break the dependency on DefaultHtmlPageRenderer, see: // https://www.drupal.org/node/2295609 $content = DefaultHtmlPageRenderer::renderPage($content, $this->t('Site under maintenance')); $response = new Response('Service unavailable', 503); $response->setContent($content); $event->setResponse($response); } else { // Display a message if the logged in user has access to the site in // maintenance mode. However, suppress it on the maintenance mode // settings page. if ($route_match->getRouteName() != 'system.site_maintenance_mode') { if ($this->account->hasPermission('administer site configuration')) { $this->drupalSetMessage($this->t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => $this->urlGenerator->generate('system.site_maintenance_mode'))), 'status', FALSE); } else { $this->drupalSetMessage($this->t('Operating in maintenance mode.'), 'status', FALSE); } } } } }
/** * Returns a database update page. * * @param string $op * The update operation to perform. Can be any of the below: * - info * - selection * - run * - results * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Symfony\Component\HttpFoundation\Response * A response object object. */ public function handle($op, Request $request) { require_once DRUPAL_ROOT . '/core/includes/install.inc'; require_once DRUPAL_ROOT . '/core/includes/update.inc'; drupal_load_updates(); update_fix_compatibility(); if ($request->query->get('continue')) { $_SESSION['update_ignore_warnings'] = TRUE; } $regions = array(); $requirements = update_check_requirements(); $severity = drupal_requirements_severity($requirements); if ($severity == REQUIREMENT_ERROR || $severity == REQUIREMENT_WARNING && empty($_SESSION['update_ignore_warnings'])) { $regions['sidebar_first'] = $this->updateTasksList('requirements'); $output = $this->requirements($severity, $requirements); } else { switch ($op) { case 'selection': $regions['sidebar_first'] = $this->updateTasksList('selection'); $output = $this->selection(); break; case 'run': $regions['sidebar_first'] = $this->updateTasksList('run'); $output = $this->triggerBatch($request); break; case 'info': $regions['sidebar_first'] = $this->updateTasksList('info'); $output = $this->info(); break; case 'results': $regions['sidebar_first'] = $this->updateTasksList('results'); $output = $this->results(); break; // Regular batch ops : defer to batch processing API. // Regular batch ops : defer to batch processing API. default: require_once DRUPAL_ROOT . '/core/includes/batch.inc'; $regions['sidebar_first'] = $this->updateTasksList('run'); $output = _batch_page($request); break; } } if ($output instanceof Response) { return $output; } $title = isset($output['#title']) ? $output['#title'] : $this->t('Drupal database update'); return new Response(DefaultHtmlPageRenderer::renderPage($output, $title, 'maintenance', $regions)); }