示例#1
0
 /**
  * Renders an exception error message without further exceptions.
  *
  * @param \Exception|\Throwable $exception
  *   The exception object that was thrown.
  *
  * @return string
  *   An error message.
  */
 public static function renderExceptionSafe($exception)
 {
     $decode = static::decodeException($exception);
     $backtrace = $decode['backtrace'];
     unset($decode['backtrace']);
     // Remove 'main()'.
     array_shift($backtrace);
     // Even though it is possible that this method is called on a public-facing
     // site, it is only called when the exception handler itself threw an
     // exception, which normally means that a code change caused the system to
     // no longer function correctly (as opposed to a user-triggered error), so
     // we assume that it is safe to include a verbose backtrace.
     $decode['@backtrace'] = Error::formatBacktrace($backtrace);
     return SafeMarkup::format('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $decode);
 }
 /**
  * {@inheritdoc}
  *
  * HTTP middleware that replaces the user agent for simpletest requests.
  */
 public function __invoke()
 {
     // If the database prefix is being used by SimpleTest to run the tests in a copied
     // database then set the user-agent header to the database prefix so that any
     // calls to other Drupal pages will run the SimpleTest prefixed database. The
     // user-agent is used to ensure that multiple testing sessions running at the
     // same time won't interfere with each other as they would if the database
     // prefix were stored statically in a file or database variable.
     return function ($handler) {
         return function (RequestInterface $request, array $options) use($handler) {
             if ($test_prefix = drupal_valid_test_ua()) {
                 $request = $request->withHeader('User-Agent', drupal_generate_test_ua($test_prefix));
             }
             return $handler($request, $options)->then(function (ResponseInterface $response) use($request) {
                 if (!drupal_valid_test_ua()) {
                     return $response;
                 }
                 $headers = $response->getHeaders();
                 foreach ($headers as $header_name => $header_values) {
                     if (preg_match('/^X-Drupal-Assertion-[0-9]+$/', $header_name, $matches)) {
                         foreach ($header_values as $header_value) {
                             // Call \Drupal\simpletest\WebTestBase::error() with the parameters from
                             // the header.
                             $parameters = unserialize(urldecode($header_value));
                             if (count($parameters) === 3) {
                                 throw new \Exception($parameters[1] . ': ' . $parameters[0] . "\n" . Error::formatBacktrace([$parameters[2]]));
                             } else {
                                 throw new \Exception('Error thrown with the wrong amount of parameters.');
                             }
                         }
                     }
                 }
                 return $response;
             });
         };
     };
 }
 /**
  * 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);
     // 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 = SafeMarkup::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 = $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. Make
             // sure the backtrace is escaped as it can contain user submitted data.
             $message .= '<pre class="backtrace">' . SafeMarkup::escape(Error::formatBacktrace($backtrace)) . '</pre>';
         }
         drupal_set_message(SafeMarkup::set($message), $class, TRUE);
     }
     $content = $this->t('The website encountered an unexpected error. Please try again later.');
     $response = $this->bareHtmlPageRenderer->renderBarePage(['#markup' => $content], $this->t('Error'), 'maintenance_page');
     if ($exception instanceof HttpExceptionInterface) {
         $response->setStatusCode($exception->getStatusCode());
         $response->headers->add($exception->getHeaders());
     } else {
         $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR, '500 Service unavailable (with message)');
     }
     $event->setResponse($response);
 }
示例#4
0
 /**
  * Handle exceptions.
  *
  * @see set_exception_handler
  */
 protected function exceptionHandler($exception)
 {
     $backtrace = $exception->getTrace();
     $verbose_backtrace = $backtrace;
     // Push on top of the backtrace the call that generated the exception.
     array_unshift($backtrace, array('line' => $exception->getLine(), 'file' => $exception->getFile()));
     $decoded_exception = Error::decodeException($exception);
     unset($decoded_exception['backtrace']);
     $message = SafeMarkup::format('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $decoded_exception + array('@backtrace' => Error::formatBacktrace($verbose_backtrace)));
     $this->error($message, 'Uncaught exception', Error::getLastCaller($backtrace));
 }
示例#5
0
 /**
  * Tests the formatBacktrace() method.
  *
  * @param array $backtrace
  *   The test backtrace array.
  * @param array $expected
  *   The expected return array.
  *
  * @dataProvider providerTestFormatBacktrace
  */
 public function testFormatBacktrace($backtrace, $expected)
 {
     $this->assertSame($expected, Error::formatBacktrace($backtrace));
 }
 /**
  * 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);
     // Display the message if the current error reporting level allows this type
     // of message to be displayed, and unconditionally in update.php.
     $message = '';
     if (error_displayable($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';
         }
         // 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);
         }
         unset($error['backtrace']);
         if ($this->getErrorLevel() != ERROR_REPORTING_DISPLAY_VERBOSE) {
             // Without verbose logging, use a simple message.
             // We call SafeMarkup::format directly here, rather than use t() since
             // we are in the middle of error handling, and we don't want t() to
             // cause further errors.
             $message = SafeMarkup::format('%type: @message in %function (line %line of %file).', $error);
         } else {
             // With verbose logging, we will also include a backtrace.
             $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.
             $error['@backtrace'] = Error::formatBacktrace($backtrace);
             $message = SafeMarkup::format('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $error);
         }
     }
     $content = $this->t('The website encountered an unexpected error. Please try again later.');
     $content .= $message ? '</br></br>' . $message : '';
     $response = new Response($content, 500);
     if ($exception instanceof HttpExceptionInterface) {
         $response->setStatusCode($exception->getStatusCode());
         $response->headers->add($exception->getHeaders());
     } else {
         $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR, '500 Service unavailable (with message)');
     }
     $event->setResponse($response);
 }
示例#7
0
 /**
  * Handle exceptions.
  *
  * @see set_exception_handler
  */
 protected function exceptionHandler($exception)
 {
     require_once DRUPAL_ROOT . '/core/includes/errors.inc';
     $backtrace = $exception->getTrace();
     $verbose_backtrace = $backtrace;
     // Push on top of the backtrace the call that generated the exception.
     array_unshift($backtrace, array('line' => $exception->getLine(), 'file' => $exception->getFile()));
     // \Drupal\Core\Utility\Error::decodeException() runs the exception
     // message through \Drupal\Component\Utility\String::checkPlain().
     $decoded_exception = Error::decodeException($exception);
     unset($decoded_exception['backtrace']);
     $message = String::format('%type: !message in %function (line %line of %file). <pre class="backtrace">!backtrace</pre>', $decoded_exception + array('!backtrace' => Error::formatBacktrace($verbose_backtrace)));
     $this->error($message, 'Uncaught exception', Error::getLastCaller($backtrace));
 }