Packages

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • HttpContext
  • HttpRequest
  • HttpRequestFactory
  • HttpResponse
  • HttpUploadedFile
  • Session
  • SessionSection
  • Url
  • UrlScript
  • UserStorage

Interfaces

  • IHttpRequest
  • IHttpResponse
  • ISessionStorage
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  * @package Nette\Http
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * HttpResponse class.
 17:  *
 18:  * @author     David Grudl
 19:  *
 20:  * @property   int $code
 21:  * @property-read bool $sent
 22:  * @property-read array $headers
 23:  * @package Nette\Http
 24:  */
 25: final class HttpResponse extends Object implements IHttpResponse
 26: {
 27:     /** @var bool  Send invisible garbage for IE 6? */
 28:     private static $fixIE = TRUE;
 29: 
 30:     /** @var string The domain in which the cookie will be available */
 31:     public $cookieDomain = '';
 32: 
 33:     /** @var string The path in which the cookie will be available */
 34:     public $cookiePath = '/';
 35: 
 36:     /** @var string Whether the cookie is available only through HTTPS */
 37:     public $cookieSecure = FALSE;
 38: 
 39:     /** @var string Whether the cookie is hidden from client-side */
 40:     public $cookieHttpOnly = TRUE;
 41: 
 42:     /** @var int HTTP response code */
 43:     private $code = self::S200_OK;
 44: 
 45: 
 46:     /**
 47:      * Sets HTTP response code.
 48:      * @param  int
 49:      * @return self
 50:      * @throws InvalidArgumentException  if code is invalid
 51:      * @throws InvalidStateException  if HTTP headers have been sent
 52:      */
 53:     public function setCode($code)
 54:     {
 55:         $code = (int) $code;
 56: 
 57:         static $allowed = array(
 58:             200=>1, 201=>1, 202=>1, 203=>1, 204=>1, 205=>1, 206=>1,
 59:             300=>1, 301=>1, 302=>1, 303=>1, 304=>1, 307=>1,
 60:             400=>1, 401=>1, 403=>1, 404=>1, 405=>1, 406=>1, 408=>1, 410=>1, 412=>1, 415=>1, 416=>1,
 61:             500=>1, 501=>1, 503=>1, 505=>1
 62:         );
 63: 
 64:         if (!isset($allowed[$code])) {
 65:             throw new InvalidArgumentException("Bad HTTP response '$code'.");
 66: 
 67:         } elseif (headers_sent($file, $line)) {
 68:             throw new InvalidStateException("Cannot set HTTP code after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
 69: 
 70:         } else {
 71:             $this->code = $code;
 72:             $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
 73:             header($protocol . ' ' . $code, TRUE, $code);
 74:         }
 75:         return $this;
 76:     }
 77: 
 78: 
 79:     /**
 80:      * Returns HTTP response code.
 81:      * @return int
 82:      */
 83:     public function getCode()
 84:     {
 85:         return $this->code;
 86:     }
 87: 
 88: 
 89:     /**
 90:      * Sends a HTTP header and replaces a previous one.
 91:      * @param  string  header name
 92:      * @param  string  header value
 93:      * @return self
 94:      * @throws InvalidStateException  if HTTP headers have been sent
 95:      */
 96:     public function setHeader($name, $value)
 97:     {
 98:         if (headers_sent($file, $line)) {
 99:             throw new InvalidStateException("Cannot send header after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
100:         }
101: 
102:         if ($value === NULL && function_exists('header_remove')) {
103:             header_remove($name);
104:         } elseif (strcasecmp($name, 'Content-Length') === 0 && ini_get('zlib.output_compression')) {
105:             // ignore, PHP bug #44164
106:         } else {
107:             header($name . ': ' . $value, TRUE, $this->code);
108:         }
109:         return $this;
110:     }
111: 
112: 
113:     /**
114:      * Adds HTTP header.
115:      * @param  string  header name
116:      * @param  string  header value
117:      * @return self
118:      * @throws InvalidStateException  if HTTP headers have been sent
119:      */
120:     public function addHeader($name, $value)
121:     {
122:         if (headers_sent($file, $line)) {
123:             throw new InvalidStateException("Cannot send header after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
124:         }
125: 
126:         header($name . ': ' . $value, FALSE, $this->code);
127:         return $this;
128:     }
129: 
130: 
131:     /**
132:      * Sends a Content-type HTTP header.
133:      * @param  string  mime-type
134:      * @param  string  charset
135:      * @return self
136:      * @throws InvalidStateException  if HTTP headers have been sent
137:      */
138:     public function setContentType($type, $charset = NULL)
139:     {
140:         $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
141:         return $this;
142:     }
143: 
144: 
145:     /**
146:      * Redirects to a new URL. Note: call exit() after it.
147:      * @param  string  URL
148:      * @param  int     HTTP code
149:      * @return void
150:      * @throws InvalidStateException  if HTTP headers have been sent
151:      */
152:     public function redirect($url, $code = self::S302_FOUND)
153:     {
154:         if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('#^Microsoft-IIS/[1-5]#', $_SERVER['SERVER_SOFTWARE'])
155:             && $this->getHeader('Set-Cookie') !== NULL
156:         ) {
157:             $this->setHeader('Refresh', "0;url=$url");
158:             return;
159:         }
160: 
161:         $this->setCode($code);
162:         $this->setHeader('Location', $url);
163:         echo "<h1>Redirect</h1>\n\n<p><a href=\"" . htmlSpecialChars($url) . "\">Please click here to continue</a>.</p>";
164:     }
165: 
166: 
167:     /**
168:      * Sets the number of seconds before a page cached on a browser expires.
169:      * @param  string|int|DateTime  time, value 0 means "until the browser is closed"
170:      * @return self
171:      * @throws InvalidStateException  if HTTP headers have been sent
172:      */
173:     public function setExpiration($time)
174:     {
175:         if (!$time) { // no cache
176:             $this->setHeader('Cache-Control', 's-maxage=0, max-age=0, must-revalidate');
177:             $this->setHeader('Expires', 'Mon, 23 Jan 1978 10:00:00 GMT');
178:             return $this;
179:         }
180: 
181:         $time = DateTime53::from($time);
182:         $this->setHeader('Cache-Control', 'max-age=' . ($time->format('U') - time()));
183:         $this->setHeader('Expires', self::date($time));
184:         return $this;
185:     }
186: 
187: 
188:     /**
189:      * Checks if headers have been sent.
190:      * @return bool
191:      */
192:     public function isSent()
193:     {
194:         return headers_sent();
195:     }
196: 
197: 
198:     /**
199:      * Return the value of the HTTP header.
200:      * @param  string
201:      * @param  mixed
202:      * @return mixed
203:      */
204:     public function getHeader($header, $default = NULL)
205:     {
206:         $header .= ':';
207:         $len = strlen($header);
208:         foreach (headers_list() as $item) {
209:             if (strncasecmp($item, $header, $len) === 0) {
210:                 return ltrim(substr($item, $len));
211:             }
212:         }
213:         return $default;
214:     }
215: 
216: 
217:     /**
218:      * Returns a list of headers to sent.
219:      * @return array
220:      */
221:     public function getHeaders()
222:     {
223:         $headers = array();
224:         foreach (headers_list() as $header) {
225:             $a = strpos($header, ':');
226:             $headers[substr($header, 0, $a)] = (string) substr($header, $a + 2);
227:         }
228:         return $headers;
229:     }
230: 
231: 
232:     /**
233:      * Returns HTTP valid date format.
234:      * @param  string|int|DateTime
235:      * @return string
236:      */
237:     public static function date($time = NULL)
238:     {
239:         $time = DateTime53::from($time);
240:         $time->setTimezone(new DateTimeZone('GMT'));
241:         return $time->format('D, d M Y H:i:s \G\M\T');
242:     }
243: 
244: 
245:     /**
246:      * @return void
247:      */
248:     public function __destruct()
249:     {
250:         if (self::$fixIE && isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') !== FALSE
251:             && in_array($this->code, array(400, 403, 404, 405, 406, 408, 409, 410, 500, 501, 505), TRUE)
252:             && $this->getHeader('Content-Type', 'text/html') === 'text/html'
253:         ) {
254:             echo Strings::random(2e3, " \t\r\n"); // sends invisible garbage for IE
255:             self::$fixIE = FALSE;
256:         }
257:     }
258: 
259: 
260:     /**
261:      * Sends a cookie.
262:      * @param  string name of the cookie
263:      * @param  string value
264:      * @param  string|int|DateTime  expiration time, value 0 means "until the browser is closed"
265:      * @param  string
266:      * @param  string
267:      * @param  bool
268:      * @param  bool
269:      * @return self
270:      * @throws InvalidStateException  if HTTP headers have been sent
271:      */
272:     public function setCookie($name, $value, $time, $path = NULL, $domain = NULL, $secure = NULL, $httpOnly = NULL)
273:     {
274:         if (headers_sent($file, $line)) {
275:             throw new InvalidStateException("Cannot set cookie after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
276:         }
277: 
278:         setcookie(
279:             $name,
280:             $value,
281:             $time ? DateTime53::from($time)->format('U') : 0,
282:             $path === NULL ? $this->cookiePath : (string) $path,
283:             $domain === NULL ? $this->cookieDomain : (string) $domain,
284:             $secure === NULL ? $this->cookieSecure : (bool) $secure,
285:             $httpOnly === NULL ? $this->cookieHttpOnly : (bool) $httpOnly
286:         );
287: 
288:         $this->removeDuplicateCookies();
289:         return $this;
290:     }
291: 
292: 
293:     /**
294:      * Removes duplicate cookies from response.
295:      * @return void
296:      */
297:     public function removeDuplicateCookies()
298:     {
299:         if (headers_sent($file, $line) || ini_get('suhosin.cookie.encrypt')) {
300:             return;
301:         }
302: 
303:         $flatten = array();
304:         foreach (headers_list() as $header) {
305:             if (preg_match('#^Set-Cookie: .+?=#', $header, $m)) {
306:                 $flatten[$m[0]] = $header;
307:                 if (PHP_VERSION_ID < 50300) { // multiple deleting due PHP bug #61605
308:                     header('Set-Cookie:');
309:                 } else {
310:                     header_remove('Set-Cookie');
311:                 }
312:             }
313:         }
314:         foreach (array_values($flatten) as $key => $header) {
315:             header($header, $key === 0);
316:         }
317:     }
318: 
319: 
320:     /**
321:      * Deletes a cookie.
322:      * @param  string name of the cookie.
323:      * @param  string
324:      * @param  string
325:      * @param  bool
326:      * @return void
327:      * @throws InvalidStateException  if HTTP headers have been sent
328:      */
329:     public function deleteCookie($name, $path = NULL, $domain = NULL, $secure = NULL)
330:     {
331:         $this->setCookie($name, FALSE, 0, $path, $domain, $secure);
332:     }
333: 
334: }
335: 
Nette Framework 2.0.11 (for PHP 5.2, un-prefixed) API API documentation generated by ApiGen 2.8.0