protected function didValidateOption(PhabricatorConfigOption $option, $value) { $key = $option->getKey(); if ($key == 'phabricator.base-uri' || $key == 'phabricator.production-uri') { $uri = new PhutilURI($value); $protocol = $uri->getProtocol(); if ($protocol !== 'http' && $protocol !== 'https') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must start with " . "%s' or '%s'.", 'http://', 'https://', $key)); } $domain = $uri->getDomain(); if (strpos($domain, '.') === false) { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must contain a dot " . "('%s'), like '%s', not just a bare name like '%s'. Some web " . "browsers will not set cookies on domains with no TLD.", '.', 'http://example.com/', 'http://example/', $key)); } $path = $uri->getPath(); if ($path !== '' && $path !== '/') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must NOT have a path, " . "e.g. '%s' is OK, but '%s' is not. Phabricator must be installed " . "on an entire domain; it can not be installed on a path.", $key, 'http://phabricator.example.com/', 'http://example.com/phabricator/')); } } if ($key === 'phabricator.timezone') { $old = date_default_timezone_get(); $ok = @date_default_timezone_set($value); @date_default_timezone_set($old); if (!$ok) { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The timezone identifier must " . "be a valid timezone identifier recognized by PHP, like '%s'. " . "\n You can find a list of valid identifiers here: %s", $key, 'America/Los_Angeles', 'http://php.net/manual/timezones.php')); } } }
/** * Makes sure a given custom blog uri is properly configured in DNS * to point at this Phabricator instance. If there is an error in * the configuration, return a string describing the error and how * to fix it. If there is no error, return an empty string. * * @return string */ public function validateCustomDomain($custom_domain) { $example_domain = 'blog.example.com'; $label = pht('Invalid'); // note this "uri" should be pretty busted given the desired input // so just use it to test if there's a protocol specified $uri = new PhutilURI($custom_domain); if ($uri->getProtocol()) { return array($label, pht('The custom domain should not include a protocol. Just provide ' . 'the bare domain name (for example, "%s").', $example_domain)); } if ($uri->getPort()) { return array($label, pht('The custom domain should not include a port number. Just provide ' . 'the bare domain name (for example, "%s").', $example_domain)); } if (strpos($custom_domain, '/') !== false) { return array($label, pht('The custom domain should not specify a path (hosting a Phame ' . 'blog at a path is currently not supported). Instead, just provide ' . 'the bare domain name (for example, "%s").', $example_domain)); } if (strpos($custom_domain, '.') === false) { return array($label, pht('The custom domain should contain at least one dot (.) because ' . 'some browsers fail to set cookies on domains without a dot. ' . 'Instead, use a normal looking domain name like "%s".', $example_domain)); } if (!PhabricatorEnv::getEnvConfig('policy.allow-public')) { $href = PhabricatorEnv::getProductionURI('/config/edit/policy.allow-public/'); return array(pht('Fix Configuration'), pht('For custom domains to work, this Phabricator instance must be ' . 'configured to allow the public access policy. Configure this ' . 'setting %s, or ask an administrator to configure this setting. ' . 'The domain can be specified later once this setting has been ' . 'changed.', phutil_tag('a', array('href' => $href), pht('here')))); } return null; }
protected function renderInput() { self::requireLib(); $uri = new PhutilURI(PhabricatorEnv::getEnvConfig('phabricator.base-uri')); $protocol = $uri->getProtocol(); $use_ssl = $protocol == 'https'; return phutil_safe_html(recaptcha_get_html(PhabricatorEnv::getEnvConfig('recaptcha.public-key'), $error = null, $use_ssl)); }
protected function getProviderConfigurationHelp() { $login_uri = PhabricatorEnv::getURI($this->getLoginURI()); $uri = new PhutilURI(PhabricatorEnv::getProductionURI('/')); $https_note = null; if ($uri->getProtocol() !== 'https') { $https_note = pht('NOTE: Amazon **requires** HTTPS, but your Phabricator install does ' . 'not use HTTPS. **You will not be able to add Amazon as an ' . 'authentication provider until you configure HTTPS on this install**.'); } return pht("%s\n\n" . "To configure Amazon OAuth, create a new 'API Project' here:" . "\n\n" . "http://login.amazon.com/manageApps" . "\n\n" . "Use these settings:" . "\n\n" . " - **Allowed Return URLs:** Add this: `%s`" . "\n\n" . "After completing configuration, copy the **Client ID** and " . "**Client Secret** to the fields above.", $https_note, $login_uri); }
private function validateURI($raw_uri) { $uri = new PhutilURI($raw_uri); $protocol = $uri->getProtocol(); if (!strlen($protocol)) { throw new Exception(pht('Unable to identify the protocol for URI "%s". URIs must be ' . 'fully qualified and have an identifiable protocol.', $raw_uri)); } $protocol_key = 'uri.allowed-protocols'; $protocols = PhabricatorEnv::getEnvConfig($protocol_key); if (empty($protocols[$protocol])) { throw new Exception(pht('URI "%s" does not have an allowable protocol. Configure ' . 'protocols in `%s`. Allowed protocols are: %s.', $raw_uri, $protocol_key, implode(', ', array_keys($protocols)))); } }
public function handleRequest(AphrontRequest $request) { $show_prototypes = PhabricatorEnv::getEnvConfig('phabricator.show-prototypes'); if (!$show_prototypes) { throw new Exception(pht('Show prototypes is disabled. Set `phabricator.show-prototypes` to `true` to use the image proxy')); } $viewer = $request->getViewer(); $img_uri = $request->getStr('uri'); // Validate the URI before doing anything PhabricatorEnv::requireValidRemoteURIForLink($img_uri); $uri = new PhutilURI($img_uri); $proto = $uri->getProtocol(); if (!in_array($proto, array('http', 'https'))) { throw new Exception(pht('The provided image URI must be either http or https')); } // Check if we already have the specified image URI downloaded $cached_request = id(new PhabricatorFileExternalRequest())->loadOneWhere('uriIndex = %s', PhabricatorHash::digestForIndex($img_uri)); if ($cached_request) { return $this->getExternalResponse($cached_request); } $ttl = PhabricatorTime::getNow() + phutil_units('7 days in seconds'); $external_request = id(new PhabricatorFileExternalRequest())->setURI($img_uri)->setTTL($ttl); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); // Cache missed so we'll need to validate and download the image try { // Rate limit outbound fetches to make this mechanism less useful for // scanning networks and ports. PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorFilesOutboundRequestAction(), 1); $file = PhabricatorFile::newFromFileDownload($uri, array('viewPolicy' => PhabricatorPolicies::POLICY_NOONE, 'canCDN' => true)); if (!$file->isViewableImage()) { $mime_type = $file->getMimeType(); $engine = new PhabricatorDestructionEngine(); $engine->destroyObject($file); $file = null; throw new Exception(pht('The URI "%s" does not correspond to a valid image file, got ' . 'a file with MIME type "%s". You must specify the URI of a ' . 'valid image file.', $uri, $mime_type)); } else { $file->save(); } $external_request->setIsSuccessful(true)->setFilePHID($file->getPHID())->save(); unset($unguarded); return $this->getExternalResponse($external_request); } catch (HTTPFutureHTTPResponseStatus $status) { $external_request->setIsSuccessful(false)->setResponseMessage($status->getMessage())->save(); return $this->getExternalResponse($external_request); } catch (Exception $ex) { // Not actually saving the request in this case $external_request->setResponseMessage($ex->getMessage()); return $this->getExternalResponse($external_request); } }
/** * @task normal */ public function getPath() { switch ($this->type) { case self::TYPE_GIT: $uri = new PhutilURI($this->uri); return $uri->getPath(); case self::TYPE_SVN: case self::TYPE_MERCURIAL: $uri = new PhutilURI($this->uri); if ($uri->getProtocol()) { return $uri->getPath(); } return $this->uri; } }
public static function hasAllowedProtocol($uri) { $uri = new PhutilURI($uri); $editor_protocol = $uri->getProtocol(); if (!$editor_protocol) { // The URI must have a protocol. return false; } $allowed_key = 'uri.allowed-editor-protocols'; $allowed_protocols = PhabricatorEnv::getEnvConfig($allowed_key); if (empty($allowed_protocols[$editor_protocol])) { // The protocol must be on the allowed protocol whitelist. return false; } return true; }
/** * Makes sure a given custom blog uri is properly configured in DNS * to point at this Phabricator instance. If there is an error in * the configuration, return a string describing the error and how * to fix it. If there is no error, return an empty string. * * @return string */ public function validateCustomDomain($custom_domain) { $example_domain = '(e.g. blog.example.com)'; $valid = ''; // note this "uri" should be pretty busted given the desired input // so just use it to test if there's a protocol specified $uri = new PhutilURI($custom_domain); if ($uri->getProtocol()) { return 'Do not specify a protocol, just the domain. ' . $example_domain; } if (strpos($custom_domain, '/') !== false) { return 'Do not specify a path, just the domain. ' . $example_domain; } if (strpos($custom_domain, '.') === false) { return 'Custom domain must contain at least one dot (.) because ' . 'some browsers fail to set cookies on domains such as ' . 'http://example. ' . $example_domain; } return $valid; }
protected function didValidateOption(PhabricatorConfigOption $option, $value) { $key = $option->getKey(); if ($key == 'security.alternate-file-domain') { $uri = new PhutilURI($value); $protocol = $uri->getProtocol(); if ($protocol !== 'http' && $protocol !== 'https') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must start with " . "'%s' or '%s'.", $key, 'http://', 'https://')); } $domain = $uri->getDomain(); if (strpos($domain, '.') === false) { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must contain a dot ('.'), " . "like '%s', not just a bare name like '%s'. " . "Some web browsers will not set cookies on domains with no TLD.", $key, 'http://example.com/', 'http://example/')); } $path = $uri->getPath(); if ($path !== '' && $path !== '/') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must NOT have a path, " . "e.g. '%s' is OK, but '%s' is not. Phabricator must be installed " . "on an entire domain; it can not be installed on a path.", $key, 'http://phabricator.example.com/', 'http://example.com/phabricator/')); } } }
public function processEditForm(AphrontRequest $request, array $values) { $errors = array(); $issues = array(); $is_setup = $this->isSetup(); $key_name = self::PROPERTY_MEDIAWIKI_NAME; $key_uri = self::PROPERTY_MEDIAWIKI_URI; $key_secret = self::PROPERTY_CONSUMER_SECRET; $key_consumer = self::PROPERTY_CONSUMER_KEY; if (!strlen($values[$key_uri])) { $errors[] = pht('MediaWiki base URI is required.'); $issues[$key_uri] = pht('Required'); } else { $uri = new PhutilURI($values[$key_uri]); if (!$uri->getProtocol()) { $errors[] = pht('MediaWiki base URI should include protocol ' . '(like "https://").'); $issues[$key_uri] = pht('Invalid'); } } if (!$is_setup && !strlen($values[$key_secret])) { $errors[] = pht('Consumer Secret is required'); $issues[$key_secret] = pht('Required'); } if (!$is_setup && !strlen($values[$key_consumer])) { $errors[] = pht('Consumer Key is required'); $issues[$key_consumer] = pht('Required'); } if (!count($errors)) { $config = $this->getProviderConfig(); $config->setProviderDomain($values[$key_name]); $config->setProperty($key_name, $values[$key_name]); if ($is_setup) { $config->setProperty($key_uri, $values[$key_uri]); } else { $config->setProperty($key_uri, $values[$key_uri]); $config->setProperty($key_secret, $values[$key_secret]); $config->setProperty($key_consumer, $values[$key_consumer]); } $config->save(); } return array($errors, $issues, $values); }
public function testURIParsing() { $uri = new PhutilURI('http://*****:*****@host:99/path/?query=value#fragment'); $this->assertEqual('http', $uri->getProtocol(), 'protocol'); $this->assertEqual('user', $uri->getUser(), 'user'); $this->assertEqual('pass', $uri->getPass(), 'pass'); $this->assertEqual('host', $uri->getDomain(), 'domain'); $this->assertEqual('99', $uri->getPort(), 'port'); $this->assertEqual('/path/', $uri->getPath(), 'path'); $this->assertEqual(array('query' => 'value'), $uri->getQueryParams(), 'query params'); $this->assertEqual('fragment', $uri->getFragment(), 'fragment'); $this->assertEqual('http://*****:*****@host:99/path/?query=value#fragment', (string) $uri, 'uri'); $uri = new PhutilURI('ssh://git@example.com/example/example.git'); $this->assertEqual('ssh', $uri->getProtocol(), 'protocol'); $this->assertEqual('git', $uri->getUser(), 'user'); $this->assertEqual('', $uri->getPass(), 'pass'); $this->assertEqual('example.com', $uri->getDomain(), 'domain'); $this->assertEqual('', $uri->getPort(), 'port'); $this->assertEqual('/example/example.git', $uri->getPath(), 'path'); $this->assertEqual(array(), $uri->getQueryParams(), 'query params'); $this->assertEqual('', $uri->getFragment(), 'fragment'); $this->assertEqual('ssh://git@example.com/example/example.git', (string) $uri, 'uri'); $uri = new PhutilURI('http://0@domain.com/'); $this->assertEqual('0', $uri->getUser()); $this->assertEqual('http://0@domain.com/', (string) $uri); $uri = new PhutilURI('http://*****:*****@domain.com/'); $this->assertEqual('0', $uri->getUser()); $this->assertEqual('0', $uri->getPass()); $this->assertEqual('http://*****:*****@domain.com/', (string) $uri); $uri = new PhutilURI('http://%20:%20@domain.com/'); $this->assertEqual(' ', $uri->getUser()); $this->assertEqual(' ', $uri->getPass()); $this->assertEqual('http://%20:%20@domain.com/', (string) $uri); $uri = new PhutilURI('http://%40:%40@domain.com/'); $this->assertEqual('@', $uri->getUser()); $this->assertEqual('@', $uri->getPass()); $this->assertEqual('http://%40:%40@domain.com/', (string) $uri); }
public function processEditForm(AphrontRequest $request, array $values) { $errors = array(); $issues = array(); $is_setup = $this->isSetup(); $key_name = self::PROPERTY_JIRA_NAME; $key_uri = self::PROPERTY_JIRA_URI; if (!strlen($values[$key_name])) { $errors[] = pht('JIRA instance name is required.'); $issues[$key_name] = pht('Required'); } else { if (!preg_match('/^[a-z0-9.]+\\z/', $values[$key_name])) { $errors[] = pht('JIRA instance name must contain only lowercase letters, digits, and ' . 'period.'); $issues[$key_name] = pht('Invalid'); } } if (!strlen($values[$key_uri])) { $errors[] = pht('JIRA base URI is required.'); $issues[$key_uri] = pht('Required'); } else { $uri = new PhutilURI($values[$key_uri]); if (!$uri->getProtocol()) { $errors[] = pht('JIRA base URI should include protocol (like "https://").'); $issues[$key_uri] = pht('Invalid'); } } if (!$errors && $is_setup) { $config = $this->getProviderConfig(); $config->setProviderDomain($values[$key_name]); $consumer_key = 'phjira.' . Filesystem::readRandomCharacters(16); list($public, $private) = PhutilJIRAAuthAdapter::newJIRAKeypair(); $config->setProperty(self::PROPERTY_PUBLIC_KEY, $public); $config->setProperty(self::PROPERTY_PRIVATE_KEY, $private); $config->setProperty(self::PROPERTY_CONSUMER_KEY, $consumer_key); } return array($errors, $issues, $values); }
/** * This method is kind of awkward here but both the SVN message and * change parsers use it. */ protected function getSVNLogXMLObject($uri, $revision, $verbose = false) { if ($verbose) { $verbose = '--verbose'; } try { list($xml) = execx("svn log --xml {$verbose} --limit 1 --non-interactive %s@%d", $uri, $revision); } catch (CommandException $ex) { // HTTPS is generally faster and more reliable than svn+ssh, but some // commit messages with non-UTF8 text can't be retrieved over HTTPS, see // Facebook rE197184 for one example. Make an attempt to fall back to // svn+ssh if we've failed outright to retrieve the message. $fallback_uri = new PhutilURI($uri); if ($fallback_uri->getProtocol() != 'https') { throw $ex; } $fallback_uri->setProtocol('svn+ssh'); list($xml) = execx("svn log --xml {$verbose} --limit 1 --non-interactive %s@%d", $fallback_uri, $revision); } // Subversion may send us back commit messages which won't parse because // they have non UTF-8 garbage in them. Slam them into valid UTF-8. $xml = phutil_utf8ize($xml); return new SimpleXMLElement($xml); }
public function processEditForm(AphrontRequest $request, array $values) { $is_setup = $this->isCreate(); if (!$is_setup) { list($errors, $issues, $values) = parent::processEditForm($request, $values); } else { $errors = array(); $issues = array(); } $key_name = self::PROPERTY_PHABRICATOR_NAME; $key_uri = self::PROPERTY_PHABRICATOR_URI; if (!strlen($values[$key_name])) { $errors[] = pht('Phabricator instance name is required.'); $issues[$key_name] = pht('Required'); } else { if (!preg_match('/^[a-z0-9.]+\\z/', $values[$key_name])) { $errors[] = pht('Phabricator instance name must contain only lowercase letters, ' . 'digits, and periods.'); $issues[$key_name] = pht('Invalid'); } } if (!strlen($values[$key_uri])) { $errors[] = pht('Phabricator base URI is required.'); $issues[$key_uri] = pht('Required'); } else { $uri = new PhutilURI($values[$key_uri]); if (!$uri->getProtocol()) { $errors[] = pht('Phabricator base URI should include protocol (like "%s").', 'https://'); $issues[$key_uri] = pht('Invalid'); } } if (!$errors && $is_setup) { $config = $this->getProviderConfig(); $config->setProviderDomain($values[$key_name]); } return array($errors, $issues, $values); }
function phabricator_detect_bad_base_uri() { $conf = PhabricatorEnv::getEnvConfig('phabricator.base-uri'); $uri = new PhutilURI($conf); switch ($uri->getProtocol()) { case 'http': case 'https': break; default: return phabricator_fatal_config_error("'phabricator.base-uri' is set to '{$conf}', which is invalid. " . "The URI must start with 'http://' or 'https://'."); } if (strpos($uri->getDomain(), '.') === false) { phabricator_fatal_config_error("'phabricator.base-uri' is set to '{$conf}', which is invalid. The URI " . "must contain a dot ('.'), like 'http://example.com/', not just " . "'http://example/'. Some web browsers will not set cookies on domains " . "with no TLD, and Phabricator requires cookies for login. " . "If you are using localhost, create an entry in the hosts file like " . "'127.0.0.1 example.com', and access the localhost with " . "'http://example.com/'."); } }
/** * Get a parsed object representation of the repository's remote URI. This * may be a normal URI (returned as a @{class:PhutilURI}) or a git URI * (returned as a @{class:PhutilGitURI}). * * @return wild A @{class:PhutilURI} or @{class:PhutilGitURI}. * @task uri */ private function getRemoteURIObject() { $raw_uri = $this->getDetail('remote-uri'); if (!$raw_uri) { return new PhutilURI(''); } if (!strncmp($raw_uri, '/', 1)) { return new PhutilURI('file://' . $raw_uri); } $uri = new PhutilURI($raw_uri); if ($uri->getProtocol()) { if ($this->isSSHProtocol($uri->getProtocol())) { if ($this->getSSHLogin()) { $uri->setUser($this->getSSHLogin()); } } return $uri; } $uri = new PhutilGitURI($raw_uri); if ($uri->getDomain()) { if ($this->getSSHLogin()) { $uri->setUser($this->getSSHLogin()); } return $uri; } throw new Exception("Remote URI '{$raw_uri}' could not be parsed!"); }
public function shouldUseSSH() { $uri = new PhutilURI($this->getRemoteURI()); $protocol = $uri->getProtocol(); if ($this->isSSHProtocol($protocol)) { return (bool) $this->getDetail('ssh-key'); } else { return false; } }
public function isValid() { $allowed_protocols = PhabricatorEnv::getEnvConfig('uri.allowed-protocols'); $uri = new PhutilURI($this->getLongURL()); return isset($allowed_protocols[$uri->getProtocol()]); }
private function determineConduitURI() { $uri = $this->getArgument('uri'); if (count($uri) > 1) { throw new ArcanistUsageException(pht('Specify at most one URI.')); } else { if (count($uri) == 1) { $uri = reset($uri); } else { $conduit_uri = $this->getConduitURI(); if (!$conduit_uri) { throw new ArcanistUsageException(pht('Specify an explicit URI or run this command from within a ' . 'project which is configured with a %s.', '.arcconfig')); } $uri = $conduit_uri; } } $uri_object = new PhutilURI($uri); if (!$uri_object->getProtocol() || !$uri_object->getDomain()) { throw new ArcanistUsageException(pht('Server URI "%s" must include a protocol and domain. It should be ' . 'in the form "%s".', $uri, 'https://phabricator.example.com/')); } $uri_object->setPath('/api/'); return (string) $uri_object; }
public static function newFromFileDownload($uri, $name) { $uri = new PhutilURI($uri); $protocol = $uri->getProtocol(); switch ($protocol) { case 'http': case 'https': break; default: // Make sure we are not accessing any file:// URIs or similar. return null; } $timeout = stream_context_create(array('http' => array('timeout' => 5))); $file_data = @file_get_contents($uri, false, $timeout); if ($file_data === false) { return null; } return self::newFromFileData($file_data, array('name' => $name)); }
#!/usr/bin/env php <?php $root = dirname(dirname(dirname(__FILE__))); require_once $root . '/scripts/__init_script__.php'; $uri = 'https://secure.phabricator.com/derp/derp/'; $method = 'GET'; $data = ''; $timeout = 30; $parsed = new PhutilURI($uri); if ($parsed->getProtocol() == 'https') { $future = new HTTPSFuture($uri, $data); } else { $future = new HTTPFuture($uri, $data); } $future->setMethod($method); $future->setTimeout($timeout); print_r($future->resolve());
private function getForcedPort() { $protocol = $this->getBuiltinProtocol(); if ($protocol == self::BUILTIN_PROTOCOL_SSH) { return PhabricatorEnv::getEnvConfig('diffusion.ssh-port'); } // If Phabricator is running on a nonstandard port, use that as the defualt // port for URIs with the same protocol. $is_http = $protocol == self::BUILTIN_PROTOCOL_HTTP; $is_https = $protocol == self::BUILTIN_PROTOCOL_HTTPS; if ($is_http || $is_https) { $uri = PhabricatorEnv::getURI('/'); $uri = new PhutilURI($uri); $port = $uri->getPort(); if (!$port) { return null; } $uri_protocol = $uri->getProtocol(); $use_port = $is_http && $uri_protocol == 'http' || $is_https && $uri_protocol == 'https'; if (!$use_port) { return null; } return $port; } return null; }
/** * If there's a URI specified in an OAuth request, it must be validated in * its own right. Further, it must have the same domain, the same path, the * same port, and (at least) the same query parameters as the primary URI. */ public function validateSecondaryRedirectURI(PhutilURI $secondary_uri, PhutilURI $primary_uri) { // The secondary URI must be valid. if (!$this->validateRedirectURI($secondary_uri)) { return false; } // Both URIs must point at the same domain. if ($secondary_uri->getDomain() != $primary_uri->getDomain()) { return false; } // Both URIs must have the same path if ($secondary_uri->getPath() != $primary_uri->getPath()) { return false; } // Both URIs must have the same port if ($secondary_uri->getPort() != $primary_uri->getPort()) { return false; } // Any query parameters present in the first URI must be exactly present // in the second URI. $need_params = $primary_uri->getQueryParams(); $have_params = $secondary_uri->getQueryParams(); foreach ($need_params as $key => $value) { if (!array_key_exists($key, $have_params)) { return false; } if ((string) $have_params[$key] != (string) $value) { return false; } } // If the first URI is HTTPS, the second URI must also be HTTPS. This // defuses an attack where a third party with control over the network // tricks you into using HTTP to authenticate over a link which is supposed // to be HTTPS only and sniffs all your token cookies. if (strtolower($primary_uri->getProtocol()) == 'https') { if (strtolower($secondary_uri->getProtocol()) != 'https') { return false; } } return true; }
public function shouldUseHTTP() { $uri = new PhutilURI($this->getRemoteURI()); $protocol = $uri->getProtocol(); if ($this->isHTTPProtocol($protocol)) { return (bool) $this->getDetail('http-login'); } else { return false; } }
public function testUnusualURIs() { $uri = new PhutilURI('file:///path/to/file'); $this->assertEqual('file', $uri->getProtocol(), pht('protocol')); $this->assertEqual('', $uri->getDomain(), pht('domain')); $this->assertEqual('/path/to/file', $uri->getPath(), pht('path')); $uri = new PhutilURI('idea://open?x=/'); $this->assertEqual('idea', $uri->getProtocol(), pht('protocol')); $this->assertEqual('open', $uri->getDomain(), pht('domain')); $this->assertEqual('', $uri->getPath(), pht('path')); $this->assertEqual(array('x' => '/'), $uri->getQueryParams()); }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhabricatorPhurlURLTransaction::TYPE_ALIAS: $overdrawn = $this->validateIsTextFieldTooLong($object->getName(), $xactions, 64); if ($overdrawn) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Alias Too Long'), pht('The alias can be no longer than 64 characters.'), nonempty(last($xactions), null)); } foreach ($xactions as $xaction) { if ($xaction->getOldValue() != $xaction->getNewValue()) { $new_alias = $xaction->getNewValue(); $debug_alias = new PHUIInvisibleCharacterView($new_alias); if (!preg_match('/[a-zA-Z]/', $new_alias)) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid Alias'), pht('The alias you provided (%s) must contain at least one ' . 'letter.', $debug_alias), $xaction); } if (preg_match('/[^a-z0-9]/i', $new_alias)) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid Alias'), pht('The alias you provided (%s) may only contain letters and ' . 'numbers.', $debug_alias), $xaction); } } } break; case PhabricatorPhurlURLTransaction::TYPE_URL: $missing = $this->validateIsEmptyTextField($object->getLongURL(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('URL path is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } foreach ($xactions as $xaction) { if ($xaction->getOldValue() != $xaction->getNewValue()) { $protocols = PhabricatorEnv::getEnvConfig('uri.allowed-protocols'); $uri = new PhutilURI($xaction->getNewValue()); if (!isset($protocols[$uri->getProtocol()])) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid URL'), pht('The protocol of the URL is invalid.'), null); } } } break; } return $errors; }
/** * Detect if a URI identifies a valid fetchable remote resource, throwing * a detailed message if it does not. * * A valid fetchable remote resource can be safely fetched using a request * originating on this server. This is a primarily an address check against * the outbound address blacklist. * * @param string URI to test. * @param list<string> Allowed protocols. * @return pair<string, string> Pre-resolved URI and domain. * @task uri */ public static function requireValidRemoteURIForFetch($uri, array $protocols) { $uri = new PhutilURI($uri); $proto = $uri->getProtocol(); if (!strlen($proto)) { throw new Exception(pht('URI "%s" is not a valid fetchable resource. A valid fetchable ' . 'resource URI must specify a protocol.', $uri)); } $protocols = array_fuse($protocols); if (!isset($protocols[$proto])) { throw new Exception(pht('URI "%s" is not a valid fetchable resource. A valid fetchable ' . 'resource URI must use one of these protocols: %s.', $uri, implode(', ', array_keys($protocols)))); } $domain = $uri->getDomain(); if (!strlen($domain)) { throw new Exception(pht('URI "%s" is not a valid fetchable resource. A valid fetchable ' . 'resource URI must specify a domain.', $uri)); } $addresses = gethostbynamel($domain); if (!$addresses) { throw new Exception(pht('URI "%s" is not a valid fetchable resource. The domain "%s" could ' . 'not be resolved.', $uri, $domain)); } foreach ($addresses as $address) { if (self::isBlacklistedOutboundAddress($address)) { throw new Exception(pht('URI "%s" is not a valid fetchable resource. The domain "%s" ' . 'resolves to the address "%s", which is blacklisted for ' . 'outbound requests.', $uri, $domain, $address)); } } $resolved_uri = clone $uri; $resolved_uri->setDomain(head($addresses)); return array($resolved_uri, $domain); }
public static function getRemoteURIProtocol($raw_uri) { $uri = new PhutilURI($raw_uri); if ($uri->getProtocol()) { return strtolower($uri->getProtocol()); } $git_uri = new PhutilGitURI($raw_uri); if (strlen($git_uri->getDomain()) && strlen($git_uri->getPath())) { return 'ssh'; } return null; }
public final function setCookie($name, $value, $expire = null) { // Ensure cookies are only set on the configured domain. $base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri'); $base_uri = new PhutilURI($base_uri); $base_domain = $base_uri->getDomain(); $base_protocol = $base_uri->getProtocol(); // The "Host" header may include a port number; if so, ignore it. We can't // use PhutilURI since there's no URI scheme. list($actual_host) = explode(':', $this->getHost(), 2); if ($base_domain != $actual_host) { throw new Exception("This install of Phabricator is configured as '{$base_domain}' but " . "you are accessing it via '{$actual_host}'. Access Phabricator via " . "the primary configured domain."); } if ($expire === null) { $expire = time() + 60 * 60 * 24 * 365 * 5; } $is_secure = $base_protocol == 'https'; setcookie($name, $value, $expire, $path = '/', $base_domain, $is_secure, $http_only = true); return $this; }