Esempio n. 1
0
 /**
  * Send HTTP response
  *
  * Send the specific X-Sendfile HTTP headers for internal processing by the server. For Nginx and Lighttpd 1.4
  * remove the X-Sendfile header and use the specific header instead.
  *
  * If the X-Sendfile header is 1 or TRUE, the response path will be used instead of the path supplied in the
  * header. If X-Sendfile header is  0 or FALSE the header is ignored and removed.
  *
  * - Apache    : X-Sendfile
  * - Nginx     : X-Accel-Redirect
  * - Lightttpd : X-LIGHTTPD-send-file (v1.4) or X-Sendfile (v1.5)
  *
  * @param DispatcherResponseInterface $response
  * @return boolean
  */
 public function send(DispatcherResponseInterface $response)
 {
     if ($response->headers->has('X-Sendfile')) {
         $path = $response->headers->get('X-Sendfile');
         if ($path === true || $path === 1) {
             $path = $response->getContent()->getPathname();
         }
         if (is_file($path)) {
             $server = strtolower($_SERVER['SERVER_SOFTWARE']);
             //Nginx uses X-Accel-Redirect header
             if (strpos($server, 'nginx') !== FALSE) {
                 $path = preg_replace('/' . preg_quote(JPATH_ROOT, '/') . '/', '', $path, 1);
                 $response->headers->set('X-Accel-Redirect', $path);
                 $response->headers->remove('X-Sendfile');
             }
             //Lighttpd 1.4 uses X-LIGHTTPD-send-file header
             if (strpos($server, 'lightttpd/1.4') !== FALSE) {
                 $response->headers->set('X-LIGHTTPD-send-file', $path);
                 $response->headers->remove('X-Sendfile');
             }
             return parent::send($response);
         } else {
             $response->headers->remove('X-Sendfile');
         }
     }
 }
Esempio n. 2
0
 /**
  * Send HTTP response
  *
  * If the format is json, add the padding by inspect the request query for a 'callback' parameter or by using
  * the default padding if set.
  *
  * Don't stop the transport handler chain to allow other transports handlers to continue processing the
  * response.
  *
  * @link http://tools.ietf.org/html/rfc2616
  *
  * @param DispatcherResponseInterface $response
  * @return boolean
  */
 public function send(DispatcherResponseInterface $response)
 {
     $request = $response->getRequest();
     //Force to use the json transport if format is json
     if ($request->getFormat() == 'json') {
         //If not padding is set inspect the request query.
         if (empty($this->_padding)) {
             if ($request->query->has('callback')) {
                 $this->setCallback($request->query->get('callback', 'cmd'));
             }
         }
         if (!empty($this->_padding)) {
             $response->setContent(sprintf('%s(%s);', $this->_padding, $response->getContent()));
         }
     }
 }
Esempio n. 3
0
 /**
  * Send response
  *
  * @param DispatcherResponseInterface $response
  * @return boolean  Returns true if the response has been send, otherwise FALSE
  */
 public function send(DispatcherResponseInterface $response)
 {
     //Cleanup and flush output to client
     if (!function_exists('fastcgi_finish_request')) {
         if (PHP_SAPI !== 'cli') {
             for ($i = 0; $i < ob_get_level(); $i++) {
                 ob_end_flush();
             }
             flush();
         }
     } else {
         fastcgi_finish_request();
     }
     //Set the exit status based on the status code.
     $status = 0;
     if (!$response->isSuccess()) {
         $status = (int) $response->getStatusCode();
     }
     exit($status);
     return true;
 }
Esempio n. 4
0
 /**
  * Send HTTP response
  *
  * Send the specific X-Sendfile HTTP headers for internal processing by the server.
  *
  * - Apache : X-Sendfile
  * - Nginx  : X-Accel-Redirect
  *
  * @param DispatcherResponseInterface $response
  * @return boolean
  */
 public function send(DispatcherResponseInterface $response)
 {
     if ($response->isDownloadable()) {
         $server = strtolower($_SERVER['SERVER_SOFTWARE']);
         //Apache
         if (strpos($server, 'apache') !== FALSE) {
             if (in_array('mod_xsendfile', apache_get_modules())) {
                 $path = $response->getStream()->getPath();
                 $response->headers->set('X-Sendfile', $path);
                 return parent::send($response);
             }
         }
         //Nginx
         if (strpos($server, 'nginx') !== FALSE) {
             $path = $response->getStream()->getPath();
             $path = preg_replace('/' . preg_quote(\Kodekit::getInstance()->getRootPath(), '/') . '/', '', $path, 1);
             $response->headers->set('X-Accel-Redirect', $path);
             return parent::send($response);
         }
     }
 }
