Changeset View
Changeset View
Standalone View
Standalone View
src/parser/PhutilURI.php
Context not available. | |||||
// Reject ambiguous URIs outright. Different versions of different clients | // Reject ambiguous URIs outright. Different versions of different clients | ||||
// parse these in different ways. See T12526 for discussion. | // parse these in different ways. See T12526 for discussion. | ||||
if (preg_match('(^[^/:]*://[^/]*[#?].*:)', $uri)) { | if (@preg_match('(^[^/:]*://[^/]*[#?].*:)', $uri)) { | ||||
throw new Exception( | throw new Exception( | ||||
pht( | pht( | ||||
'Rejecting ambiguous URI "%s". This URI is not formatted or '. | 'Rejecting ambiguous URI "%s". This URI is not formatted or '. | ||||
Context not available. | |||||
} | } | ||||
$matches = null; | $matches = null; | ||||
if (preg_match('(^([^/:]*://[^/]*)(\\?.*)\z)', $uri, $matches)) { | if (@preg_match('(^([^/:]*://[^/]*)(\\?.*)\z)', $uri, $matches)) { | ||||
// If the URI is something like `idea://open?file=/path/to/file`, the | // If the URI is something like `idea://open?file=/path/to/file`, the | ||||
// `parse_url()` function will parse `open?file=` as the host. This is | // `parse_url()` function will parse `open?file=` as the host. This is | ||||
// not the expected result. Break the URI into two pieces, stick a slash | // not the expected result. Break the URI into two pieces, stick a slash | ||||
Context not available. | |||||
$host = '(?P<host>[^/:]+)'; | $host = '(?P<host>[^/:]+)'; | ||||
$path = ':(?P<path>.*)'; | $path = ':(?P<path>.*)'; | ||||
$ok = preg_match('(^'.$user.$host.$path.'\z)', $uri, $matches); | $ok = @preg_match('(^'.$user.$host.$path.'\z)', $uri, $matches); | ||||
if (!$ok) { | if (!$ok) { | ||||
throw new Exception( | throw new Exception( | ||||
pht( | pht( | ||||
Context not available. | |||||
// hosts beginning with "-". | // hosts beginning with "-". | ||||
if ($parts) { | if ($parts) { | ||||
$host = idx($parts, 'host', ''); | $host = idx($parts, 'host', ''); | ||||
if (strlen($host)) { | if (@strlen($host)) { | ||||
if (!preg_match('/^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-]*\z/', $host)) { | if (!@preg_match('/^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-]*\z/', $host)) { | ||||
$parts = false; | $parts = false; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
$user = $this->user; | $user = $this->user; | ||||
$pass = $this->pass; | $pass = $this->pass; | ||||
if (strlen($user) && strlen($pass)) { | if (@strlen($user) && @strlen($pass)) { | ||||
$auth = rawurlencode($user).':'.rawurlencode($pass).'@'; | $auth = rawurlencode($user).':'.rawurlencode($pass).'@'; | ||||
} else if (strlen($user)) { | } else if (@strlen($user)) { | ||||
$auth = rawurlencode($user).'@'; | $auth = rawurlencode($user).'@'; | ||||
} else { | } else { | ||||
$auth = null; | $auth = null; | ||||
Context not available. | |||||
if ($this->isGitURI()) { | if ($this->isGitURI()) { | ||||
$protocol = null; | $protocol = null; | ||||
} else { | } else { | ||||
if (strlen($auth)) { | if (@strlen($auth)) { | ||||
$protocol = nonempty($this->protocol, 'http'); | $protocol = nonempty($this->protocol, 'http'); | ||||
} | } | ||||
} | } | ||||
if (strlen($protocol) || strlen($auth) || strlen($domain)) { | if (@strlen($protocol) || @strlen($auth) || @strlen($domain)) { | ||||
if ($this->isGitURI()) { | if ($this->isGitURI()) { | ||||
$prefix = "{$auth}{$domain}"; | $prefix = "{$auth}{$domain}"; | ||||
} else { | } else { | ||||
$prefix = "{$protocol}://{$auth}{$domain}"; | $prefix = "{$protocol}://{$auth}{$domain}"; | ||||
} | } | ||||
if (strlen($port)) { | if (@strlen($port)) { | ||||
$prefix .= ':'.$port; | $prefix .= ':'.$port; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
$query = null; | $query = null; | ||||
} | } | ||||
if (strlen($this->getFragment())) { | if (@strlen($this->getFragment())) { | ||||
$fragment = '#'.$this->getFragment(); | $fragment = '#'.$this->getFragment(); | ||||
} else { | } else { | ||||
$fragment = null; | $fragment = null; | ||||
Context not available. | |||||
$path = $this->getPath(); | $path = $this->getPath(); | ||||
if ($this->isGitURI()) { | if ($this->isGitURI()) { | ||||
if (strlen($path)) { | if (@strlen($path)) { | ||||
$path = ':'.$path; | $path = ':'.$path; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
if ($this->isGitURI()) { | if ($this->isGitURI()) { | ||||
// Git URIs use relative paths which do not need to begin with "/". | // Git URIs use relative paths which do not need to begin with "/". | ||||
} else { | } else { | ||||
if ($this->domain && strlen($path) && $path[0] !== '/') { | if ($this->domain && @strlen($path) && $path[0] !== '/') { | ||||
$path = '/'.$path; | $path = '/'.$path; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
public function appendPath($path) { | public function appendPath($path) { | ||||
$first = strlen($path) ? $path[0] : null; | $first = @strlen($path) ? $path[0] : null; | ||||
$last = strlen($this->path) ? $this->path[strlen($this->path) - 1] : null; | $last = @strlen($this->path) ? $this->path[@strlen($this->path) - 1] : null; | ||||
if (!$this->path) { | if (!$this->path) { | ||||
return $this->setPath($path); | return $this->setPath($path); | ||||
} else if ($first === '/' && $last === '/') { | } else if ($first === '/' && $last === '/') { | ||||
$path = substr($path, 1); | $path = @substr($path, 1); | ||||
} else if ($first !== '/' && $last !== '/') { | } else if ($first !== '/' && $last !== '/') { | ||||
$path = '/'.$path; | $path = '/'.$path; | ||||
} | } | ||||
Context not available. | |||||
if ($type == self::TYPE_URI) { | if ($type == self::TYPE_URI) { | ||||
$path = $this->getPath(); | $path = $this->getPath(); | ||||
if (strlen($path) && ($path[0] !== '/')) { | if (@strlen($path) && ($path[0] !== '/')) { | ||||
// Try to catch this here because we are not allowed to throw from | // Try to catch this here because we are not allowed to throw from | ||||
// inside __toString() so we don't have a reasonable opportunity to | // inside __toString() so we don't have a reasonable opportunity to | ||||
// react properly if we catch it later. | // react properly if we catch it later. | ||||
Context not available. | |||||
private function isGitURIPattern($uri) { | private function isGitURIPattern($uri) { | ||||
$matches = null; | $matches = null; | ||||
$ok = preg_match('(^(?P<head>[^/]+):(?P<last>(?!//).*)\z)', $uri, $matches); | $ok = @preg_match('(^(?P<head>[^/]+):(?P<last>(?!//).*)\z)', $uri, $matches); | ||||
if (!$ok) { | if (!$ok) { | ||||
return false; | return false; | ||||
} | } | ||||
Context not available. | |||||
// If any part of this has spaces in it, it's not a Git URI. We fail here | // If any part of this has spaces in it, it's not a Git URI. We fail here | ||||
// so we fall back and don't fail more abruptly later. | // so we fall back and don't fail more abruptly later. | ||||
if (preg_match('(\s)', $head.$last)) { | if (@preg_match('(\s)', $head.$last)) { | ||||
return false; | return false; | ||||
} | } | ||||
// If the second part only contains digits, assume we're looking at | // If the second part only contains digits, assume we're looking at | ||||
// casually specified "domain.com:123" URI, not a Git URI pointed at an | // casually specified "domain.com:123" URI, not a Git URI pointed at an | ||||
// entirely numeric relative path. | // entirely numeric relative path. | ||||
if (preg_match('(^\d+\z)', $last)) { | if (@preg_match('(^\d+\z)', $last)) { | ||||
return false; | return false; | ||||
} | } | ||||
// If the first part has a "." or an "@" in it, interpret it as a domain | // If the first part has a "." or an "@" in it, interpret it as a domain | ||||
// or a "user@host" string. | // or a "user@host" string. | ||||
if (preg_match('([.@])', $head)) { | if (@preg_match('([.@])', $head)) { | ||||
return true; | return true; | ||||
} | } | ||||
Context not available. |
Content licensed under Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) unless otherwise noted; code licensed under Apache 2.0 or other open source licenses. · CC BY-SA 4.0 · Apache 2.0