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

Classes

  • Context
  • FileUpload
  • 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 (http://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\FreezableObject
 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  URL
 87:      * @throws Nette\InvalidArgumentException
 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->updating();
125:         $this->scheme = (string) $value;
126:         return $this;
127:     }
128: 
129: 
130:     /**
131:      * Returns the scheme part of URI.
132:      * @return string
133:      */
134:     public function getScheme()
135:     {
136:         return $this->scheme;
137:     }
138: 
139: 
140:     /**
141:      * Sets the user name part of URI.
142:      * @param  string
143:      * @return self
144:      */
145:     public function setUser($value)
146:     {
147:         $this->updating();
148:         $this->user = (string) $value;
149:         return $this;
150:     }
151: 
152: 
153:     /**
154:      * Returns the user name part of URI.
155:      * @return string
156:      */
157:     public function getUser()
158:     {
159:         return $this->user;
160:     }
161: 
162: 
163:     /**
164:      * Sets the password part of URI.
165:      * @param  string
166:      * @return self
167:      */
168:     public function setPassword($value)
169:     {
170:         $this->updating();
171:         $this->pass = (string) $value;
172:         return $this;
173:     }
174: 
175: 
176:     /**
177:      * Returns the password part of URI.
178:      * @return string
179:      */
180:     public function getPassword()
181:     {
182:         return $this->pass;
183:     }
184: 
185: 
186:     /**
187:      * Sets the host part of URI.
188:      * @param  string
189:      * @return self
190:      */
191:     public function setHost($value)
192:     {
193:         $this->updating();
194:         $this->host = (string) $value;
195:         return $this;
196:     }
197: 
198: 
199:     /**
200:      * Returns the host part of URI.
201:      * @return string
202:      */
203:     public function getHost()
204:     {
205:         return $this->host;
206:     }
207: 
208: 
209:     /**
210:      * Sets the port part of URI.
211:      * @param  string
212:      * @return self
213:      */
214:     public function setPort($value)
215:     {
216:         $this->updating();
217:         $this->port = (int) $value;
218:         return $this;
219:     }
220: 
221: 
222:     /**
223:      * Returns the port part of URI.
224:      * @return string
225:      */
226:     public function getPort()
227:     {
228:         return $this->port;
229:     }
230: 
231: 
232:     /**
233:      * Sets the path part of URI.
234:      * @param  string
235:      * @return self
236:      */
237:     public function setPath($value)
238:     {
239:         $this->updating();
240:         $this->path = (string) $value;
241:         return $this;
242:     }
243: 
244: 
245:     /**
246:      * Returns the path part of URI.
247:      * @return string
248:      */
249:     public function getPath()
250:     {
251:         return $this->path;
252:     }
253: 
254: 
255:     /**
256:      * Sets the query part of URI.
257:      * @param  string|array
258:      * @return self
259:      */
260:     public function setQuery($value)
261:     {
262:         $this->updating();
263:         $this->query = (string) (is_array($value) ? http_build_query($value, '', '&') : $value);
264:         return $this;
265:     }
266: 
267: 
268:     /**
269:      * Appends the query part of URI.
270:      * @param  string|array
271:      * @return void
272:      */
273:     public function appendQuery($value)
274:     {
275:         $this->updating();
276:         $value = (string) (is_array($value) ? http_build_query($value, '', '&') : $value);
277:         $this->query .= ($this->query === '' || $value === '') ? $value : '&' . $value;
278:     }
279: 
280: 
281:     /**
282:      * Returns the query part of URI.
283:      * @return string
284:      */
285:     public function getQuery()
286:     {
287:         return $this->query;
288:     }
289: 
290: 
291:     /**
292:      * Sets the fragment part of URI.
293:      * @param  string
294:      * @return self
295:      */
296:     public function setFragment($value)
297:     {
298:         $this->updating();
299:         $this->fragment = (string) $value;
300:         return $this;
301:     }
302: 
303: 
304:     /**
305:      * Returns the fragment part of URI.
306:      * @return string
307:      */
308:     public function getFragment()
309:     {
310:         return $this->fragment;
311:     }
312: 
313: 
314:     /**
315:      * Returns the entire URI including query string and fragment.
316:      * @return string
317:      */
318:     public function getAbsoluteUrl()
319:     {
320:         return $this->getHostUrl() . $this->path
321:             . ($this->query === '' ? '' : '?' . $this->query)
322:             . ($this->fragment === '' ? '' : '#' . $this->fragment);
323:     }
324: 
325: 
326:     /**
327:      * Returns the [user[:pass]@]host[:port] part of URI.
328:      * @return string
329:      */
330:     public function getAuthority()
331:     {
332:         $authority = $this->host;
333:         if ($this->port && (!isset(self::$defaultPorts[$this->scheme]) || $this->port !== self::$defaultPorts[$this->scheme])) {
334:             $authority .= ':' . $this->port;
335:         }
336: 
337:         if ($this->user !== '' && $this->scheme !== 'http' && $this->scheme !== 'https') {
338:             $authority = $this->user . ($this->pass === '' ? '' : ':' . $this->pass) . '@' . $authority;
339:         }
340: 
341:         return $authority;
342:     }
343: 
344: 
345:     /**
346:      * Returns the scheme and authority part of URI.
347:      * @return string
348:      */
349:     public function getHostUrl()
350:     {
351:         return ($this->scheme ? $this->scheme . ':' : '') . '//' . $this->getAuthority();
352:     }
353: 
354: 
355:     /**
356:      * Returns the base-path.
357:      * @return string
358:      */
359:     public function getBasePath()
360:     {
361:         $pos = strrpos($this->path, '/');
362:         return $pos === FALSE ? '' : substr($this->path, 0, $pos + 1);
363:     }
364: 
365: 
366:     /**
367:      * Returns the base-URI.
368:      * @return string
369:      */
370:     public function getBaseUrl()
371:     {
372:         return $this->getHostUrl() . $this->getBasePath();
373:     }
374: 
375: 
376:     /**
377:      * Returns the relative-URI.
378:      * @return string
379:      */
380:     public function getRelativeUrl()
381:     {
382:         return (string) substr($this->getAbsoluteUrl(), strlen($this->getBaseUrl()));
383:     }
384: 
385: 
386:     /**
387:      * URI comparsion (this object must be in canonical form).
388:      * @param  string
389:      * @return bool
390:      */
391:     public function isEqual($url)
392:     {
393:         // compare host + path
394:         $part = self::unescape(strtok($url, '?#'), '%/');
395:         if (strncmp($part, '//', 2) === 0) { // absolute URI without scheme
396:             if ($part !== '//' . $this->getAuthority() . $this->path) {
397:                 return FALSE;
398:             }
399: 
400:         } elseif (strncmp($part, '/', 1) === 0) { // absolute path
401:             if ($part !== $this->path) {
402:                 return FALSE;
403:             }
404: 
405:         } else {
406:             if ($part !== $this->getHostUrl() . $this->path) {
407:                 return FALSE;
408:             }
409:         }
410: 
411:         // compare query strings
412:         $part = preg_split('#[&;]#', self::unescape(strtr((string) strtok('?#'), '+', ' '), '%&;=+'));
413:         sort($part);
414:         $query = preg_split('#[&;]#', $this->query);
415:         sort($query);
416:         return $part === $query;
417:     }
418: 
419: 
420:     /**
421:      * Transform to canonical form.
422:      * @return void
423:      */
424:     public function canonicalize()
425:     {
426:         $this->updating();
427:         $this->path = $this->path === '' ? '/' : self::unescape($this->path, '%/');
428:         $this->host = strtolower(rawurldecode($this->host));
429:         $this->query = self::unescape(strtr($this->query, '+', ' '), '%&;=+');
430:     }
431: 
432: 
433:     /**
434:      * @return string
435:      */
436:     public function __toString()
437:     {
438:         return $this->getAbsoluteUrl();
439:     }
440: 
441: 
442:     /**
443:      * Similar to rawurldecode, but preserve reserved chars encoded.
444:      * @param  string to decode
445:      * @param  string reserved characters
446:      * @return string
447:      */
448:     public static function unescape($s, $reserved = '%;/?:@&=+$,')
449:     {
450:         // reserved (@see RFC 2396) = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
451:         // within a path segment, the characters "/", ";", "=", "?" are reserved
452:         // within a query component, the characters ";", "/", "?", ":", "@", "&", "=", "+", ",", "$" are reserved.
453:         preg_match_all('#(?<=%)[a-f0-9][a-f0-9]#i', $s, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
454:         foreach (array_reverse($matches) as $match) {
455:             $ch = chr(hexdec($match[0][0]));
456:             if (strpos($reserved, $ch) === FALSE) {
457:                 $s = substr_replace($s, $ch, $match[0][1] - 1, 3);
458:             }
459:         }
460:         return $s;
461:     }
462: 
463: 
464:     /** @deprecated */
465:     function getRelativeUri()
466:     {
467:         trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::getRelativeUrl() instead.', E_USER_WARNING);
468:         return $this->getRelativeUrl();
469:     }
470: 
471:     /** @deprecated */
472:     function getAbsoluteUri()
473:     {
474:         trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::getAbsoluteUrl() instead.', E_USER_WARNING);
475:         return $this->getAbsoluteUrl();
476:     }
477: 
478:     /** @deprecated */
479:     function getHostUri()
480:     {
481:         trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::getHostUrl() instead.', E_USER_WARNING);
482:         return $this->getHostUrl();
483:     }
484: 
485:     /** @deprecated */
486:     function getBaseUri()
487:     {
488:         trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::getBaseUrl() instead.', E_USER_WARNING);
489:         return $this->getBaseUrl();
490:     }
491: 
492: }
493: 
Nette 2.0 API documentation generated by ApiGen 2.8.0