Esempio n. 5
0
 /**
  * Send HTTP response
  *
  * If this is a redirect response, send the response and stop the transport handler chain.
  *
  * @link: https://en.wikipedia.org/wiki/Meta_refresh
  *
  * @param DispatcherResponseInterface $response
  * @return boolean
  */
 public function send(DispatcherResponseInterface $response)
 {
     if ($response->isRedirect()) {
         $session = $response->getUser()->getSession();
         //Set the messages into the session
         $messages = $response->getMessages();
         if (count($messages)) {
             //Auto start the session if it's not active.
             if (!$session->isActive()) {
                 $session->start();
             }
             $session->getContainer('message')->add($messages);
         }
         //Set the redirect into the response
         $format = $response->getRequest()->getFormat();
         if ($format == 'json') {
             array_unshift($messages, sprintf('Redirecting to %1$s', $response->getHeaders()->get('Location')));
             $response->setContent(json_encode(array('messages' => $messages)), 'application/json');
         }
         if ($format == 'html') {
             $response->setContent(sprintf('<!DOCTYPE html>
                     <html>
                         <head>
                             <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                             <noscript>
                                 <meta http-equiv="refresh" content="1;url=%1$s" />
                             </noscript>
                             <title>Redirecting to %1$s</title>
                         </head>
                         <body onload="window.location = \'%1$s\'">
                             Redirecting to <a href="%1$s">%1$s</a>.
                         </body>
                     </html>', htmlspecialchars($response->getHeaders()->get('Location'), ENT_QUOTES, 'UTF-8')), 'text/html');
         }
         return parent::send($response);
     }
 }
Esempio n. 6
0
 /**
  * Send HTTP response
  *
  * Prepares the Response before it is sent to the client. This method tweaks the headers to ensure that
  * it is compliant with RFC 2616 and calculates or modifies the cache-control header to a sensible and
  * conservative value
  *
  * @link http://tools.ietf.org/html/rfc2616
  *
  * @param DispatcherResponseInterface $response
  * @return boolean  Returns true if the response has been send, otherwise FALSE
  */
 public function send(DispatcherResponseInterface $response)
 {
     $request = $response->getRequest();
     //Make sure we do not have body content for 204, 205 and 305 status codes
     $codes = array(HttpResponse::NO_CONTENT, HttpResponse::NOT_MODIFIED, HttpResponse::RESET_CONTENT);
     if (in_array($response->getStatusCode(), $codes)) {
         $response->setContent(null);
     }
     //Remove location header if we are not redirecting and the status code is not 201
     if (!$response->isRedirect() && $response->getStatusCode() !== HttpResponse::CREATED) {
         if ($response->headers->has('Location')) {
             $response->headers->remove('Location');
         }
     }
     //Add file related information if we are serving a file
     if ($response->isDownloadable()) {
         //Last-Modified header
         $time = $response->getStream()->getTime(FilesystemStream::TIME_MODIFIED);
         $response->setLastModified($time);
         //Disposition header
         $response->headers->set('Content-Disposition', array('inline', 'filename' => '"' . basename($response->getStream()->getPath()) . '"'));
         //Force a download by the browser by setting the disposition to 'attachment'.
         if ($response->isAttachable()) {
             $response->setContentType('application/force-download');
             $response->headers->set('Content-Disposition', array('attachment', 'filename' => '"' . basename($response->getStream()->getPath()) . '"'));
         }
     }
     //Add Last-Modified header if not present
     if (!$response->headers->has('Last-Modified')) {
         $response->setLastModified(new \DateTime('now'));
     }
     //Add Content-Length if not present
     if (!$response->headers->has('Content-Length')) {
         $response->headers->set('Content-Length', $response->getStream()->getSize());
     }
     //Remove Content-Length for transfer encoded responses that do not contain a content range
     if ($response->headers->has('Transfer-Encoding')) {
         $response->headers->remove('Content-Length');
     }
     //Modifies the response so that it conforms to the rules defined for a 304 status code.
     if ($response->getStatusCode() == HttpResponse::NOT_MODIFIED) {
         $response->setContent(null);
         $headers = array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified');
         //Remove headers that MUST NOT be included with 304 Not Modified responses
         foreach ($headers as $header) {
             $response->headers->remove($header);
         }
     }
     //Calculates or modifies the cache-control header to a sensible, conservative value.
     $cache_control = (array) $response->headers->get('Cache-Control', null, false);
     if (empty($cache_control)) {
         if (!$response->isCacheable()) {
             $response->headers->set('Cache-Control', 'no-cache');
         } else {
             $response->headers->set('Cache-Control', array('private', 'must-revalidate'));
         }
     }
     //Send headers and content
     $this->sendHeaders($response)->sendContent($response);
     return headers_sent();
 }
Esempio n. 7
0
 /**
  * Send HTTP response
  *
  * If this is a redirect response, send the response and stop the transport handler chain.
  *
  * @param DispatcherResponseInterface $response
  * @return boolean
  */
 public function send(DispatcherResponseInterface $response)
 {
     if ($response->isRedirect()) {
         return parent::send($response);
     }
 }
Esempio n. 8
0
 /**
  * Send HTTP response
  *
  * @param DispatcherResponseInterface $response
  * @return boolean
  */
 public function send(DispatcherResponseInterface $response)
 {
     $request = $response->getRequest();
     if ($response->isStreamable()) {
         //Explicitly set the Accept Ranges header to bytes to inform client we accept range requests
         $response->headers->set('Accept-Ranges', 'bytes');
         //Set a file etag
         $response->headers->set('etag', $this->getFileEtag($response));
         if ($request->isStreaming()) {
             if ($response->isSuccess()) {
                 //Default Content-Type Header
                 if (!$response->headers->has('Content-Type')) {
                     $response->headers->set('Content-Type', 'application/octet-stream');
                 }
                 //Transfer Encoding Headers
                 $response->headers->set('Transfer-Encoding', 'chunked');
                 //Content Range Headers
                 $offset = $this->getOffset($response);
                 $range = $this->getRange($response);
                 $size = $this->getFileSize($response);
                 $response->setStatus(HttpResponse::PARTIAL_CONTENT);
                 $response->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $offset, $range, $size));
             }
             if ($response->isError()) {
                 /**
                  * A server sending a response with status code 416 (Requested range not satisfiable) SHOULD include a
                  * Content-Range field with a byte-range- resp-spec of "*". The instance-length specifies the current
                  * length of the selected resource.
                  *
                  * @see : http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
                  */
                 if ($response->getStatusCode() == HttpResponse::REQUESTED_RANGE_NOT_SATISFIED) {
                     $size = $this->getFileSize($response);
                     $response->headers->set('Content-Range', sprintf('bytes */%s', $size));
                 }
             }
         }
         return parent::send($response);
     }
 }
