3v4l.org

run code in 150+ php & hhvm versions
Bugs & Features
<?php /** * PHP library for working with URI's. Requires * PHP 5.3.7 or later. Replaces and extends PHP's * parse_url() * * Based on P Guardiario's original work * * @author Nicholas Jordon * @copyright 2014 Nicholas Jordon - All Rights Reserved * @license http://opensource.org/licenses/MIT * @version 0.1.0 */ /** * PHP URI */ class uri { /*** Variables ***/ public $input; public $scheme; public $protocol; public $scheme_name; public $user; public $username; public $pass; public $password; public $host; public $fqdn; public $port; public $authority; public $path; public $query; public $fragment; public $error; public $error_msg; /*** Methods ***/ public function __construct($input) { $t = $this; $t->input = $input; $t->error = FALSE; $t->protocol = &$this->scheme; $t->username = &$this->user; $t->password = &$this->pass; $t->fqdn = &$this->host; if (!is_string($input)) { $t->error = TRUE; $t->error_msg = 'Input was not a string!'; $t->scheme = FALSE; $t->scheme_name = FALSE; $t->user = FALSE; $t->pass = FALSE; $t->host = FALSE; $t->port = FALSE; $t->authority = FALSE; $t->path = FALSE; $t->query = FALSE; $t->fragment = FALSE; } else { $this->parse($input); } } protected function parse($uri) { if ($this->error) { return FALSE; } $t = $this; $parsed = $t->_parse((string) $uri); if (empty($parsed)) { $t->error = TRUE; $t->error = 'Could not parse the input as a URI'; return $parsed; } $defaults = array( 'scheme' => '', 'scheme_name' => '', 'user' => '', 'pass' => '', 'host' => '', 'port' => '', 'authority' => '', 'path' => '', 'query' => '', 'fragment' => '' ); $values = $parsed + $defaults; if (!empty($values['scheme'])) { $t->scheme = $values['scheme'].'://'; } else { $t->scheme = ''; } $t->scheme_name = $values['scheme']; $t->user = $values['user']; $t->pass = $values['pass']; $t->host = $values['host']; $t->port = $values['port']; $t->path = $values['path']; $t->query = $values['query']; $t->fragment = $values['fragment']; $t->gen_authority(); } private function _parse($uri) { $uri = (string) $uri; if (!version_compare(PHP_VERSION, '5.4.7') >= 0) { if ($uri[0] == '/') { unset($uri[0]); } if ($uri[0] == '/') { unset($uri[0]); } } return parse_url((string) $uri); } private function gen_authority() { $t = $this; $authority = ''; if (!empty($t->user)) { $authority .= $t->user; if (empty($t->pass)) { $authority .= '@'; } else { $authority .= ':'; } } if (!empty($t->pass)) { $authority .= $t->pass.'@'; } if (!empty($t->host)) { $authority .= $t->host; } if (!empty($t->port)) { $authority .= ':'.$t->port; } $t->authority = $authority; } public function arr() { if ($this->error) { return FALSE; } return array( 'scheme' => $this->scheme, 'user' => $this->user, 'pass' => $this->pass, 'host' => $this->host, 'port' => $this->port, 'authority' => $this->authority, 'path' => $this->path, 'query' => $this->query, 'fragment' => $this->fragment ); } public function str() { if ($this->error) { return FALSE; } $t = $this; $str = ''; if (!empty($t->scheme)) { $str .= $t->scheme; } if (!empty($t->user)) { $str .= $t->user; if (empty($t->pass)) { $str .= '@'; } else { $str .= ':'; $str .= $t->pass.'@'; } } if (!empty($t->host)) { $str .= $t->host; } if (!empty($t->port)) { $str .= ':'.$t->port; } if (!empty($t->path)) { $str .= $t->path; } if (!empty($t->query)) { $str .= '?'.$t->query; } if (!empty($t->fragment)) { $str .= '#'.$t->fragment; } return $str; } public function p_str() { if ($this->error) { return FALSE; } echo $this->str(); } public function path_info() { if ($this->error) { return FALSE; } $info = pathinfo($this->path); $arr = explode('/',$this->path); $last = count($arr) - 1; if ($arr[$last] == '') { unset($arr[$last]); } if ($arr[0] == '') { array_shift($arr); } $info['array'] = $arr; return $info; } public function query_arr() { if ($this->error) { return FALSE; } parse_str($this->query, $return); return $return; } public function append($section, $str, $disable_safety = FALSE) { if ($this->error) { return FALSE; } $section = strtolower($section); if (!isset($this->$section)) { return FALSE; } if ($disable_safety) { $this->$section = $this->$section.$str; } else { $test = $this->$section.$str; $safety = $this->safety($section, $test); if ($safety != FALSE) { $this->$section = $safety; } else { return FALSE; } } $this->gen_authority(); return $this->str(); } public function prepend($section, $str, $disable_safety = FALSE) { if ($this->error) { return FALSE; } $section = strtolower($section); if (!isset($this->$section)) { return FALSE; } if ($disable_safety) { $this->$section = $str.$this->$section; } else { $test = $str.$this->$section; $safety = $this->safety($section, $test); if ($safety != FALSE) { $this->$section = $safety; } else { return FALSE; } } $this->gen_authority(); return $this->str(); } public function replace($section, $str, $disable_safety = FALSE) { if ($this->error) { return FALSE; } $section = strtolower($section); if (!isset($this->$section)) { return FALSE; } if ($disable_safety) { $this->$section = $str; } else { $safety = $this->safety($section, $str); if ($safety != FALSE) { $this->$section = $safety; } else { return FALSE; } } $this->gen_authority(); return $this->str(); } protected function safety($type, $str) { $type = strtoupper((string) $type); if ($type != 'QUERY') { $str = trim((string) $str); } $err = 0; switch ($type) { case 'SCHEME_NAME': if (!preg_match('/\A[a-z]{1,10}\Z/', $str)) { $err++; } break; case 'SCHEME': if (strpos($str, '\\') !== FALSE) { $str = str_replace('\\', '/', $str); } if (strpos($str, '//') === FALSE && stripos($str, ':') === FALSE) { if (!empty($str)) { $str = $str.'://'; // assume it is generic } else { break; // there is nothing to check } } $str = strtolower($str); if (!stripos($str, '://') === FALSE) { // explicit generic if (!preg_match('/\A[a-z]{1,10}:\/\/(\/)?\Z/', $str)) { $err++; } } elseif(stripos($str, ':') === FALSE) { // explicit pipe if (!preg_match('/\A[a-z]{1,10}:\Z/', $str)) { $err++; } } elseif(stripos($str, '//') === FALSE) { // inherit if ($str != '//') { $err++; } } break; case 'USER': $str = rawurlencode($str); break; case 'PASS': $str = rawurlencode($str); break; case 'HOST': $str = strtolower($str); if ( ( !preg_match('/\A(([a-z0-9_]([a-z0-9\-_]+)?)\.)+[a-z0-9]([a-z0-9\-]+)?\Z/', $str) // fqdn && !preg_match('/\A([0-9]\.){3}[0-9]\Z/', $str) // ip ) || strlen($str) > 255 ) { $err++; } break; case 'PORT': if ($str[0] == ':') { $str = substr($str, 1); } if (!preg_match('/\A[0-9]{0,5}\Z/', $str)) { $err++; } break; case 'PATH': $str = str_replace(array('//', '\\'), '/', $str); // common mistakes $path_arr = explode('/', $str); $safe_arr = array(); foreach ($path_arr as $path_part) { $safe_arr[] = rawurlencode($path_part); } $str = implode('/', $safe_arr); break; case 'QUERY': if (is_array($str)) { $str = http_build_query($str); } if ($str[0] == '?') { $str = substr($str, 1); } $frag_loc = strpos($str, '#'); if ($frag_loc) { $str = substr($str, 0, ($frag_loc - 1)); } elseif ($str[0] == '#') { $str = ''; } break; case 'FRAGMENT': if ($str[0] == '#') { unset($str[0]); } $str = urlencode($str); break; default: return FALSE; break; } if ($err) { return FALSE; } return $str; } public function reset() { $this->__construct($this->input); } } $uri = new uri('http://example.com/path/to/file.ext'); $uri->replace('QUERY', array('rand', (string) rand(1, 10))); $uri->replace('PATH', '/foo/bar'); $uri->append('PATH', '.baz'); $new = $uri->prepend('HOST', 'www.'); $uri->reset(); $original = $uri->str(); $uri->replace('FRAGMENT', 'Checkout'); $secure = $uri->replace('SCHEME', 'https'); echo $new.PHP_EOL; echo $original.PHP_EOL; echo $secure.PHP_EOL;
Output for 5.3.2, 5.4.15, 5.4.17, 5.4.20, 5.4.23, 5.4.37, 5.4.39, 5.6.1, 5.6.23, 5.6.25, 7.0.2, 7.1.0
http://www.example.com/foo/bar.baz?0=rand&1=1 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.14, 5.3.21, 5.4.4, 5.4.9, 5.4.30, 5.4.36, 5.4.40, 5.4.44, 5.5.14, 5.6.0, 5.6.4, 5.6.9, 5.6.16, 5.6.28, 7.0.3 - 7.0.4, 7.0.6, 7.0.14
http://www.example.com/foo/bar.baz?0=rand&1=7 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.10, 5.3.12, 5.4.38, 5.5.9, 5.5.12, 5.5.16, 5.5.23 - 5.5.24, 5.5.27 - 5.5.28, 5.5.35, 5.6.7, 5.6.12, 7.0.0, 7.0.10
http://www.example.com/foo/bar.baz?0=rand&1=6 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.5, 5.3.11, 5.3.13, 5.3.26, 5.3.29, 5.4.7, 5.4.14, 5.4.16, 5.4.34, 5.5.2, 5.5.10, 5.5.30, 5.6.3, 7.0.1, 7.0.9
http://www.example.com/foo/bar.baz?0=rand&1=3 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.0, 5.3.4, 5.3.25, 5.3.28, 5.4.35, 5.5.0 - 5.5.1, 5.5.8, 5.5.33, 5.6.10 - 5.6.11, 5.6.18, hhvm-3.10.0, 7.0.8
http://www.example.com/foo/bar.baz?0=rand&1=10 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.8, 5.3.15, 5.4.2, 5.4.6, 5.4.12, 5.4.28, 5.4.32, 5.5.6 - 5.5.7, 5.6.5, 5.6.22, hhvm-3.12.0, 7.0.7
http://www.example.com/foo/bar.baz?0=rand&1=4 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.3, 5.3.7, 5.4.10, 5.4.18 - 5.4.19, 5.4.41 - 5.4.42, 5.5.3 - 5.5.5, 5.5.13, 5.5.18, 5.5.34, 5.5.38, 5.6.6, 5.6.19 - 5.6.20, 7.0.5
http://www.example.com/foo/bar.baz?0=rand&1=2 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.6, 5.3.18, 5.3.23 - 5.3.24, 5.4.8, 5.4.21, 5.4.25, 5.4.27, 5.4.31, 5.4.43, 5.4.45, 5.5.11, 5.5.15, 5.5.20, 5.5.29, 5.5.32, 5.6.8, 5.6.13, 5.6.15, 5.6.21, 5.6.24
http://www.example.com/foo/bar.baz?0=rand&1=9 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.16 - 5.3.17, 5.3.20, 5.4.3, 5.4.5, 5.4.24, 5.5.21, 5.5.25 - 5.5.26, 5.5.31, 5.5.36 - 5.5.37, 5.6.17
http://www.example.com/foo/bar.baz?0=rand&1=5 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout
Output for 5.3.1, 5.3.9, 5.3.19, 5.3.22, 5.3.27, 5.4.0 - 5.4.1, 5.4.11, 5.4.13, 5.4.22, 5.4.26, 5.4.29, 5.5.19, 5.5.22, 5.6.2, 5.6.14
http://www.example.com/foo/bar.baz?0=rand&1=8 http://example.com/path/to/file.ext https://example.com/path/to/file.ext#Checkout