Namespaces

  • 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

  • Context
  • FileUpload
  • Request
  • RequestFactory
  • Response
  • Session
  • SessionSection
  • Url
  • UrlScript
  • UserStorage

Interfaces

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