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