Namespaces

  • Nette
    • Application
    • Caching
    • Collections
    • Config
    • Forms
    • IO
    • Loaders
    • Mail
    • Reflection
    • Security
    • Templates
    • Web
  • None
  • PHP

Classes

  • Ftp
  • Html
  • HttpContext
  • HttpRequest
  • HttpResponse
  • HttpUploadedFile
  • Session
  • SessionNamespace
  • Uri
  • UriScript
  • User

Interfaces

  • IHttpRequest
  • IHttpResponse
  • IUser

Exceptions

  • FtpException
  • Overview
  • Namespace
  • Class
  • Tree
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://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\Web;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18: /**
 19:  * HttpResponse class.
 20:  *
 21:  * @author     David Grudl
 22:  *
 23:  * @property   int $code
 24:  * @property-read array $headers
 25:  * @property-read mixed $sent
 26:  */
 27: final class HttpResponse extends Nette\Object implements IHttpResponse
 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 The path in which the cookie will be available */
 39:     public $cookieSecure = FALSE;
 40: 
 41:     /** @var int HTTP response code */
 42:     private $code = self::S200_OK;
 43: 
 44: 
 45: 
 46:     /**
 47:      * Sets HTTP response code.
 48:      * @param  int
 49:      * @return HttpResponse  provides a fluent interface
 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, 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:     /**
 81:      * Returns HTTP response code.
 82:      * @return int
 83:      */
 84:     public function getCode()
 85:     {
 86:         return $this->code;
 87:     }
 88: 
 89: 
 90: 
 91:     /**
 92:      * Sends a HTTP header and replaces a previous one.
 93:      * @param  string  header name
 94:      * @param  string  header value
 95:      * @return HttpResponse  provides a fluent interface
 96:      * @throws \InvalidStateException  if HTTP headers have been sent
 97:      */
 98:     public function setHeader($name, $value)
 99:     {
100:         if (headers_sent($file, $line)) {
101:             throw new \InvalidStateException("Cannot send header after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
102:         }
103: 
104:         if ($value === NULL && function_exists('header_remove')) {
105:             header_remove($name);
106:         } else {
107:             header($name . ': ' . $value, TRUE, $this->code);
108:         }
109:         return $this;
110:     }
111: 
112: 
113: 
114:     /**
115:      * Adds HTTP header.
116:      * @param  string  header name
117:      * @param  string  header value
118:      * @return void
119:      * @throws \InvalidStateException  if HTTP headers have been sent
120:      */
121:     public function addHeader($name, $value)
122:     {
123:         if (headers_sent($file, $line)) {
124:             throw new \InvalidStateException("Cannot send header after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
125:         }
126: 
127:         header($name . ': ' . $value, FALSE, $this->code);
128:     }
129: 
130: 
131: 
132:     /**
133:      * Sends a Content-type HTTP header.
134:      * @param  string  mime-type
135:      * @param  string  charset
136:      * @return HttpResponse  provides a fluent interface
137:      * @throws \InvalidStateException  if HTTP headers have been sent
138:      */
139:     public function setContentType($type, $charset = NULL)
140:     {
141:         $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
142:         return $this;
143:     }
144: 
145: 
146: 
147:     /**
148:      * Redirects to a new URL. Note: call exit() after it.
149:      * @param  string  URL
150:      * @param  int     HTTP code
151:      * @return void
152:      * @throws \InvalidStateException  if HTTP headers have been sent
153:      */
154:     public function redirect($url, $code = self::S302_FOUND)
155:     {
156:         if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('#^Microsoft-IIS/[1-5]#', $_SERVER['SERVER_SOFTWARE']) && $this->getHeader('Set-Cookie') !== NULL) {
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:     /**
169:      * Sets the number of seconds before a page cached on a browser expires.
170:      * @param  string|int|DateTime  time, value 0 means "until the browser is closed"
171:      * @return HttpResponse  provides a fluent interface
172:      * @throws \InvalidStateException  if HTTP headers have been sent
173:      */
174:     public function setExpiration($time)
175:     {
176:         if (!$time) { // no cache
177:             $this->setHeader('Cache-Control', 's-maxage=0, max-age=0, must-revalidate');
178:             $this->setHeader('Expires', 'Mon, 23 Jan 1978 10:00:00 GMT');
179:             return $this;
180:         }
181: 
182:         $time = Nette\DateTime::from($time);
183:         $this->setHeader('Cache-Control', 'max-age=' . ($time->format('U') - time()));
184:         $this->setHeader('Expires', self::date($time));
185:         return $this;
186:     }
187: 
188: 
189: 
190:     /** @deprecated */
191:     public function expire($seconds)
192:     {
193:         trigger_error(__METHOD__ . '() is deprecated; use setExpiration() instead.', E_USER_WARNING);
194:         $this->setExpiration($seconds);
195:     }
196: 
197: 
198: 
199:     /**
200:      * Checks if headers have been sent.
201:      * @return bool
202:      */
203:     public function isSent()
204:     {
205:         return headers_sent();
206:     }
207: 
208: 
209: 
210:     /**
211:      * Return the value of the HTTP header.
212:      * @param  string
213:      * @param  mixed
214:      * @return mixed
215:      */
216:     public function getHeader($header, $default = NULL)
217:     {
218:         $header .= ':';
219:         $len = strlen($header);
220:         foreach (headers_list() as $item) {
221:             if (strncasecmp($item, $header, $len) === 0) {
222:                 return ltrim(substr($item, $len));
223:             }
224:         }
225:         return $default;
226:     }
227: 
228: 
229: 
230:     /**
231:      * Returns a list of headers to sent.
232:      * @return array
233:      */
234:     public function getHeaders()
235:     {
236:         $headers = array();
237:         foreach (headers_list() as $header) {
238:             $a = strpos($header, ':');
239:             $headers[substr($header, 0, $a)] = (string) substr($header, $a + 2);
240:         }
241:         return $headers;
242:     }
243: 
244: 
245: 
246:     /**
247:      * Returns HTTP valid date format.
248:      * @param  string|int|DateTime
249:      * @return string
250:      */
251:     public static function date($time = NULL)
252:     {
253:         $time = Nette\DateTime::from($time);
254:         $time->setTimezone(new \DateTimeZone('GMT'));
255:         return $time->format('D, d M Y H:i:s \G\M\T');
256:     }
257: 
258: 
259: 
260:     /**
261:      * Enables compression. (warning: may not work)
262:      * @return bool
263:      */
264:     public function enableCompression()
265:     {
266:         if (headers_sent()) {
267:             return FALSE;
268:         }
269: 
270:         if ($this->getHeader('Content-Encoding') !== NULL) {
271:             return FALSE; // called twice
272:         }
273: 
274:         $ok = ob_gzhandler('', PHP_OUTPUT_HANDLER_START);
275:         if ($ok === FALSE) {
276:             return FALSE; // not allowed
277:         }
278: 
279:         if (function_exists('ini_set')) {
280:             ini_set('zlib.output_compression', 'Off');
281:             ini_set('zlib.output_compression_level', '6');
282:         }
283:         ob_start('ob_gzhandler', 1);
284:         return TRUE;
285:     }
286: 
287: 
288: 
289:     /**
290:      * @return void
291:      */
292:     public function __destruct()
293:     {
294:         if (self::$fixIE) {
295:             // Sends invisible garbage for IE.
296:             if (!isset($_SERVER['HTTP_USER_AGENT']) || strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') === FALSE) return;
297:             if (!in_array($this->code, array(400, 403, 404, 405, 406, 408, 409, 410, 500, 501, 505), TRUE)) return;
298:             if ($this->getHeader('Content-Type', 'text/html') !== 'text/html') return;
299:             $s = " \t\r\n";
300:             for ($i = 2e3; $i; $i--) echo $s{rand(0, 3)};
301:             self::$fixIE = FALSE;
302:         }
303:     }
304: 
305: 
306: 
307:     /**
308:      * Sends a cookie.
309:      * @param  string name of the cookie
310:      * @param  string value
311:      * @param  string|int|DateTime  expiration time, value 0 means "until the browser is closed"
312:      * @param  string
313:      * @param  string
314:      * @param  bool
315:      * @return HttpResponse  provides a fluent interface
316:      * @throws \InvalidStateException  if HTTP headers have been sent
317:      */
318:     public function setCookie($name, $value, $time, $path = NULL, $domain = NULL, $secure = NULL)
319:     {
320:         if (headers_sent($file, $line)) {
321:             throw new \InvalidStateException("Cannot set cookie after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
322:         }
323: 
324:         setcookie(
325:             $name,
326:             $value,
327:             $time ? Nette\DateTime::from($time)->format('U') : 0,
328:             $path === NULL ? $this->cookiePath : (string) $path,
329:             $domain === NULL ? $this->cookieDomain : (string) $domain, //  . '; httponly'
330:             $secure === NULL ? $this->cookieSecure : (bool) $secure,
331:             TRUE // added in PHP 5.2.0.
332:         );
333:         return $this;
334:     }
335: 
336: 
337: 
338:     /**
339:      * Deletes a cookie.
340:      * @param  string name of the cookie.
341:      * @param  string
342:      * @param  string
343:      * @param  bool
344:      * @return void
345:      * @throws \InvalidStateException  if HTTP headers have been sent
346:      */
347:     public function deleteCookie($name, $path = NULL, $domain = NULL, $secure = NULL)
348:     {
349:         if (headers_sent($file, $line)) {
350:             throw new \InvalidStateException("Cannot delete cookie after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
351:         }
352: 
353:         setcookie(
354:             $name,
355:             FALSE,
356:             254400000,
357:             $path === NULL ? $this->cookiePath : (string) $path,
358:             $domain === NULL ? $this->cookieDomain : (string) $domain, //  . '; httponly'
359:             $secure === NULL ? $this->cookieSecure : (bool) $secure,
360:             TRUE // added in PHP 5.2.0.
361:         );
362:     }
363: 
364: }
365: 
Nette Framework 0.9.7 API documentation generated by ApiGen 2.3.0