Namespaces

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

Classes

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

Interfaces

  • IRequest
  • IResponse
  • ISessionStorage
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Http;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * URI Syntax (RFC 3986).
 15:  *
 16:  * <pre>
 17:  * scheme  user  password  host  port  basePath   relativeUrl
 18:  *   |      |      |        |      |    |             |
 19:  * /--\   /--\ /------\ /-------\ /--\/--\/----------------------------\
 20:  * http://john:x0y17575@nette.org:8042/en/manual.php?name=param#fragment  <-- absoluteUrl
 21:  *        \__________________________/\____________/^\________/^\______/
 22:  *                     |                     |           |         |
 23:  *                 authority               path        query    fragment
 24:  * </pre>
 25:  *
 26:  * - authority:   [user[:password]@]host[:port]
 27:  * - hostUrl:     http://user:password@nette.org:8042
 28:  * - basePath:    /en/ (everything before relative URI not including the script name)
 29:  * - baseUrl:     http://user:password@nette.org:8042/en/
 30:  * - relativeUrl: manual.php
 31:  *
 32:  * @author     David Grudl
 33:  *
 34:  * @property   string $scheme
 35:  * @property   string $user
 36:  * @property   string $password
 37:  * @property   string $host
 38:  * @property   string $port
 39:  * @property   string $path
 40:  * @property   string $query
 41:  * @property   string $fragment
 42:  * @property-read string $absoluteUrl
 43:  * @property-read string $authority
 44:  * @property-read string $hostUrl
 45:  * @property-read string $basePath
 46:  * @property-read string $baseUrl
 47:  * @property-read string $relativeUrl
 48:  */
 49: class Url extends Nette\Object
 50: {
 51:     /** @var array */
 52:     public static $defaultPorts = array(
 53:         'http' => 80,
 54:         'https' => 443,
 55:         'ftp' => 21,
 56:         'news' => 119,
 57:         'nntp' => 119,
 58:     );
 59: 
 60:     /** @var string */
 61:     private $scheme = '';
 62: 
 63:     /** @var string */
 64:     private $user = '';
 65: 
 66:     /** @var string */
 67:     private $pass = '';
 68: 
 69:     /** @var string */
 70:     private $host = '';
 71: 
 72:     /** @var int */
 73:     private $port = NULL;
 74: 
 75:     /** @var string */
 76:     private $path = '';
 77: 
 78:     /** @var string */
 79:     private $query = '';
 80: 
 81:     /** @var string */
 82:     private $fragment = '';
 83: 
 84: 
 85:     /**
 86:      * @param  string|self
 87:      * @throws Nette\InvalidArgumentException if URL is malformed
 88:      */
 89:     public function __construct($url = NULL)
 90:     {
 91:         if (is_string($url)) {
 92:             $parts = @parse_url($url); // @ - is escalated to exception
 93:             if ($parts === FALSE) {
 94:                 throw new Nette\InvalidArgumentException("Malformed or unsupported URI '$url'.");
 95:             }
 96: 
 97:             foreach ($parts as $key => $val) {
 98:                 $this->$key = $val;
 99:             }
100: 
101:             if (!$this->port && isset(self::$defaultPorts[$this->scheme])) {
102:                 $this->port = self::$defaultPorts[$this->scheme];
103:             }
104: 
105:             if ($this->path === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
106:                 $this->path = '/';
107:             }
108: 
109:         } elseif ($url instanceof self) {
110:             foreach ($this as $key => $val) {
111:                 $this->$key = $url->$key;
112:             }
113:         }
114:     }
115: 
116: 
117:     /**
118:      * Sets the scheme part of URI.
119:      * @param  string
120:      * @return self
121:      */
122:     public function setScheme($value)
123:     {
124:         $this->scheme = (string) $value;
125:         return $this;
126:     }
127: 
128: 
129:     /**
130:      * Returns the scheme part of URI.
131:      * @return string
132:      */
133:     public function getScheme()
134:     {
135:         return $this->scheme;
136:     }
137: 
138: 
139:     /**
140:      * Sets the user name part of URI.
141:      * @param  string
142:      * @return self
143:      */
144:     public function setUser($value)
145:     {
146:         $this->user = (string) $value;
147:         return $this;
148:     }
149: 
150: 
151:     /**
152:      * Returns the user name part of URI.
153:      * @return string
154:      */
155:     public function getUser()
156:     {
157:         return $this->user;
158:     }
159: 
160: 
161:     /**
162:      * Sets the password part of URI.
163:      * @param  string
164:      * @return self
165:      */
166:     public function setPassword($value)
167:     {
168:         $this->pass = (string) $value;
169:         return $this;
170:     }
171: 
172: 
173:     /**
174:      * Returns the password part of URI.
175:      * @return string
176:      */
177:     public function getPassword()
178:     {
179:         return $this->pass;
180:     }
181: 
182: 
183:     /**
184:      * Sets the host part of URI.
185:      * @param  string
186:      * @return self
187:      */
188:     public function setHost($value)
189:     {
190:         $this->host = (string) $value;
191:         return $this;
192:     }
193: 
194: 
195:     /**
196:      * Returns the host part of URI.
197:      * @return string
198:      */
199:     public function getHost()
200:     {
201:         return $this->host;
202:     }
203: 
204: 
205:     /**
206:      * Sets the port part of URI.
207:      * @param  string
208:      * @return self
209:      */
210:     public function setPort($value)
211:     {
212:         $this->port = (int) $value;
213:         return $this;
214:     }
215: 
216: 
217:     /**
218:      * Returns the port part of URI.
219:      * @return string
220:      */
221:     public function getPort()
222:     {
223:         return $this->port;
224:     }
225: 
226: 
227:     /**
228:      * Sets the path part of URI.
229:      * @param  string
230:      * @return self
231:      */
232:     public function setPath($value)
233:     {
234:         $this->path = (string) $value;
235:         return $this;
236:     }
237: 
238: 
239:     /**
240:      * Returns the path part of URI.
241:      * @return string
242:      */
243:     public function getPath()
244:     {
245:         return $this->path;
246:     }
247: 
248: 
249:     /**
250:      * Sets the query part of URI.
251:      * @param  string|array
252:      * @return self
253:      */
254:     public function setQuery($value)
255:     {
256:         $this->query = (string) (is_array($value) ? http_build_query($value, '', '&') : $value);
257:         return $this;
258:     }
259: 
260: 
261:     /**
262:      * Appends the query part of URI.
263:      * @param  string|array
264:      * @return self
265:      */
266:     public function appendQuery($value)
267:     {
268:         $value = (string) (is_array($value) ? http_build_query($value, '', '&') : $value);
269:         $this->query .= ($this->query === '' || $value === '') ? $value : '&' . $value;
270:         return $this;
271:     }
272: 
273: 
274:     /**
275:      * Returns the query part of URI.
276:      * @return string
277:      */
278:     public function getQuery()
279:     {
280:         return $this->query;
281:     }
282: 
283: 
284:     /**
285:      * @param string
286:      * @param mixed
287:      * @return mixed
288:      */
289:     public function getQueryParameter($name, $default = NULL)
290:     {
291:         parse_str($this->query, $params);
292:         return isset($params[$name]) ? $params[$name] : $default;
293:     }
294: 
295: 
296:     /**
297:      * @param string
298:      * @param mixed NULL unsets the parameter
299:      * @return self
300:      */
301:     public function setQueryParameter($name, $value)
302:     {
303:         parse_str($this->query, $params);
304:         if ($value === NULL) {
305:             unset($params[$name]);
306:         } else {
307:             $params[$name] = $value;
308:         }
309:         $this->setQuery($params);
310:         return $this;
311:     }
312: 
313: 
314:     /**
315:      * Sets the fragment part of URI.
316:      * @param  string
317:      * @return self
318:      */
319:     public function setFragment($value)
320:     {
321:         $this->fragment = (string) $value;
322:         return $this;
323:     }
324: 
325: 
326:     /**
327:      * Returns the fragment part of URI.
328:      * @return string
329:      */
330:     public function getFragment()
331:     {
332:         return $this->fragment;
333:     }
334: 
335: 
336:     /**
337:      * Returns the entire URI including query string and fragment.
338:      * @return string
339:      */
340:     public function getAbsoluteUrl()
341:     {
342:         return $this->getHostUrl() . $this->path
343:             . ($this->query === '' ? '' : '?' . $this->query)
344:             . ($this->fragment === '' ? '' : '#' . $this->fragment);
345:     }
346: 
347: 
348:     /**
349:      * Returns the [user[:pass]@]host[:port] part of URI.
350:      * @return string
351:      */
352:     public function getAuthority()
353:     {
354:         $authority = $this->host;
355:         if ($this->port && (!isset(self::$defaultPorts[$this->scheme]) || $this->port !== self::$defaultPorts[$this->scheme])) {
356:             $authority .= ':' . $this->port;
357:         }
358: 
359:         if ($this->user !== '' && $this->scheme !== 'http' && $this->scheme !== 'https') {
360:             $authority = $this->user . ($this->pass === '' ? '' : ':' . $this->pass) . '@' . $authority;
361:         }
362: 
363:         return $authority;
364:     }
365: 
366: 
367:     /**
368:      * Returns the scheme and authority part of URI.
369:      * @return string
370:      */
371:     public function getHostUrl()
372:     {
373:         return ($this->scheme ? $this->scheme . ':' : '') . '//' . $this->getAuthority();
374:     }
375: 
376: 
377:     /**
378:      * Returns the base-path.
379:      * @return string
380:      */
381:     public function getBasePath()
382:     {
383:         $pos = strrpos($this->path, '/');
384:         return $pos === FALSE ? '' : substr($this->path, 0, $pos + 1);
385:     }
386: 
387: 
388:     /**
389:      * Returns the base-URI.
390:      * @return string
391:      */
392:     public function getBaseUrl()
393:     {
394:         return $this->getHostUrl() . $this->getBasePath();
395:     }
396: 
397: 
398:     /**
399:      * Returns the relative-URI.
400:      * @return string
401:      */
402:     public function getRelativeUrl()
403:     {
404:         return (string) substr($this->getAbsoluteUrl(), strlen($this->getBaseUrl()));
405:     }
406: 
407: 
408:     /**
409:      * URL comparison.
410:      * @param  string|self
411:      * @return bool
412:      */
413:     public function isEqual($url)
414:     {
415:         $url = new self($url);
416:         parse_str($url->query, $query);
417:         ksort($query);
418:         parse_str($this->query, $query2);
419:         ksort($query2);
420:         $http = in_array($this->scheme, array('http', 'https'), TRUE);
421:         return $url->scheme === $this->scheme
422:             && !strcasecmp(rawurldecode($url->host), rawurldecode($this->host))
423:             && $url->port === $this->port
424:             && ($http || rawurldecode($url->user) === rawurldecode($this->user))
425:             && ($http || rawurldecode($url->pass) === rawurldecode($this->pass))
426:             && self::unescape($url->path, '%/') === self::unescape($this->path, '%/')
427:             && $query === $query2
428:             && rawurldecode($url->fragment) === rawurldecode($this->fragment);
429:     }
430: 
431: 
432:     /**
433:      * Transforms URL to canonical form.
434:      * @return self
435:      */
436:     public function canonicalize()
437:     {
438:         $this->path = $this->path === '' ? '/' : self::unescape($this->path, '%/#?');
439:         $this->host = strtolower(rawurldecode($this->host));
440:         $this->query = self::unescape(strtr($this->query, '+', ' '), '%&;=+#');
441:         return $this;
442:     }
443: 
444: 
445:     /**
446:      * @return string
447:      */
448:     public function __toString()
449:     {
450:         return $this->getAbsoluteUrl();
451:     }
452: 
453: 
454:     /**
455:      * Similar to rawurldecode, but preserves reserved chars encoded.
456:      * @param  string to decode
457:      * @param  string reserved characters
458:      * @return string
459:      */
460:     public static function unescape($s, $reserved = '%;/?:@&=+$,')
461:     {
462:         // reserved (@see RFC 2396) = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
463:         // within a path segment, the characters "/", ";", "=", "?" are reserved
464:         // within a query component, the characters ";", "/", "?", ":", "@", "&", "=", "+", ",", "$" are reserved.
465:         if ($reserved !== '') {
466:             $s = preg_replace(
467:                 '#%(' . substr(chunk_split(bin2hex($reserved), 2, '|'), 0, -1) . ')#i',
468:                 '%25$1',
469:                 $s
470:             );
471:         }
472:         return rawurldecode($s);
473:     }
474: 
475: }
476: 
Nette 2.1 API documentation generated by ApiGen 2.8.0