Esempio n. 9
0
 /**
  * Send HTTP response
  *
  * Prepares the Response before it is sent to the client. This method tweaks the headers to ensure that
  * it is compliant with RFC 2616 and calculates or modifies the cache-control header to a sensible and
  * conservative value
  *
  * @link http://tools.ietf.org/html/rfc2616
  * @link http://tools.ietf.org/html/rfc7235
  *
  * @param DispatcherResponseInterface $response
  * @return boolean  Returns true if the response has been send, otherwise FALSE
  */
 public function send(DispatcherResponseInterface $response)
 {
     $request = $response->getRequest();
     //Make sure we do not have body content for 204, 205 and 305 status codes
     $codes = array(HttpResponse::NO_CONTENT, HttpResponse::NOT_MODIFIED, HttpResponse::RESET_CONTENT);
     if (in_array($response->getStatusCode(), $codes)) {
         $response->setContent(null);
     }
     //Remove location header if we are not redirecting and the status code is not 201
     if (!$response->isRedirect() && $response->getStatusCode() !== HttpResponse::CREATED) {
         if ($response->headers->has('Location')) {
             $response->headers->remove('Location');
         }
     }
     // IIS does not like it when you have a Location header in a non-redirect request
     // @link : http://stackoverflow.com/questions/12074730/w7-pro-iis-7-5-overwrites-php-location-header-solved
     if ($response->headers->has('Location') && !$response->isRedirect()) {
         $server = isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : getenv('SERVER_SOFTWARE');
         if ($server && strpos(strtolower($server), 'microsoft-iis') !== false) {
             $response->headers->remove('Location');
         }
     }
     //Add file related information if we are serving a file
     if ($response->isDownloadable()) {
         //Last-Modified header
         if ($time = $response->getStream()->getTime(FilesystemStreamInterface::TIME_MODIFIED)) {
             $response->setLastModified($time);
         }
         //Allow to define a custom filename
         if ($response->headers->has('X-Content-Disposition-Filename')) {
             $filename = $response->headers->get('X-Content-Disposition-Filename');
             $response->headers->remove('X-Content-Disposition-Filename');
         } else {
             //basename does not work if the string starts with a UTF character
             $filename = ltrim(basename(' ' . strtr($response->getStream()->getPath(), array('/' => '/ '))));
         }
         //Android cuts file names after #
         $user_agent = $response->getRequest()->getAgent();
         if (stripos($user_agent, 'Android')) {
             $filename = str_replace('#', '_', $filename);
         }
         $disposition = array('filename' => '"' . $filename . '"');
         //IE7 and 8 accepts percent encoded file names as the filename value
         //Other browsers (except Safari) use filename* header starting with UTF-8''
         $encoded_name = rawurlencode($filename);
         if ($encoded_name !== $filename) {
             if (preg_match('/(?i)MSIE [4-8]/i', $user_agent)) {
                 $disposition['filename'] = '"' . $encoded_name . '"';
             } elseif (!stripos($user_agent, 'AppleWebkit')) {
                 $disposition['filename*'] = 'UTF-8\'\'' . $encoded_name;
             }
         }
         //Disposition header
         $response->headers->set('Content-Disposition', array_merge(array('inline'), $disposition));
         //Force a download by the browser by setting the disposition to 'attachment'.
         if ($response->isAttachable()) {
             $response->setContentType('application/octet-stream');
             $response->headers->set('Content-Disposition', array_merge(array('attachment'), $disposition));
         }
     }
     //Add Last-Modified header if not present
     if (!$response->headers->has('Last-Modified')) {
         $response->setLastModified(new \DateTime('now'));
     }
     //Add Content-Length if not present
     if (!$response->headers->has('Content-Length') && $response->getStream()->getSize()) {
         $response->headers->set('Content-Length', $response->getStream()->getSize());
     }
     //Remove Content-Length for transfer encoded responses that do not contain a content range
     if ($response->headers->has('Transfer-Encoding')) {
         $response->headers->remove('Content-Length');
     }
     //Modifies the response so that it conforms to the rules defined for a 304 status code.
     if ($response->getStatusCode() == HttpResponse::NOT_MODIFIED) {
         $response->setContent(null);
         $headers = array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified');
         //Remove headers that MUST NOT be included with 304 Not Modified responses
         foreach ($headers as $header) {
             $response->headers->remove($header);
         }
     }
     //Modifies the response so that it conforms to the rules defined for a 401 status code.
     if ($response->getStatusCode() == HttpResponse::UNAUTHORIZED) {
         //The response MUST include a WWW-Authenticate header field, use 'unknown' scheme.
         //@link : http://tools.ietf.org/html/rfc7235 (updated spec)
         //@link : http://greenbytes.de/tech/tc/httpauth/
         if (!$response->headers->has('WWW-Authenticate')) {
             $response->headers->set('WWW-Authenticate', 'unknown');
         }
     }
     //Calculates or modifies the cache-control header to a sensible, conservative value.
     $cache_control = (array) $response->headers->get('Cache-Control', null, false);
     if (empty($cache_control)) {
         if (!$response->isCacheable()) {
             $response->headers->set('Cache-Control', 'no-cache');
         } else {
             $response->headers->set('Cache-Control', array('private', 'must-revalidate'));
         }
     }
     // Prevent caching: Cache-control needs to be empty for IE on SSL.
     // @link : http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431
     if ($request->isSecure() && preg_match('#(?:MSIE |Internet Explorer/)(?:[0-9.]+)#', $request->getAgent())) {
         $response->headers->set('Cache-Control', '');
     }
     //Send headers and content
     $this->sendHeaders($response)->sendContent($response);
     return parent::send($response);
 }