Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

ExceptionHandler.php

Zuletzt modifiziert: 09.10.2024, 12:54 - Dateigröße: 18.81 KiB


 001  <?php
 002   
 003  /*
 004   * This file is part of the Symfony package.
 005   *
 006   * (c) Fabien Potencier <fabien@symfony.com>
 007   *
 008   * For the full copyright and license information, please view the LICENSE
 009   * file that was distributed with this source code.
 010   */
 011   
 012  namespace Symfony\Component\Debug;
 013   
 014  use Symfony\Component\HttpFoundation\Response;
 015  use Symfony\Component\Debug\Exception\FlattenException;
 016  use Symfony\Component\Debug\Exception\OutOfMemoryException;
 017   
 018  /**
 019   * ExceptionHandler converts an exception to a Response object.
 020   *
 021   * It is mostly useful in debug mode to replace the default PHP/XDebug
 022   * output with something prettier and more useful.
 023   *
 024   * As this class is mainly used during Kernel boot, where nothing is yet
 025   * available, the Response content is always HTML.
 026   *
 027   * @author Fabien Potencier <fabien@symfony.com>
 028   * @author Nicolas Grekas <p@tchwork.com>
 029   */
 030  class ExceptionHandler
 031  {
 032      private $debug;
 033      private $charset;
 034      private $handler;
 035      private $caughtBuffer;
 036      private $caughtLength;
 037      private $fileLinkFormat;
 038   
 039      public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
 040      {
 041          if (false !== strpos($charset, '%')) {
 042              @trigger_error('Providing $fileLinkFormat as second argument to '.__METHOD__.' is deprecated since version 2.8 and will be unsupported in 3.0. Please provide it as third argument, after $charset.', E_USER_DEPRECATED);
 043   
 044              // Swap $charset and $fileLinkFormat for BC reasons
 045              $pivot = $fileLinkFormat;
 046              $fileLinkFormat = $charset;
 047              $charset = $pivot;
 048          }
 049          $this->debug = $debug;
 050          $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
 051          $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
 052      }
 053   
 054      /**
 055       * Registers the exception handler.
 056       *
 057       * @param bool        $debug          Enable/disable debug mode, where the stack trace is displayed
 058       * @param string|null $charset        The charset used by exception messages
 059       * @param string|null $fileLinkFormat The IDE link template
 060       *
 061       * @return ExceptionHandler The registered exception handler
 062       */
 063      public static function register($debug = true, $charset = null, $fileLinkFormat = null)
 064      {
 065          $handler = new static($debug, $charset, $fileLinkFormat);
 066   
 067          $prev = set_exception_handler(array($handler, 'handle'));
 068          if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
 069              restore_exception_handler();
 070              $prev[0]->setExceptionHandler(array($handler, 'handle'));
 071          }
 072   
 073          return $handler;
 074      }
 075   
 076      /**
 077       * Sets a user exception handler.
 078       *
 079       * @param callable $handler An handler that will be called on Exception
 080       *
 081       * @return callable|null The previous exception handler if any
 082       */
 083      public function setHandler($handler)
 084      {
 085          if (null !== $handler && !is_callable($handler)) {
 086              throw new \LogicException('The exception handler must be a valid PHP callable.');
 087          }
 088          $old = $this->handler;
 089          $this->handler = $handler;
 090   
 091          return $old;
 092      }
 093   
 094      /**
 095       * Sets the format for links to source files.
 096       *
 097       * @param string $format The format for links to source files
 098       *
 099       * @return string The previous file link format
 100       */
 101      public function setFileLinkFormat($format)
 102      {
 103          $old = $this->fileLinkFormat;
 104          $this->fileLinkFormat = $format;
 105   
 106          return $old;
 107      }
 108   
 109      /**
 110       * Sends a response for the given Exception.
 111       *
 112       * To be as fail-safe as possible, the exception is first handled
 113       * by our simple exception handler, then by the user exception handler.
 114       * The latter takes precedence and any output from the former is cancelled,
 115       * if and only if nothing bad happens in this handling path.
 116       */
 117      public function handle(\Exception $exception)
 118      {
 119          if (null === $this->handler || $exception instanceof OutOfMemoryException) {
 120              $this->failSafeHandle($exception);
 121   
 122              return;
 123          }
 124   
 125          $caughtLength = $this->caughtLength = 0;
 126   
 127          ob_start(array($this, 'catchOutput'));
 128          $this->failSafeHandle($exception);
 129          while (null === $this->caughtBuffer && ob_end_flush()) {
 130              // Empty loop, everything is in the condition
 131          }
 132          if (isset($this->caughtBuffer[0])) {
 133              ob_start(array($this, 'cleanOutput'));
 134              echo $this->caughtBuffer;
 135              $caughtLength = ob_get_length();
 136          }
 137          $this->caughtBuffer = null;
 138   
 139          try {
 140              call_user_func($this->handler, $exception);
 141              $this->caughtLength = $caughtLength;
 142          } catch (\Exception $e) {
 143              if (!$caughtLength) {
 144                  // All handlers failed. Let PHP handle that now.
 145                  throw $exception;
 146              }
 147          }
 148      }
 149   
 150      /**
 151       * Sends a response for the given Exception.
 152       *
 153       * If you have the Symfony HttpFoundation component installed,
 154       * this method will use it to create and send the response. If not,
 155       * it will fallback to plain PHP functions.
 156       *
 157       * @param \Exception $exception An \Exception instance
 158       */
 159      private function failSafeHandle(\Exception $exception)
 160      {
 161          if (class_exists('Symfony\Component\HttpFoundation\Response', false)
 162              && __CLASS__ !== get_class($this)
 163              && ($reflector = new \ReflectionMethod($this, 'createResponse'))
 164              && __CLASS__ !== $reflector->class
 165          ) {
 166              $response = $this->createResponse($exception);
 167              $response->sendHeaders();
 168              $response->sendContent();
 169              @trigger_error(sprintf("The %s::createResponse method is deprecated since 2.8 and won't be called anymore when handling an exception in 3.0.", $reflector->class), E_USER_DEPRECATED);
 170   
 171              return;
 172          }
 173   
 174          $this->sendPhpResponse($exception);
 175      }
 176   
 177      /**
 178       * Sends the error associated with the given Exception as a plain PHP response.
 179       *
 180       * This method uses plain PHP functions like header() and echo to output
 181       * the response.
 182       *
 183       * @param \Exception|FlattenException $exception An \Exception or FlattenException instance
 184       */
 185      public function sendPhpResponse($exception)
 186      {
 187          if (!$exception instanceof FlattenException) {
 188              $exception = FlattenException::create($exception);
 189          }
 190   
 191          if (!headers_sent()) {
 192              header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
 193              foreach ($exception->getHeaders() as $name => $value) {
 194                  header($name.': '.$value, false);
 195              }
 196              header('Content-Type: text/html; charset='.$this->charset);
 197          }
 198   
 199          echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
 200      }
 201   
 202      /**
 203       * Creates the error Response associated with the given Exception.
 204       *
 205       * @param \Exception|FlattenException $exception An \Exception or FlattenException instance
 206       *
 207       * @return Response A Response instance
 208       *
 209       * @deprecated since 2.8, to be removed in 3.0.
 210       */
 211      public function createResponse($exception)
 212      {
 213          @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
 214   
 215          if (!$exception instanceof FlattenException) {
 216              $exception = FlattenException::create($exception);
 217          }
 218   
 219          return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
 220      }
 221   
 222      /**
 223       * Gets the full HTML content associated with the given exception.
 224       *
 225       * @param \Exception|FlattenException $exception An \Exception or FlattenException instance
 226       *
 227       * @return string The HTML content as a string
 228       */
 229      public function getHtml($exception)
 230      {
 231          if (!$exception instanceof FlattenException) {
 232              $exception = FlattenException::create($exception);
 233          }
 234   
 235          return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
 236      }
 237   
 238      /**
 239       * Gets the HTML content associated with the given exception.
 240       *
 241       * @param FlattenException $exception A FlattenException instance
 242       *
 243       * @return string The content as a string
 244       */
 245      public function getContent(FlattenException $exception)
 246      {
 247          switch ($exception->getStatusCode()) {
 248              case 404:
 249                  $title = 'Sorry, the page you are looking for could not be found.';
 250                  break;
 251              default:
 252                  $title = 'Whoops, looks like something went wrong.';
 253          }
 254   
 255          $content = '';
 256          if ($this->debug) {
 257              try {
 258                  $count = count($exception->getAllPrevious());
 259                  $total = $count + 1;
 260                  foreach ($exception->toArray() as $position => $e) {
 261                      $ind = $count - $position + 1;
 262                      $class = $this->formatClass($e['class']);
 263                      $message = nl2br($this->escapeHtml($e['message']));
 264                      $content .= sprintf(<<<'EOF'
 265                          <h2 class="block_exception clear_fix">
 266                              <span class="exception_counter">%d/%d</span>
 267                              <span class="exception_title">%s%s:</span>
 268                              <span class="exception_message">%s</span>
 269                          </h2>
 270                          <div class="block">
 271                              <ol class="traces list_exception">
 272   
 273  EOF
 274                          , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
 275                      foreach ($e['trace'] as $trace) {
 276                          $content .= '       <li>';
 277                          if ($trace['function']) {
 278                              $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
 279                          }
 280                          if (isset($trace['file']) && isset($trace['line'])) {
 281                              $content .= $this->formatPath($trace['file'], $trace['line']);
 282                          }
 283                          $content .= "</li>\n";
 284                      }
 285   
 286                      $content .= "    </ol>\n</div>\n";
 287                  }
 288              } catch (\Exception $e) {
 289                  // something nasty happened and we cannot throw an exception anymore
 290                  if ($this->debug) {
 291                      $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
 292                  } else {
 293                      $title = 'Whoops, looks like something went wrong.';
 294                  }
 295              }
 296          }
 297   
 298          return <<<EOF
 299              <div id="sf-resetcontent" class="sf-reset">
 300                  <h1>$title</h1>
 301                  $content
 302              </div>
 303  EOF;
 304   
 305      }
 306   
 307      /**
 308       * Gets the stylesheet associated with the given exception.
 309       *
 310       * @param FlattenException $exception A FlattenException instance
 311       *
 312       * @return string The stylesheet as a string
 313       */
 314      public function getStylesheet(FlattenException $exception)
 315      {
 316          return <<<'EOF'
 317              .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
 318              .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
 319              .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
 320              .sf-reset .clear_fix { display:inline-block; }
 321              .sf-reset * html .clear_fix { height:1%; }
 322              .sf-reset .clear_fix { display:block; }
 323              .sf-reset, .sf-reset .block { margin: auto }
 324              .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
 325              .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
 326              .sf-reset strong { font-weight:bold; }
 327              .sf-reset a { color:#6c6159; cursor: default; }
 328              .sf-reset a img { border:none; }
 329              .sf-reset a:hover { text-decoration:underline; }
 330              .sf-reset em { font-style:italic; }
 331              .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
 332              .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
 333              .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
 334              .sf-reset .exception_message { margin-left: 3em; display: block; }
 335              .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
 336              .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
 337                  -webkit-border-bottom-right-radius: 16px;
 338                  -webkit-border-bottom-left-radius: 16px;
 339                  -moz-border-radius-bottomright: 16px;
 340                  -moz-border-radius-bottomleft: 16px;
 341                  border-bottom-right-radius: 16px;
 342                  border-bottom-left-radius: 16px;
 343                  border-bottom:1px solid #ccc;
 344                  border-right:1px solid #ccc;
 345                  border-left:1px solid #ccc;
 346                  word-wrap: break-word;
 347              }
 348              .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
 349                  -webkit-border-top-left-radius: 16px;
 350                  -webkit-border-top-right-radius: 16px;
 351                  -moz-border-radius-topleft: 16px;
 352                  -moz-border-radius-topright: 16px;
 353                  border-top-left-radius: 16px;
 354                  border-top-right-radius: 16px;
 355                  border-top:1px solid #ccc;
 356                  border-right:1px solid #ccc;
 357                  border-left:1px solid #ccc;
 358                  overflow: hidden;
 359                  word-wrap: break-word;
 360              }
 361              .sf-reset a { background:none; color:#868686; text-decoration:none; }
 362              .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
 363              .sf-reset ol { padding: 10px 0; }
 364              .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
 365                  -webkit-border-radius: 10px;
 366                  -moz-border-radius: 10px;
 367                  border-radius: 10px;
 368                  border: 1px solid #ccc;
 369              }
 370  EOF;
 371   
 372      }
 373   
 374      private function decorate($content, $css)
 375      {
 376          return <<<EOF
 377  <!DOCTYPE html>
 378  <html>
 379      <head>
 380          <meta charset="{$this->charset}" />
 381          <meta name="robots" content="noindex,nofollow" />
 382          <style>
 383              /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
 384              html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
 385   
 386              html { background: #eee; padding: 10px }
 387              img { border: 0; }
 388              #sf-resetcontent { width:970px; margin:0 auto; }
 389              $css
 390          </style>
 391      </head>
 392      <body>
 393          $content
 394      </body>
 395  </html>
 396  EOF;
 397   
 398      }
 399   
 400      private function formatClass($class)
 401      {
 402          $parts = explode('\\', $class);
 403   
 404          return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
 405      }
 406   
 407      private function formatPath($path, $line)
 408      {
 409          $path = $this->escapeHtml($path);
 410          $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
 411   
 412          if ($linkFormat = $this->fileLinkFormat) {
 413              $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
 414   
 415              return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
 416          }
 417   
 418          return sprintf(' in <a title="%s line %3$d" ondblclick="var f=this.innerHTML;this.innerHTML=this.title;this.title=f;">%s line %d</a>', $path, $file, $line);
 419      }
 420   
 421      /**
 422       * Formats an array as a string.
 423       *
 424       * @param array $args The argument array
 425       *
 426       * @return string
 427       */
 428      private function formatArgs(array $args)
 429      {
 430          $result = array();
 431          foreach ($args as $key => $item) {
 432              if ('object' === $item[0]) {
 433                  $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
 434              } elseif ('array' === $item[0]) {
 435                  $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
 436              } elseif ('string' === $item[0]) {
 437                  $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
 438              } elseif ('null' === $item[0]) {
 439                  $formattedValue = '<em>null</em>';
 440              } elseif ('boolean' === $item[0]) {
 441                  $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
 442              } elseif ('resource' === $item[0]) {
 443                  $formattedValue = '<em>resource</em>';
 444              } else {
 445                  $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
 446              }
 447   
 448              $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
 449          }
 450   
 451          return implode(', ', $result);
 452      }
 453   
 454      /**
 455       * Returns an UTF-8 and HTML encoded string.
 456       *
 457       * @deprecated since version 2.7, to be removed in 3.0.
 458       */
 459      protected static function utf8Htmlize($str)
 460      {
 461          @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
 462   
 463          return htmlspecialchars($str, ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
 464      }
 465   
 466      /**
 467       * HTML-encodes a string.
 468       */
 469      private function escapeHtml($str)
 470      {
 471          return htmlspecialchars($str, ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
 472      }
 473   
 474      /**
 475       * @internal
 476       */
 477      public function catchOutput($buffer)
 478      {
 479          $this->caughtBuffer = $buffer;
 480   
 481          return '';
 482      }
 483   
 484      /**
 485       * @internal
 486       */
 487      public function cleanOutput($buffer)
 488      {
 489          if ($this->caughtLength) {
 490              // use substr_replace() instead of substr() for mbstring overloading resistance
 491              $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
 492              if (isset($cleanBuffer[0])) {
 493                  $buffer = $cleanBuffer;
 494              }
 495          }
 496   
 497          return $buffer;
 498      }
 499  }
 500