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:  * URI Syntax (RFC 3986).
 20:  *
 21:  * <pre>
 22:  * http://user:password@nette.org:8042/en/manual.html?name=param#fragment
 23:  * \__/^^^\__________________________/\_____________/^\________/^\______/
 24:  *   |                 |                     |            |         |
 25:  * scheme          authority               path         query    fragment
 26:  * </pre>
 27:  *
 28:  * - authority:   [user[:password]@]host[:port]
 29:  * - hostUri:     http://user:password@nette.org:8042
 30:  *
 31:  * @author     David Grudl
 32:  *
 33:  * @property   string $scheme
 34:  * @property   string $user
 35:  * @property   string $password
 36:  * @property   string $host
 37:  * @property   string $port
 38:  * @property   string $path
 39:  * @property   string $query
 40:  * @property   string $fragment
 41:  * @property-read string $absoluteUri
 42:  * @property-read string $authority
 43:  * @property-read string $hostUri
 44:  */
 45: class Uri extends Nette\FreezableObject
 46: {
 47:     /** @var array */
 48:     public static $defaultPorts = array(
 49:         'http' => 80,
 50:         'https' => 443,
 51:         'ftp' => 21,
 52:         'news' => 119,
 53:         'nntp' => 119,
 54:     );
 55: 
 56:     /** @var string */
 57:     private $scheme = '';
 58: 
 59:     /** @var string */
 60:     private $user = '';
 61: 
 62:     /** @var string */
 63:     private $pass = '';
 64: 
 65:     /** @var string */
 66:     private $host = '';
 67: 
 68:     /** @var int */
 69:     private $port = NULL;
 70: 
 71:     /** @var string */
 72:     private $path = '';
 73: 
 74:     /** @var string */
 75:     private $query = '';
 76: 
 77:     /** @var string */
 78:     private $fragment = '';
 79: 
 80: 
 81: 
 82:     /**
 83:      * @param  string  URL
 84:      * @throws InvalidArgumentException
 85:      */
 86:     public function __construct($uri = NULL)
 87:     {
 88:         if (is_string($uri)) {
 89:             $parts = @parse_url($uri); // @ - is escalated to exception
 90:             if ($parts === FALSE) {
 91:                 throw new \InvalidArgumentException("Malformed or unsupported URI '$uri'.");
 92:             }
 93: 
 94:             foreach ($parts as $key => $val) {
 95:                 $this->$key = $val;
 96:             }
 97: 
 98:             if (!$this->port && isset(self::$defaultPorts[$this->scheme])) {
 99:                 $this->port = self::$defaultPorts[$this->scheme];
100:             }
101: 
102:         } elseif ($uri instanceof self) {
103:             foreach ($this as $key => $val) {
104:                 $this->$key = $uri->$key;
105:             }
106:         }
107:     }
108: 
109: 
110: 
111:     /**
112:      * Sets the scheme part of URI.
113:      * @param  string
114:      * @return Uri  provides a fluent interface
115:      */
116:     public function setScheme($value)
117:     {
118:         $this->updating();
119:         $this->scheme = (string) $value;
120:         return $this;
121:     }
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:     /**
137:      * Sets the user name part of URI.
138:      * @param  string
139:      * @return Uri  provides a fluent interface
140:      */
141:     public function setUser($value)
142:     {
143:         $this->updating();
144:         $this->user = (string) $value;
145:         return $this;
146:     }
147: 
148: 
149: 
150:     /**
151:      * Returns the user name part of URI.
152:      * @return string
153:      */
154:     public function getUser()
155:     {
156:         return $this->user;
157:     }
158: 
159: 
160: 
161:     /**
162:      * Sets the password part of URI.
163:      * @param  string
164:      * @return Uri  provides a fluent interface
165:      */
166:     public function setPassword($value)
167:     {
168:         $this->updating();
169:         $this->pass = (string) $value;
170:         return $this;
171:     }
172: 
173: 
174: 
175:     /**
176:      * Returns the password part of URI.
177:      * @return string
178:      */
179:     public function getPassword()
180:     {
181:         return $this->pass;
182:     }
183: 
184: 
185: 
186:     /**
187:      * @deprecated
188:      */
189:     public function setPass($value)
190:     {
191:         trigger_error(__METHOD__ . '() is deprecated; use setPassword() instead.', E_USER_WARNING);
192:         $this->setPassword($value);
193:     }
194: 
195: 
196: 
197:     /**
198:      * @deprecated
199:      */
200:     public function getPass()
201:     {
202:         trigger_error(__METHOD__ . '() is deprecated; use getPassword() instead.', E_USER_WARNING);
203:         return $this->pass;
204:     }
205: 
206: 
207: 
208:     /**
209:      * Sets the host part of URI.
210:      * @param  string
211:      * @return Uri  provides a fluent interface
212:      */
213:     public function setHost($value)
214:     {
215:         $this->updating();
216:         $this->host = (string) $value;
217:         return $this;
218:     }
219: 
220: 
221: 
222:     /**
223:      * Returns the host part of URI.
224:      * @return string
225:      */
226:     public function getHost()
227:     {
228:         return $this->host;
229:     }
230: 
231: 
232: 
233:     /**
234:      * Sets the port part of URI.
235:      * @param  string
236:      * @return Uri  provides a fluent interface
237:      */
238:     public function setPort($value)
239:     {
240:         $this->updating();
241:         $this->port = (int) $value;
242:         return $this;
243:     }
244: 
245: 
246: 
247:     /**
248:      * Returns the port part of URI.
249:      * @return string
250:      */
251:     public function getPort()
252:     {
253:         return $this->port;
254:     }
255: 
256: 
257: 
258:     /**
259:      * Sets the path part of URI.
260:      * @param  string
261:      * @return Uri  provides a fluent interface
262:      */
263:     public function setPath($value)
264:     {
265:         $this->updating();
266:         $this->path = (string) $value;
267:         return $this;
268:     }
269: 
270: 
271: 
272:     /**
273:      * Returns the path part of URI.
274:      * @return string
275:      */
276:     public function getPath()
277:     {
278:         return $this->path;
279:     }
280: 
281: 
282: 
283:     /**
284:      * Sets the query part of URI.
285:      * @param  string|array
286:      * @return Uri  provides a fluent interface
287:      */
288:     public function setQuery($value)
289:     {
290:         $this->updating();
291:         $this->query = (string) (is_array($value) ? http_build_query($value, '', '&') : $value);
292:         return $this;
293:     }
294: 
295: 
296: 
297:     /**
298:      * Appends the query part of URI.
299:      * @param  string|array
300:      * @return void
301:      */
302:     public function appendQuery($value)
303:     {
304:         $this->updating();
305:         $value = (string) (is_array($value) ? http_build_query($value, '', '&') : $value);
306:         $this->query .= ($this->query === '' || $value === '') ? $value : '&' . $value;
307:     }
308: 
309: 
310: 
311:     /**
312:      * Returns the query part of URI.
313:      * @return string
314:      */
315:     public function getQuery()
316:     {
317:         return $this->query;
318:     }
319: 
320: 
321: 
322:     /**
323:      * Sets the fragment part of URI.
324:      * @param  string
325:      * @return Uri  provides a fluent interface
326:      */
327:     public function setFragment($value)
328:     {
329:         $this->updating();
330:         $this->fragment = (string) $value;
331:         return $this;
332:     }
333: 
334: 
335: 
336:     /**
337:      * Returns the fragment part of URI.
338:      * @return string
339:      */
340:     public function getFragment()
341:     {
342:         return $this->fragment;
343:     }
344: 
345: 
346: 
347:     /**
348:      * Returns the entire URI including query string and fragment.
349:      * @return string
350:      */
351:     public function getAbsoluteUri()
352:     {
353:         return $this->scheme . '://' . $this->getAuthority() . $this->path
354:             . ($this->query === '' ? '' : '?' . $this->query)
355:             . ($this->fragment === '' ? '' : '#' . $this->fragment);
356:     }
357: 
358: 
359: 
360:     /**
361:      * Returns the [user[:pass]@]host[:port] part of URI.
362:      * @return string
363:      */
364:     public function getAuthority()
365:     {
366:         $authority = $this->host;
367:         if ($this->port && isset(self::$defaultPorts[$this->scheme]) && $this->port !== self::$defaultPorts[$this->scheme]) {
368:             $authority .= ':' . $this->port;
369:         }
370: 
371:         if ($this->user !== '' && $this->scheme !== 'http' && $this->scheme !== 'https') {
372:             $authority = $this->user . ($this->pass === '' ? '' : ':' . $this->pass) . '@' . $authority;
373:         }
374: 
375:         return $authority;
376:     }
377: 
378: 
379: 
380:     /**
381:      * Returns the scheme and authority part of URI.
382:      * @return string
383:      */
384:     public function getHostUri()
385:     {
386:         return $this->scheme . '://' . $this->getAuthority();
387:     }
388: 
389: 
390: 
391:     /**
392:      * URI comparsion (this object must be in canonical form).
393:      * @param  string
394:      * @return bool
395:      */
396:     public function isEqual($uri)
397:     {
398:         // compare host + path
399:         $part = self::unescape(strtok($uri, '?#'), '%/');
400:         if (strncmp($part, '//', 2) === 0) { // absolute URI without scheme
401:             if ($part !== '//' . $this->getAuthority() . $this->path) return FALSE;
402: 
403:         } elseif (strncmp($part, '/', 1) === 0) { // absolute path
404:             if ($part !== $this->path) return FALSE;
405: 
406:         } else {
407:             if ($part !== $this->scheme . '://' . $this->getAuthority() . $this->path) return FALSE;
408:         }
409: 
410:         // compare query strings
411:         $part = preg_split('#[&;]#', self::unescape(strtr((string) strtok('?#'), '+', ' '), '%&;=+'));
412:         sort($part);
413:         $query = preg_split('#[&;]#', $this->query);
414:         sort($query);
415:         return $part === $query;
416:     }
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:     /**
435:      * @return string
436:      */
437:     public function __toString()
438:     {
439:         return $this->getAbsoluteUri();
440:     }
441: 
442: 
443: 
444:     /**
445:      * Similar to rawurldecode, but preserve reserved chars encoded.
446:      * @param  string to decode
447:      * @param  string reserved characters
448:      * @return string
449:      */
450:     public static function unescape($s, $reserved = '%;/?:@&=+$,')
451:     {
452:         // reserved (@see RFC 2396) = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
453:         // within a path segment, the characters "/", ";", "=", "?" are reserved
454:         // within a query component, the characters ";", "/", "?", ":", "@", "&", "=", "+", ",", "$" are reserved.
455:         preg_match_all('#(?<=%)[a-f0-9][a-f0-9]#i', $s, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
456:         foreach (array_reverse($matches) as $match) {
457:             $ch = chr(hexdec($match[0][0]));
458:             if (strpos($reserved, $ch) === FALSE) {
459:                 $s = substr_replace($s, $ch, $match[0][1] - 1, 3);
460:             }
461:         }
462:         return $s;
463:     }
464: 
465: }
466: 
Nette Framework 0.9.7 API documentation generated by ApiGen 2.3.0