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:         } else {
110:             header($name . ': ' . $value, TRUE, $this->code);
111:         }
112:         return $this;
113:     }
114: 
115: 
116: 
117:     /**
118:      * Adds HTTP header.
119:      * @param  string  header name
120:      * @param  string  header value
121:      * @return Response  provides a fluent interface
122:      * @throws Nette\InvalidStateException  if HTTP headers have been sent
123:      */
124:     public function addHeader($name, $value)
125:     {
126:         if (headers_sent($file, $line)) {
127:             throw new Nette\InvalidStateException("Cannot send header after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
128:         }
129: 
130:         header($name . ': ' . $value, FALSE, $this->code);
131:         return $this;
132:     }
133: 
134: 
135: 
136:     /**
137:      * Sends a Content-type HTTP header.
138:      * @param  string  mime-type
139:      * @param  string  charset
140:      * @return Response  provides a fluent interface
141:      * @throws Nette\InvalidStateException  if HTTP headers have been sent
142:      */
143:     public function setContentType($type, $charset = NULL)
144:     {
145:         $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
146:         return $this;
147:     }
148: 
149: 
150: 
151:     /**
152:      * Redirects to a new URL. Note: call exit() after it.
153:      * @param  string  URL
154:      * @param  int     HTTP code
155:      * @return void
156:      * @throws Nette\InvalidStateException  if HTTP headers have been sent
157:      */
158:     public function redirect($url, $code = self::S302_FOUND)
159:     {
160:         if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('#^Microsoft-IIS/[1-5]#', $_SERVER['SERVER_SOFTWARE'])
161:             && $this->getHeader('Set-Cookie') !== NULL
162:         ) {
163:             $this->setHeader('Refresh', "0;url=$url");
164:             return;
165:         }
166: 
167:         $this->setCode($code);
168:         $this->setHeader('Location', $url);
169:         echo "<h1>Redirect</h1>\n\n<p><a href=\"" . htmlSpecialChars($url) . "\">Please click here to continue</a>.</p>";
170:     }
171: 
172: 
173: 
174:     /**
175:      * Sets the number of seconds before a page cached on a browser expires.
176:      * @param  string|int|DateTime  time, value 0 means "until the browser is closed"
177:      * @return Response  provides a fluent interface
178:      * @throws Nette\InvalidStateException  if HTTP headers have been sent
179:      */
180:     public function setExpiration($time)
181:     {
182:         if (!$time) { // no cache
183:             $this->setHeader('Cache-Control', 's-maxage=0, max-age=0, must-revalidate');
184:             $this->setHeader('Expires', 'Mon, 23 Jan 1978 10:00:00 GMT');
185:             return $this;
186:         }
187: 
188:         $time = Nette\DateTime::from($time);
189:         $this->setHeader('Cache-Control', 'max-age=' . ($time->format('U') - time()));
190:         $this->setHeader('Expires', self::date($time));
191:         return $this;
192:     }
193: 
194: 
195: 
196:     /**
197:      * Checks if headers have been sent.
198:      * @return bool
199:      */
200:     public function isSent()
201:     {
202:         return headers_sent();
203:     }
204: 
205: 
206: 
207:     /**
208:      * Return the value of the HTTP header.
209:      * @param  string
210:      * @param  mixed
211:      * @return mixed
212:      */
213:     public function getHeader($header, $default = NULL)
214:     {
215:         $header .= ':';
216:         $len = strlen($header);
217:         foreach (headers_list() as $item) {
218:             if (strncasecmp($item, $header, $len) === 0) {
219:                 return ltrim(substr($item, $len));
220:             }
221:         }
222:         return $default;
223:     }
224: 
225: 
226: 
227:     /**
228:      * Returns a list of headers to sent.
229:      * @return array
230:      */
231:     public function getHeaders()
232:     {
233:         $headers = array();
234:         foreach (headers_list() as $header) {
235:             $a = strpos($header, ':');
236:             $headers[substr($header, 0, $a)] = (string) substr($header, $a + 2);
237:         }
238:         return $headers;
239:     }
240: 
241: 
242: 
243:     /**
244:      * Returns HTTP valid date format.
245:      * @param  string|int|DateTime
246:      * @return string
247:      */
248:     public static function date($time = NULL)
249:     {
250:         $time = Nette\DateTime::from($time);
251:         $time->setTimezone(new \DateTimeZone('GMT'));
252:         return $time->format('D, d M Y H:i:s \G\M\T');
253:     }
254: 
255: 
256: 
257:     /**
258:      * @return void
259:      */
260:     public function __destruct()
261:     {
262:         if (self::$fixIE && isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') !== FALSE
263:             && in_array($this->code, array(400, 403, 404, 405, 406, 408, 409, 410, 500, 501, 505), TRUE)
264:             && $this->getHeader('Content-Type', 'text/html') === 'text/html'
265:         ) {
266:             echo Nette\Utils\Strings::random(2e3, " \t\r\n"); // sends invisible garbage for IE
267:             self::$fixIE = FALSE;
268:         }
269:     }
270: 
271: 
272: 
273:     /**
274:      * Sends a cookie.
275:      * @param  string name of the cookie
276:      * @param  string value
277:      * @param  string|int|DateTime  expiration time, value 0 means "until the browser is closed"
278:      * @param  string
279:      * @param  string
280:      * @param  bool
281:      * @param  bool
282:      * @return Response  provides a fluent interface
283:      * @throws Nette\InvalidStateException  if HTTP headers have been sent
284:      */
285:     public function setCookie($name, $value, $time, $path = NULL, $domain = NULL, $secure = NULL, $httpOnly = NULL)
286:     {
287:         if (headers_sent($file, $line)) {
288:             throw new Nette\InvalidStateException("Cannot set cookie after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
289:         }
290: 
291:         setcookie(
292:             $name,
293:             $value,
294:             $time ? Nette\DateTime::from($time)->format('U') : 0,
295:             $path === NULL ? $this->cookiePath : (string) $path,
296:             $domain === NULL ? $this->cookieDomain : (string) $domain,
297:             $secure === NULL ? $this->cookieSecure : (bool) $secure,
298:             $httpOnly === NULL ? $this->cookieHttpOnly : (bool) $httpOnly
299:         );
300: 
301:         $flatten = array();
302:         foreach (headers_list() as $header) {
303:             if (preg_match('#^Set-Cookie: .+?=#', $header, $m)) {
304:                 $flatten[$m[0]] = $header;
305:                 if (PHP_VERSION_ID < 50300) { // multiple deleting due PHP bug #61605
306:                     header('Set-Cookie:');
307:                 } else {
308:                     header_remove('Set-Cookie');
309:                 }
310:             }
311:         }
312:         foreach (array_values($flatten) as $key => $header) {
313:             header($header, $key === 0);
314:         }
315: 
316:         return $this;
317:     }
318: 
319: 
320: 
321:     /**
322:      * Deletes a cookie.
323:      * @param  string name of the cookie.
324:      * @param  string
325:      * @param  string
326:      * @param  bool
327:      * @return void
328:      * @throws Nette\InvalidStateException  if HTTP headers have been sent
329:      */
330:     public function deleteCookie($name, $path = NULL, $domain = NULL, $secure = NULL)
331:     {
332:         $this->setCookie($name, FALSE, 0, $path, $domain, $secure);
333:     }
334: 
335: }
336: 
Nette Framework 2.0.3 API API documentation generated by ApiGen 2.7.0