[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/http-foundation/ -> JsonResponse.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\HttpFoundation;
  13  
  14  /**
  15   * Response represents an HTTP response in JSON format.
  16   *
  17   * Note that this class does not force the returned JSON content to be an
  18   * object. It is however recommended that you do return an object as it
  19   * protects yourself against XSSI and JSON-JavaScript Hijacking.
  20   *
  21   * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside
  22   *
  23   * @author Igor Wiedler <igor@wiedler.ch>
  24   */
  25  class JsonResponse extends Response
  26  {
  27      protected $data;
  28      protected $callback;
  29  
  30      // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML.
  31      // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT
  32      protected $encodingOptions = 15;
  33  
  34      /**
  35       * @param mixed $data    The response data
  36       * @param int   $status  The response status code
  37       * @param array $headers An array of response headers
  38       */
  39      public function __construct($data = null, $status = 200, $headers = array())
  40      {
  41          parent::__construct('', $status, $headers);
  42  
  43          if (null === $data) {
  44              $data = new \ArrayObject();
  45          }
  46  
  47          $this->setData($data);
  48      }
  49  
  50      /**
  51       * Factory method for chainability.
  52       *
  53       * Example:
  54       *
  55       *     return JsonResponse::create($data, 200)
  56       *         ->setSharedMaxAge(300);
  57       *
  58       * @param mixed $data    The json response data
  59       * @param int   $status  The response status code
  60       * @param array $headers An array of response headers
  61       *
  62       * @return static
  63       */
  64      public static function create($data = null, $status = 200, $headers = array())
  65      {
  66          return new static($data, $status, $headers);
  67      }
  68  
  69      /**
  70       * Sets the JSONP callback.
  71       *
  72       * @param string|null $callback The JSONP callback or null to use none
  73       *
  74       * @return $this
  75       *
  76       * @throws \InvalidArgumentException When the callback name is not valid
  77       */
  78      public function setCallback($callback = null)
  79      {
  80          if (null !== $callback) {
  81              // partially token from http://www.geekality.net/2011/08/03/valid-javascript-identifier/
  82              // partially token from https://github.com/willdurand/JsonpCallbackValidator
  83              //      JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details.
  84              //      (c) William Durand <william.durand1@gmail.com>
  85              $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u';
  86              $reserved = array(
  87                  'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while',
  88                  'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super',  'const', 'export',
  89                  'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false',
  90              );
  91              $parts = explode('.', $callback);
  92              foreach ($parts as $part) {
  93                  if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) {
  94                      throw new \InvalidArgumentException('The callback name is not valid.');
  95                  }
  96              }
  97          }
  98  
  99          $this->callback = $callback;
 100  
 101          return $this->update();
 102      }
 103  
 104      /**
 105       * Sets the data to be sent as JSON.
 106       *
 107       * @param mixed $data
 108       *
 109       * @return $this
 110       *
 111       * @throws \InvalidArgumentException
 112       */
 113      public function setData($data = array())
 114      {
 115          if (\defined('HHVM_VERSION')) {
 116              // HHVM does not trigger any warnings and let exceptions
 117              // thrown from a JsonSerializable object pass through.
 118              // If only PHP did the same...
 119              $data = json_encode($data, $this->encodingOptions);
 120          } else {
 121              try {
 122                  if (!interface_exists('JsonSerializable', false)) {
 123                      // PHP 5.3 triggers annoying warnings for some
 124                      // types that can't be serialized as JSON (INF, resources, etc.)
 125                      // but doesn't provide the JsonSerializable interface.
 126                      set_error_handler(function () { return false; });
 127                      $data = @json_encode($data, $this->encodingOptions);
 128                      restore_error_handler();
 129                  } elseif (\PHP_VERSION_ID < 50500) {
 130                      // PHP 5.4 and up wrap exceptions thrown by JsonSerializable
 131                      // objects in a new exception that needs to be removed.
 132                      // Fortunately, PHP 5.5 and up do not trigger any warning anymore.
 133                      // Clear json_last_error()
 134                      json_encode(null);
 135                      $errorHandler = set_error_handler('var_dump');
 136                      restore_error_handler();
 137                      set_error_handler(function () use ($errorHandler) {
 138                          if (JSON_ERROR_NONE === json_last_error()) {
 139                              return $errorHandler && false !== \call_user_func_array($errorHandler, \func_get_args());
 140                          }
 141                      });
 142                      $data = json_encode($data, $this->encodingOptions);
 143                      restore_error_handler();
 144                  } else {
 145                      $data = json_encode($data, $this->encodingOptions);
 146                  }
 147              } catch (\Error $e) {
 148                  if (\PHP_VERSION_ID < 50500 || !interface_exists('JsonSerializable', false)) {
 149                      restore_error_handler();
 150                  }
 151                  throw $e;
 152              } catch (\Exception $e) {
 153                  if (\PHP_VERSION_ID < 50500 || !interface_exists('JsonSerializable', false)) {
 154                      restore_error_handler();
 155                  }
 156                  if (interface_exists('JsonSerializable', false) && 'Exception' === \get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
 157                      throw $e->getPrevious() ?: $e;
 158                  }
 159                  throw $e;
 160              }
 161          }
 162  
 163          if (JSON_ERROR_NONE !== json_last_error()) {
 164              throw new \InvalidArgumentException(json_last_error_msg());
 165          }
 166  
 167          $this->data = $data;
 168  
 169          return $this->update();
 170      }
 171  
 172      /**
 173       * Returns options used while encoding data to JSON.
 174       *
 175       * @return int
 176       */
 177      public function getEncodingOptions()
 178      {
 179          return $this->encodingOptions;
 180      }
 181  
 182      /**
 183       * Sets options used while encoding data to JSON.
 184       *
 185       * @param int $encodingOptions
 186       *
 187       * @return $this
 188       */
 189      public function setEncodingOptions($encodingOptions)
 190      {
 191          $this->encodingOptions = (int) $encodingOptions;
 192  
 193          return $this->setData(json_decode($this->data));
 194      }
 195  
 196      /**
 197       * Updates the content and headers according to the JSON data and callback.
 198       *
 199       * @return $this
 200       */
 201      protected function update()
 202      {
 203          if (null !== $this->callback) {
 204              // Not using application/javascript for compatibility reasons with older browsers.
 205              $this->headers->set('Content-Type', 'text/javascript');
 206  
 207              return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data));
 208          }
 209  
 210          // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback)
 211          // in order to not overwrite a custom definition.
 212          if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) {
 213              $this->headers->set('Content-Type', 'application/json');
 214          }
 215  
 216          return $this->setContent($this->data);
 217      }
 218  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1