[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/aphront/response/ -> AphrontResponse.php (source)

   1  <?php
   2  
   3  abstract class AphrontResponse {
   4  
   5    private $request;
   6    private $cacheable = false;
   7    private $responseCode = 200;
   8    private $lastModified = null;
   9  
  10    protected $frameable;
  11  
  12    public function setRequest($request) {
  13      $this->request = $request;
  14      return $this;
  15    }
  16  
  17    public function getRequest() {
  18      return $this->request;
  19    }
  20  
  21    public function getHeaders() {
  22      $headers = array();
  23      if (!$this->frameable) {
  24        $headers[] = array('X-Frame-Options', 'Deny');
  25      }
  26  
  27      return $headers;
  28    }
  29  
  30    public function setCacheDurationInSeconds($duration) {
  31      $this->cacheable = $duration;
  32      return $this;
  33    }
  34  
  35    public function setLastModified($epoch_timestamp) {
  36      $this->lastModified = $epoch_timestamp;
  37      return $this;
  38    }
  39  
  40    public function setHTTPResponseCode($code) {
  41      $this->responseCode = $code;
  42      return $this;
  43    }
  44  
  45    public function getHTTPResponseCode() {
  46      return $this->responseCode;
  47    }
  48  
  49    public function getHTTPResponseMessage() {
  50      return '';
  51    }
  52  
  53    public function setFrameable($frameable) {
  54      $this->frameable = $frameable;
  55      return $this;
  56    }
  57  
  58    public static function processValueForJSONEncoding(&$value, $key) {
  59      if ($value instanceof PhutilSafeHTMLProducerInterface) {
  60        // This renders the producer down to PhutilSafeHTML, which will then
  61        // be simplified into a string below.
  62        $value = hsprintf('%s', $value);
  63      }
  64  
  65      if ($value instanceof PhutilSafeHTML) {
  66        // TODO: Javelin supports implicity conversion of '__html' objects to
  67        // JX.HTML, but only for Ajax responses, not behaviors. Just leave things
  68        // as they are for now (where behaviors treat responses as HTML or plain
  69        // text at their discretion).
  70        $value = $value->getHTMLContent();
  71      }
  72    }
  73  
  74    public static function encodeJSONForHTTPResponse(array $object) {
  75  
  76      array_walk_recursive(
  77        $object,
  78        array('AphrontResponse', 'processValueForJSONEncoding'));
  79  
  80      $response = json_encode($object);
  81  
  82      // Prevent content sniffing attacks by encoding "<" and ">", so browsers
  83      // won't try to execute the document as HTML even if they ignore
  84      // Content-Type and X-Content-Type-Options. See T865.
  85      $response = str_replace(
  86        array('<', '>'),
  87        array('\u003c', '\u003e'),
  88        $response);
  89  
  90      return $response;
  91    }
  92  
  93    protected function addJSONShield($json_response) {
  94      // Add a shield to prevent "JSON Hijacking" attacks where an attacker
  95      // requests a JSON response using a normal <script /> tag and then uses
  96      // Object.prototype.__defineSetter__() or similar to read response data.
  97      // This header causes the browser to loop infinitely instead of handing over
  98      // sensitive data.
  99  
 100      $shield = 'for (;;);';
 101  
 102      $response = $shield.$json_response;
 103  
 104      return $response;
 105    }
 106  
 107    public function getCacheHeaders() {
 108      $headers = array();
 109      if ($this->cacheable) {
 110        $headers[] = array(
 111          'Expires',
 112          $this->formatEpochTimestampForHTTPHeader(time() + $this->cacheable),
 113        );
 114      } else {
 115        $headers[] = array(
 116          'Cache-Control',
 117          'private, no-cache, no-store, must-revalidate',
 118        );
 119        $headers[] = array(
 120          'Pragma',
 121          'no-cache',
 122        );
 123        $headers[] = array(
 124          'Expires',
 125          'Sat, 01 Jan 2000 00:00:00 GMT',
 126        );
 127      }
 128  
 129      if ($this->lastModified) {
 130        $headers[] = array(
 131          'Last-Modified',
 132          $this->formatEpochTimestampForHTTPHeader($this->lastModified),
 133        );
 134      }
 135  
 136      // IE has a feature where it may override an explicit Content-Type
 137      // declaration by inferring a content type. This can be a security risk
 138      // and we always explicitly transmit the correct Content-Type header, so
 139      // prevent IE from using inferred content types. This only offers protection
 140      // on recent versions of IE; IE6/7 and Opera currently ignore this header.
 141      $headers[] = array('X-Content-Type-Options', 'nosniff');
 142  
 143      return $headers;
 144    }
 145  
 146    private function formatEpochTimestampForHTTPHeader($epoch_timestamp) {
 147      return gmdate('D, d M Y H:i:s', $epoch_timestamp).' GMT';
 148    }
 149  
 150    abstract public function buildResponseString();
 151  
 152  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1