parseUri($uri); } } /** * @param string $uri * * @throws \InvalidArgumentException */ protected function parseUri($uri) { if (false === ($uriParts = parse_url($uri))) { // congratulations if you've managed to get parse_url to fail, // it seems to always return some semblance of a parsed url no matter what throw new InvalidArgumentException("Invalid URI: $uri"); } if (!isset($uriParts['scheme'])) { throw new InvalidArgumentException('Invalid URI: http|https scheme required'); } $this->scheme = $uriParts['scheme']; $this->host = $uriParts['host']; if (isset($uriParts['port'])) { $this->port = $uriParts['port']; $this->explicitPortSpecified = true; } else { $this->port = strcmp('https', $uriParts['scheme']) ? 80 : 443; $this->explicitPortSpecified = false; } if (isset($uriParts['path'])) { $this->path = $uriParts['path']; if ('/' === $uriParts['path']) { $this->explicitTrailingHostSlash = true; } } else { $this->path = '/'; } $this->query = isset($uriParts['query']) ? $uriParts['query'] : ''; $this->fragment = isset($uriParts['fragment']) ? $uriParts['fragment'] : ''; $userInfo = ''; if (!empty($uriParts['user'])) { $userInfo .= $uriParts['user']; } if ($userInfo && !empty($uriParts['pass'])) { $userInfo .= ':' . $uriParts['pass']; } $this->setUserInfo($userInfo); } /** * @param string $rawUserInfo * * @return string */ protected function protectUserInfo($rawUserInfo) { $colonPos = strpos($rawUserInfo, ':'); // rfc3986-3.2.1 | http://tools.ietf.org/html/rfc3986#section-3.2 // "Applications should not render as clear text any data // after the first colon (":") character found within a userinfo // subcomponent unless the data after the colon is the empty string // (indicating no password)" if ($colonPos !== false && strlen($rawUserInfo)-1 > $colonPos) { return substr($rawUserInfo, 0, $colonPos) . ':********'; } else { return $rawUserInfo; } } /** * @return string */ public function getScheme() { return $this->scheme; } /** * @return string */ public function getUserInfo() { return $this->userInfo; } /** * @return string */ public function getRawUserInfo() { return $this->rawUserInfo; } /** * @return string */ public function getHost() { return $this->host; } /** * @return int */ public function getPort() { return $this->port; } /** * @return string */ public function getPath() { return $this->path; } /** * @return string */ public function getQuery() { return $this->query; } /** * @return string */ public function getFragment() { return $this->fragment; } /** * Uses protected user info by default as per rfc3986-3.2.1 * Uri::getRawAuthority() is available if plain-text password information is desirable. * * @return string */ public function getAuthority() { $authority = $this->userInfo ? $this->userInfo.'@' : ''; $authority .= $this->host; if ($this->explicitPortSpecified) { $authority .= ":{$this->port}"; } return $authority; } /** * @return string */ public function getRawAuthority() { $authority = $this->rawUserInfo ? $this->rawUserInfo.'@' : ''; $authority .= $this->host; if ($this->explicitPortSpecified) { $authority .= ":{$this->port}"; } return $authority; } /** * @return string */ public function getAbsoluteUri() { $uri = $this->scheme . '://' . $this->getRawAuthority(); if ('/' === $this->path) { $uri .= $this->explicitTrailingHostSlash ? '/' : ''; } else { $uri .= $this->path; } if (!empty($this->query)) { $uri .= "?{$this->query}"; } if (!empty($this->fragment)) { $uri .= "#{$this->fragment}"; } return $uri; } /** * @return string */ public function getRelativeUri() { $uri = ''; if ('/' === $this->path) { $uri .= $this->explicitTrailingHostSlash ? '/' : ''; } else { $uri .= $this->path; } return $uri; } /** * Uses protected user info by default as per rfc3986-3.2.1 * Uri::getAbsoluteUri() is available if plain-text password information is desirable. * * @return string */ public function __toString() { $uri = $this->scheme . '://' . $this->getAuthority(); if ('/' === $this->path) { $uri .= $this->explicitTrailingHostSlash ? '/' : ''; } else { $uri .= $this->path; } if (!empty($this->query)) { $uri .= "?{$this->query}"; } if (!empty($this->fragment)) { $uri .= "#{$this->fragment}"; } return $uri; } /** * @param $path */ public function setPath($path) { if (empty($path)) { $this->path = '/'; $this->explicitTrailingHostSlash = false; } else { $this->path = $path; if ('/' === $this->path) { $this->explicitTrailingHostSlash = true; } } } /** * @param string $query */ public function setQuery($query) { $this->query = $query; } /** * @param string $var * @param string $val */ public function addToQuery($var, $val) { if (strlen($this->query) > 0) { $this->query .= '&'; } $this->query .= http_build_query(array($var => $val), '', '&'); } /** * @param string $fragment */ public function setFragment($fragment) { $this->fragment = $fragment; } /** * @param string $scheme */ public function setScheme($scheme) { $this->scheme = $scheme; } /** * @param string $userInfo */ public function setUserInfo($userInfo) { $this->userInfo = $userInfo ? $this->protectUserInfo($userInfo) : ''; $this->rawUserInfo = $userInfo; } /** * @param int $port */ public function setPort($port) { $this->port = intval($port); if (('https' === $this->scheme && $this->port === 443) || ('http' === $this->scheme && $this->port === 80)) { $this->explicitPortSpecified = false; } else { $this->explicitPortSpecified = true; } } /** * @param string $host */ public function setHost($host) { $this->host = $host; } /** * @return bool */ public function hasExplicitTrailingHostSlash() { return $this->explicitTrailingHostSlash; } /** * @return bool */ public function hasExplicitPortSpecified() { return $this->explicitPortSpecified; } }