<?php /** * THttpResponse class * * @author Qiang Xue <qiang.xue@gmail.com> * @link http://www.pradosoft.com/ * @copyright Copyright © 2005 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web */ /** * Includes the THttpResponse adapter. */ Prado::using('System.Web.THttpResponseAdapter'); /** * THttpResponse class * * THttpResponse implements the mechanism for sending output to client users. * * To output a string to client, use {@link write()}. By default, the output is * buffered until {@link flush()} is called or the application ends. The output in * the buffer can also be cleaned by {@link clear()}. To disable output buffering, * set BufferOutput property to false. * * To send cookies to client, use {@link getCookies()}. * To redirect client browser to a new URL, use {@link redirect()}. * To send a file to client, use {@link writeFile()}. * * By default, THttpResponse is registered with {@link TApplication} as the * response module. It can be accessed via {@link TApplication::getResponse()}. * * THttpResponse may be configured in application configuration file as follows * * <module id="response" class="System.Web.THttpResponse" CacheExpire="20" CacheControl="nocache" BufferOutput="true" /> * * where {@link getCacheExpire CacheExpire}, {@link getCacheControl CacheControl} * and {@link getBufferOutput BufferOutput} are optional properties of THttpResponse. * * THttpResponse sends charset header if either {@link setCharset() Charset} * or {@link TGlobalization::setCharset() TGlobalization.Charset} is set. * * @author Qiang Xue <qiang.xue@gmail.com> * @version $Id$ * @package System.Web * @since 3.0 */ class THttpResponse extends TModule implements ITextWriter { /** * @var boolean whether to buffer output */ private $_bufferOutput=true; /** * @var boolean if the application is initialized */ private $_initialized=false; /** * @var THttpCookieCollection list of cookies to return */ private $_cookies=null; /** * @var integer response status code */ private $_status=200; /** * @var string HTML writer type */ private $_htmlWriterType='System.Web.UI.THtmlWriter'; /** * @var string content type */ private $_contentType=null; /** * @var string character set, e.g. UTF-8 */ private $_charset=''; /** * @var THttpResponseAdapter adapter. */ private $_adapter; /** * Destructor. * Flushes any existing content in buffer. */ public function __destruct() { //if($this->_bufferOutput) // @ob_end_flush(); } /** * @param THttpResponseAdapter response adapter */ public function setAdapter(THttpResponseAdapter $adapter) { $this->_adapter=$adapter; } /** * @return THttpResponseAdapter response adapter, null if not exist. */ public function getAdapter() { return $this->_adapter; } /** * @return boolean true if adapter exists, false otherwise. */ public function getHasAdapter() { return !is_null($this->_adapter); } /** * Initializes the module. * This method is required by IModule and is invoked by application. * It starts output buffer if it is enabled. * @param TXmlElement module configuration */ public function init($config) { if($this->_bufferOutput) ob_start(); $this->_initialized=true; $this->getApplication()->setResponse($this); } /** * @return integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter. Defaults to 180. */ public function getCacheExpire() { return session_cache_expire(); } /** * @param integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter. */ public function setCacheExpire($value) { session_cache_expire(TPropertyValue::ensureInteger($value)); } /** * @return string cache control method to use for session pages */ public function getCacheControl() { return session_cache_limiter(); } /** * @param string cache control method to use for session pages. Valid values * include none/nocache/private/private_no_expire/public */ public function setCacheControl($value) { session_cache_limiter(TPropertyValue::ensureEnum($value,array('none','nocache','private','private_no_expire','public'))); } /** * @return string content type, default is text/html */ public function setContentType($type) { $this->_contentType = $type; } /** * @return string current content type */ public function getContentType() { return $this->_contentType; } /** * @return string output charset. */ public function getCharset() { return $this->_charset; } /** * @param string output charset. */ public function setCharset($charset) { $this->_charset = $charset; } /** * @return boolean whether to enable output buffer */ public function getBufferOutput() { return $this->_bufferOutput; } /** * @param boolean whether to enable output buffer * @throws TInvalidOperationException if session is started already */ public function setBufferOutput($value) { if($this->_initialized) throw new TInvalidOperationException('httpresponse_bufferoutput_unchangeable'); else $this->_bufferOutput=TPropertyValue::ensureBoolean($value); } /** * @return integer HTTP status code, defaults to 200 */ public function getStatusCode() { return $this->_status; } /** * @param integer HTTP status code */ public function setStatusCode($status) { $this->_status=TPropertyValue::ensureInteger($status); } /** * @return THttpCookieCollection list of output cookies */ public function getCookies() { if($this->_cookies===null) $this->_cookies=new THttpCookieCollection($this); return $this->_cookies; } /** * Outputs a string. * It may not be sent back to user immediately if output buffer is enabled. * @param string string to be output */ public function write($str) { echo $str; } /** * Sends a file back to user. * Make sure not to output anything else after calling this method. * @param string file name * @param string content to be set. If null, the content will be read from the server file pointed to by $fileName. * @param string mime type of the content. * @param array list of headers to be sent. Each array element represents a header string (e.g. 'Content-Type: text/plain'). * @throws TInvalidDataValueException if the file cannot be found */ public function writeFile($fileName,$content=null,$mimeType=null,$headers=null) { static $defaultMimeTypes=array( 'css'=>'text/css', 'gif'=>'image/gif', 'jpg'=>'image/jpeg', 'jpeg'=>'image/jpeg', 'htm'=>'text/html', 'html'=>'text/html', 'js'=>'javascript/js' ); if($mimeType===null) { $mimeType='text/plain'; if(function_exists('mime_content_type')) $mimeType=mime_content_type($fileName); else if(($ext=strrchr($fileName,'.'))!==false) { $ext=substr($ext,1); if(isset($defaultMimeTypes[$ext])) $mimeType=$defaultMimeTypes[$ext]; } } $fn=basename($fileName); if(is_array($headers)) { foreach($headers as $h) header($h); } else { header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); } header("Content-type: $mimeType"); header('Content-Length: '.($content===null?filesize($fileName):strlen($content))); header("Content-Disposition: attachment; filename=\"$fn\""); header('Content-Transfer-Encoding: binary'); if($content===null) readfile($fileName); else echo $content; } /** * Redirects the browser to the specified URL. * The current application will be terminated after this method is invoked. * @param string URL to be redirected to. If the URL is a relative one, the base URL of * the current request will be inserted at the beginning. */ public function redirect($url) { if($this->getHasAdapter()) $this->_adapter->httpRedirect($url); else $this->httpRedirect($url); } /** * Redirect the browser to another URL and exists the current application. * This method is used internally. Please use {@link redirect} instead. * @param string URL to be redirected to. If the URL is a relative one, the base URL of * the current request will be inserted at the beginning. */ public function httpRedirect($url) { if(!$this->getApplication()->getRequestCompleted()) $this->getApplication()->onEndRequest(); if($url[0]==='/') $url=$this->getRequest()->getBaseUrl().$url; header('Location: '.str_replace('&','&',$url)); exit(); } /** * Reloads the current page. * The effect of this method call is the same as user pressing the * refresh button on his browser (without post data). **/ public function reload() { $this->redirect($this->getRequest()->getRequestUri()); } /** * Flush the response contents and headers. */ public function flush() { if($this->getHasAdapter()) $this->_adapter->flushContent(); else $this->flushContent(); } /** * Outputs the buffered content, sends content-type and charset header. * This method is used internally. Please use {@link flush} instead. */ public function flushContent() { Prado::trace("Flushing output",'System.Web.THttpResponse'); $this->sendContentTypeHeader(); if($this->_bufferOutput) ob_flush(); } /** * Sends content type header if charset is not empty. */ protected function sendContentTypeHeader() { $charset=$this->getCharset(); if($charset==='' && ($globalization=$this->getApplication()->getGlobalization(false))!==null) $charset=$globalization->getCharset(); if($charset!=='') { $contentType=$this->_contentType===null?'text/html':$this->_contentType; $this->appendHeader('Content-Type: '.$contentType.';charset='.$charset); } else if($this->_contentType!==null) $this->appendHeader('Content-Type: '.$this->_contentType.';charset=UTF-8'); } /** * Returns the content in the output buffer. * The buffer will NOT be cleared after calling this method. * Use {@link clear()} is you want to clear the buffer. * @return string output that is in the buffer. */ public function getContents() { Prado::trace("Retrieving output",'System.Web.THttpResponse'); return $this->_bufferOutput?ob_get_contents():''; } /** * Clears any existing buffered content. */ public function clear() { if($this->_bufferOutput) ob_clean(); Prado::trace("Clearing output",'System.Web.THttpResponse'); } /** * Sends a header. * @param string header */ public function appendHeader($value) { Prado::trace("Sending header '$value'",'System.Web.THttpResponse'); header($value); } /** * Writes a log message into error log. * This method is simple wrapper of PHP function error_log. * @param string The error message that should be logged * @param integer where the error should go * @param string The destination. Its meaning depends on the message parameter as described above * @param string The extra headers. It's used when the message parameter is set to 1. This message type uses the same internal function as mail() does. * @see http://us2.php.net/manual/en/function.error-log.php */ public function appendLog($message,$messageType=0,$destination='',$extraHeaders='') { error_log($message,$messageType,$destination,$extraHeaders); } /** * Sends a cookie. * Do not call this method directly. Operate with the result of {@link getCookies} instead. * @param THttpCookie cook to be sent */ public function addCookie($cookie) { $request=$this->getRequest(); if($request->getEnableCookieValidation()) { $value=$this->getApplication()->getSecurityManager()->hashData($cookie->getValue()); setcookie($cookie->getName(),$value,$cookie->getExpire(),$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); } else setcookie($cookie->getName(),$cookie->getValue(),$cookie->getExpire(),$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); } /** * Deletes a cookie. * Do not call this method directly. Operate with the result of {@link getCookies} instead. * @param THttpCookie cook to be deleted */ public function removeCookie($cookie) { setcookie($cookie->getName(),null,0,$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); } /** * @return string the type of HTML writer to be used, defaults to THtmlWriter */ public function getHtmlWriterType() { return $this->_htmlWriterType; } /** * @param string the type of HTML writer to be used, may be the class name or the namespace */ public function setHtmlWriterType($value) { $this->_htmlWriterType=$value; } /** * Creates a new instance of HTML writer. * If the type of the HTML writer is not supplied, {@link getHtmlWriterType HtmlWriterType} will be assumed. * @param string type of the HTML writer to be created. If null, {@link getHtmlWriterType HtmlWriterType} will be assumed. */ public function createHtmlWriter($type=null) { if($type===null) $type=$this->getHtmlWriterType(); if($this->getHasAdapter()) return $this->_adapter->createNewHtmlWriter($type, $this); else return $this->createNewHtmlWriter($type, $this); } /** * Create a new html writer instance. * This method is used internally. Please use {@link createHtmlWriter} instead. * @param string type of HTML writer to be created. * @param ITextWriter text writer holding the contents. */ public function createNewHtmlWriter($type, $writer) { return Prado::createComponent($type, $writer); } } ?>