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

  • NHttpContext
  • NHttpRequest
  • NHttpRequestFactory
  • NHttpResponse
  • NHttpUploadedFile
  • NSession
  • NSessionSection
  • NUrl
  • NUrlScript
  • NUserStorage

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 NHttpResponse extends NObject 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:     /**
 48:      * Sets HTTP response code.
 49:      * @param  int
 50:      * @return NHttpResponse  provides a fluent interface
 51:      * @throws InvalidArgumentException  if code is invalid
 52:      * @throws InvalidStateException  if HTTP headers have been sent
 53:      */
 54:     public function setCode($code)
 55:     {
 56:         $code = (int) $code;
 57: 
 58:         static $allowed = array(
 59:             200=>1, 201=>1, 202=>1, 203=>1, 204=>1, 205=>1, 206=>1,
 60:             300=>1, 301=>1, 302=>1, 303=>1, 304=>1, 307=>1,
 61:             400=>1, 401=>1, 403=>1, 404=>1, 405=>1, 406=>1, 408=>1, 410=>1, 412=>1, 415=>1, 416=>1,
 62:             500=>1, 501=>1, 503=>1, 505=>1
 63:         );
 64: 
 65:         if (!isset($allowed[$code])) {
 66:             throw new InvalidArgumentException("Bad HTTP response '$code'.");
 67: 
 68:         } elseif (headers_sent($file, $line)) {
 69:             throw new InvalidStateException("Cannot set HTTP code after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
 70: 
 71:         } else {
 72:             $this->code = $code;
 73:             $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
 74:             header($protocol . ' ' . $code, TRUE, $code);
 75:         }
 76:         return $this;
 77:     }
 78: 
 79: 
 80: 
 81:     /**
 82:      * Returns HTTP response code.
 83:      * @return int
 84:      */
 85:     public function getCode()
 86:     {
 87:         return $this->code;
 88:     }
 89: 
 90: 
 91: 
 92:     /**
 93:      * Sends a HTTP header and replaces a previous one.
 94:      * @param  string  header name
 95:      * @param  string  header value
 96:      * @return NHttpResponse  provides a fluent interface
 97:      * @throws InvalidStateException  if HTTP headers have been sent
 98:      */
 99:     public function setHeader($name, $value)
100:     {
101:         if (headers_sent($file, $line)) {
102:             throw new InvalidStateException("Cannot send header after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
103:         }
104: 
105:         if ($value === NULL && function_exists('header_remove')) {
106:             header_remove($name);
107:         } elseif (strcasecmp($name, 'Content-Length') === 0 && ini_get('zlib.output_compression')) {
108:             // ignore, PHP bug #44164
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 NHttpResponse  provides a fluent interface
122:      * @throws InvalidStateException  if HTTP headers have been sent
123:      */
124:     public function addHeader($name, $value)
125:     {
126:         if (headers_sent($file, $line)) {
127:             throw new 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 NHttpResponse  provides a fluent interface
141:      * @throws 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 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 NHttpResponse  provides a fluent interface
178:      * @throws 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 = NDateTime53::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 = NDateTime53::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 NStrings::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 NHttpResponse  provides a fluent interface
283:      * @throws 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 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 ? NDateTime53::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:         $this->removeDuplicateCookies();
302:         return $this;
303:     }
304: 
305: 
306: 
307:     /**
308:      * Removes duplicate cookies from response.
309:      * @return void
310:      */
311:     public function removeDuplicateCookies()
312:     {
313:         if (headers_sent($file, $line) || ini_get('suhosin.cookie.encrypt')) {
314:             return;
315:         }
316: 
317:         $flatten = array();
318:         foreach (headers_list() as $header) {
319:             if (preg_match('#^Set-Cookie: .+?=#', $header, $m)) {
320:                 $flatten[$m[0]] = $header;
321:                 if (PHP_VERSION_ID < 50300) { // multiple deleting due PHP bug #61605
322:                     header('Set-Cookie:');
323:                 } else {
324:                     header_remove('Set-Cookie');
325:                 }
326:             }
327:         }
328:         foreach (array_values($flatten) as $key => $header) {
329:             header($header, $key === 0);
330:         }
331:     }
332: 
333: 
334: 
335:     /**
336:      * Deletes a cookie.
337:      * @param  string name of the cookie.
338:      * @param  string
339:      * @param  string
340:      * @param  bool
341:      * @return void
342:      * @throws InvalidStateException  if HTTP headers have been sent
343:      */
344:     public function deleteCookie($name, $path = NULL, $domain = NULL, $secure = NULL)
345:     {
346:         $this->setCookie($name, FALSE, 0, $path, $domain, $secure);
347:     }
348: 
349: }
350: 
Nette Framework 2.0.7 (for PHP 5.2, prefixed) API API documentation generated by ApiGen 2.8.0