Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

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