[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/ -> 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 " for RFC4627-compliant JSON, which may also be embedded into HTML.
  31      // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT
  32      private $encodingOptions = 15;
  33  
  34      /**
  35       * Constructor.
  36       *
  37       * @param mixed $data    The response data
  38       * @param int   $status  The response status code
  39       * @param array $headers An array of response headers
  40       */
  41      public function __construct($data = null, $status = 200, $headers = array())
  42      {
  43          parent::__construct('', $status, $headers);
  44  
  45          if (null === $data) {
  46              $data = new \ArrayObject();
  47          }
  48  
  49          $this->setData($data);
  50      }
  51  
  52      /**
  53       * {@inheritdoc}
  54       */
  55      public static function create($data = null, $status = 200, $headers = array())
  56      {
  57          return new static($data, $status, $headers);
  58      }
  59  
  60      /**
  61       * Sets the JSONP callback.
  62       *
  63       * @param string|null $callback The JSONP callback or null to use none
  64       *
  65       * @return JsonResponse
  66       *
  67       * @throws \InvalidArgumentException When the callback name is not valid
  68       */
  69      public function setCallback($callback = null)
  70      {
  71          if (null !== $callback) {
  72              // taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/
  73              $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u';
  74              $parts = explode('.', $callback);
  75              foreach ($parts as $part) {
  76                  if (!preg_match($pattern, $part)) {
  77                      throw new \InvalidArgumentException('The callback name is not valid.');
  78                  }
  79              }
  80          }
  81  
  82          $this->callback = $callback;
  83  
  84          return $this->update();
  85      }
  86  
  87      /**
  88       * Sets the data to be sent as JSON.
  89       *
  90       * @param mixed $data
  91       *
  92       * @return JsonResponse
  93       *
  94       * @throws \InvalidArgumentException
  95       */
  96      public function setData($data = array())
  97      {
  98          if (defined('HHVM_VERSION')) {
  99              // HHVM does not trigger any warnings and let exceptions
 100              // thrown from a JsonSerializable object pass through.
 101              // If only PHP did the same...
 102              $data = json_encode($data, $this->encodingOptions);
 103          } else {
 104              try {
 105                  if (PHP_VERSION_ID < 50400) {
 106                      // PHP 5.3 triggers annoying warnings for some
 107                      // types that can't be serialized as JSON (INF, resources, etc.)
 108                      // but doesn't provide the JsonSerializable interface.
 109                      set_error_handler(function () { return false; });
 110                      $data = @json_encode($data, $this->encodingOptions);
 111                  } else {
 112                      // PHP 5.4 and up wrap exceptions thrown by JsonSerializable
 113                      // objects in a new exception that needs to be removed.
 114                      // Fortunately, PHP 5.5 and up do not trigger any warning anymore.
 115                      if (PHP_VERSION_ID < 50500) {
 116                          // Clear json_last_error()
 117                          json_encode(null);
 118                          $errorHandler = set_error_handler('var_dump');
 119                          restore_error_handler();
 120                          set_error_handler(function () use ($errorHandler) {
 121                              if (JSON_ERROR_NONE === json_last_error()) {
 122                                  return $errorHandler && false !== call_user_func_array($errorHandler, func_get_args());
 123                              }
 124                          });
 125                      }
 126  
 127                      $data = json_encode($data, $this->encodingOptions);
 128                  }
 129  
 130                  if (PHP_VERSION_ID < 50500) {
 131                      restore_error_handler();
 132                  }
 133              } catch (\Exception $e) {
 134                  if (PHP_VERSION_ID < 50500) {
 135                      restore_error_handler();
 136                  }
 137                  if (PHP_VERSION_ID >= 50400 && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
 138                      throw $e->getPrevious() ?: $e;
 139                  }
 140                  throw $e;
 141              }
 142          }
 143  
 144          if (JSON_ERROR_NONE !== json_last_error()) {
 145              throw new \InvalidArgumentException($this->transformJsonError());
 146          }
 147  
 148          $this->data = $data;
 149  
 150          return $this->update();
 151      }
 152  
 153      /**
 154       * Updates the content and headers according to the JSON data and callback.
 155       *
 156       * @return JsonResponse
 157       */
 158      protected function update()
 159      {
 160          if (null !== $this->callback) {
 161              // Not using application/javascript for compatibility reasons with older browsers.
 162              $this->headers->set('Content-Type', 'text/javascript');
 163  
 164              return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data));
 165          }
 166  
 167          // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback)
 168          // in order to not overwrite a custom definition.
 169          if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) {
 170              $this->headers->set('Content-Type', 'application/json');
 171          }
 172  
 173          return $this->setContent($this->data);
 174      }
 175  
 176      private function transformJsonError()
 177      {
 178          if (function_exists('json_last_error_msg')) {
 179              return json_last_error_msg();
 180          }
 181  
 182          switch (json_last_error()) {
 183              case JSON_ERROR_DEPTH:
 184                  return 'Maximum stack depth exceeded.';
 185  
 186              case JSON_ERROR_STATE_MISMATCH:
 187                  return 'Underflow or the modes mismatch.';
 188  
 189              case JSON_ERROR_CTRL_CHAR:
 190                  return 'Unexpected control character found.';
 191  
 192              case JSON_ERROR_SYNTAX:
 193                  return 'Syntax error, malformed JSON.';
 194  
 195              case JSON_ERROR_UTF8:
 196                  return 'Malformed UTF-8 characters, possibly incorrectly encoded.';
 197  
 198              default:
 199                  return 'Unknown error.';
 200          }
 201      }
 202  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1