emitHTTPStatus($code); } /** * Write HTTP headers to the output. * * @param list List of pairs. * @return void */ final public function writeHeaders(array $headers) { foreach ($headers as $header) { if (!is_array($header) || count($header) !== 2) { throw new Exception('Malformed header.'); } list($name, $value) = $header; if (strpos($name, ':') !== false) { throw new Exception( "Declining to emit response with malformed HTTP header name: ". $name); } // Attackers may perform an "HTTP response splitting" attack by making // the application emit certain types of headers containing newlines: // // http://en.wikipedia.org/wiki/HTTP_response_splitting // // PHP has built-in protections against HTTP response-splitting, but they // are of dubious trustworthiness: // // http://news.php.net/php.internals/57655 if (preg_match('/[\r\n\0]/', $name.$value)) { throw new Exception( "Declining to emit response with unsafe HTTP header: ". "<'".$name."', '".$value."'>."); } } foreach ($headers as $header) { list($name, $value) = $header; $this->emitHeader($name, $value); } } /** * Write HTTP body data to the output. * * @param string Body data. * @return void */ final public function writeData($data) { $this->emitData($data); } /** * Write an entire @{class:AphrontResponse} to the output. * * @param AphrontResponse The response object to write. * @return void */ final public function writeResponse(AphrontResponse $response) { // Do this first, in case it throws. $response_string = $response->buildResponseString(); $all_headers = array_merge( $response->getHeaders(), $response->getCacheHeaders()); $this->writeHTTPStatus($response->getHTTPResponseCode()); $this->writeHeaders($all_headers); $this->writeData($response_string); } /* -( Emitting the Response )---------------------------------------------- */ abstract protected function emitHTTPStatus($code); abstract protected function emitHeader($name, $value); abstract protected function emitData($data); }