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')); } } }
public static function newFromRawCorpus($corpus) { $obj = new ArcanistDifferentialCommitMessage(); $obj->rawCorpus = $corpus; // Parse older-style "123" fields, or newer-style full-URI fields. // TODO: Remove support for older-style fields. $match = null; if (preg_match('/^Differential Revision:\\s*(.*)/im', $corpus, $match)) { $revision_id = trim($match[1]); if (strlen($revision_id)) { if (preg_match('/^D?\\d+$/', $revision_id)) { $obj->revisionID = (int) trim($revision_id, 'D'); } else { $uri = new PhutilURI($revision_id); $path = $uri->getPath(); $path = trim($path, '/'); if (preg_match('/^D\\d+$/', $path)) { $obj->revisionID = (int) trim($path, 'D'); } else { throw new ArcanistUsageException("Invalid 'Differential Revision' field. The field should have a " . "Phabricator URI like 'http://phabricator.example.com/D123', " . "but has '{$match[1]}'."); } } } } $pattern = '/^git-svn-id:\\s*([^@]+)@(\\d+)\\s+(.*)$/m'; if (preg_match($pattern, $corpus, $match)) { $obj->gitSVNBaseRevision = $match[1] . '@' . $match[2]; $obj->gitSVNBasePath = $match[1]; $obj->gitSVNUUID = $match[3]; } return $obj; }
public function markupDocumentLink($matches) { $link = trim($matches[1]); $name = trim(idx($matches, 2, $link)); if (empty($matches[2])) { $name = explode('/', trim($name, '/')); $name = end($name); } $uri = new PhutilURI($link); $slug = $uri->getPath(); $fragment = $uri->getFragment(); $slug = PhabricatorSlug::normalize($slug); $slug = PhrictionDocument::getSlugURI($slug); $href = (string) id(new PhutilURI($slug))->setFragment($fragment); if ($this->getEngine()->getState('toc')) { $text = $name; } else { if ($this->getEngine()->isTextMode()) { return PhabricatorEnv::getProductionURI($href); } else { $text = $this->newTag('a', array('href' => $href, 'class' => 'phriction-link'), $name); } } return $this->getEngine()->storeText($text); }
/** * 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($domain_full_uri) { $example_domain = 'http://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($domain_full_uri); $domain = $uri->getDomain(); $protocol = $uri->getProtocol(); $path = $uri->getPath(); $supported_protocols = array('http', 'https'); if (!in_array($protocol, $supported_protocols)) { return array($label, pht('The custom domain should include a valid protocol in the URI ' . '(for example, "%s"). Valid protocols are "http" or "https".', $example_domain)); } if (strlen($path) && $path != '/') { 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($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; }
public function getWikiURI() { $config = $this->getProviderConfig(); $uri = $config->getProperty(self::PROPERTY_MEDIAWIKI_URI); $uri = new PhutilURI($uri); $normalized = $uri->getProtocol() . '://' . $uri->getDomain(); if ($uri->getPort() != 80 && $uri->getPort() != 443) { $normalized .= ':' . $uri->getPort(); } if (strlen($uri->getPath()) > 0 && $uri->getPath() !== '/') { $normalized .= $uri->getPath(); } if (substr($normalized, -1) == '/') { $normalized = substr($normalized, 0, -1); } return $normalized; }
public static function getGitHubPath($uri) { $uri_object = new PhutilURI($uri); $domain = $uri_object->getDomain(); $domain = phutil_utf8_strtolower($domain); switch ($domain) { case 'github.com': case 'www.github.com': return $uri_object->getPath(); default: return null; } }
/** * @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; } }
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/')); } } }
private static function parseRevisionIDFromURI($uri_string) { $uri = new PhutilURI($uri_string); $path = $uri->getPath(); $matches = null; if (preg_match('#^/D(\\d+)$#', $path, $matches)) { $id = (int) $matches[1]; $prod_uri = new PhutilURI(PhabricatorEnv::getProductionURI('/D' . $id)); // Make sure the URI is the same as our URI. Basically, we want to ignore // commits from other Phabricator installs. if ($uri->getDomain() == $prod_uri->getDomain()) { return $id; } $allowed_uris = PhabricatorEnv::getAllowedURIs('/D' . $id); foreach ($allowed_uris as $allowed_uri) { if ($uri_string == $allowed_uri) { return $id; } } } return null; }
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 processRequest() { $provider = $this->getOAuthProvider(); $oauth_info = $this->getOAuthInfo(); $request = $this->getRequest(); $errors = array(); $e_username = true; $e_email = true; $e_realname = true; $user = new PhabricatorUser(); $user->setUsername($provider->retrieveUserAccountName()); $user->setRealName($provider->retrieveUserRealName()); $user->setEmail($provider->retrieveUserEmail()); if ($request->isFormPost()) { $user->setUsername($request->getStr('username')); $username = $user->getUsername(); if (!strlen($user->getUsername())) { $e_username = '******'; $errors[] = 'Username is required.'; } else { if (!PhabricatorUser::validateUsername($username)) { $e_username = '******'; $errors[] = 'Username must consist of only numbers and letters.'; } else { $e_username = null; } } if ($user->getEmail() === null) { $user->setEmail($request->getStr('email')); if (!strlen($user->getEmail())) { $e_email = 'Required'; $errors[] = 'Email is required.'; } else { $e_email = null; } } if (!strlen($user->getRealName())) { $user->setRealName($request->getStr('realname')); if (!strlen($user->getRealName())) { $e_realname = 'Required'; $errors[] = 'Real name is required.'; } else { $e_realname = null; } } if (!$errors) { $image = $provider->retrieveUserProfileImage(); if ($image) { $file = PhabricatorFile::newFromFileData($image, array('name' => $provider->getProviderKey() . '-profile.jpg', 'authorPHID' => $user->getPHID())); $user->setProfileImagePHID($file->getPHID()); } try { $user->save(); $oauth_info->setUserID($user->getID()); $oauth_info->save(); $session_key = $user->establishSession('web'); $request->setCookie('phusr', $user->getUsername()); $request->setCookie('phsid', $session_key); return id(new AphrontRedirectResponse())->setURI('/'); } catch (AphrontQueryDuplicateKeyException $exception) { $same_username = id(new PhabricatorUser())->loadOneWhere('userName = %s', $user->getUserName()); $same_email = id(new PhabricatorUser())->loadOneWhere('email = %s', $user->getEmail()); if ($same_username) { $e_username = '******'; $errors[] = 'That username or email is not unique.'; } else { if ($same_email) { $e_email = 'Duplicate'; $errors[] = 'That email is not unique.'; } else { throw $exception; } } } } } $error_view = null; if ($errors) { $error_view = new AphrontErrorView(); $error_view->setTitle('Registration Failed'); $error_view->setErrors($errors); } // Strip the URI down to the path, because otherwise we'll trigger // external CSRF protection (by having a protocol in the form "action") // and generate a form with no CSRF token. $action_uri = new PhutilURI($provider->getRedirectURI()); $action_path = $action_uri->getPath(); $form = new AphrontFormView(); $form->addHiddenInput('token', $provider->getAccessToken())->addHiddenInput('expires', $oauth_info->getTokenExpires())->addHiddenInput('state', $this->getOAuthState())->setUser($request->getUser())->setAction($action_path)->appendChild(id(new AphrontFormTextControl())->setLabel('Username')->setName('username')->setValue($user->getUsername())->setError($e_username)); if ($provider->retrieveUserEmail() === null) { $form->appendChild(id(new AphrontFormTextControl())->setLabel('Email')->setName('email')->setValue($request->getStr('email'))->setError($e_email)); } if ($provider->retrieveUserRealName() === null) { $form->appendChild(id(new AphrontFormTextControl())->setLabel('Real Name')->setName('realname')->setValue($request->getStr('realname'))->setError($e_realname)); } $form->appendChild(id(new AphrontFormSubmitControl())->setValue('Create Account')); $panel = new AphrontPanelView(); $panel->setHeader('Create New Account'); $panel->setWidth(AphrontPanelView::WIDTH_FORM); $panel->appendChild($form); return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Create New Account')); }
private function getPathFromSubversionURI($uri_string) { $uri = new PhutilURI($uri_string); $proto = $uri->getProtocol(); if ($proto !== 'svn+ssh') { throw new Exception(pht('Protocol for URI "%s" MUST be "%s".', $uri_string, 'svn+ssh')); } $path = $uri->getPath(); // Subversion presumably deals with this, but make sure there's nothing // sketchy going on with the URI. if (preg_match('(/\\.\\./)', $path)) { throw new Exception(pht('String "%s" is invalid in path specification "%s".', '/../', $uri_string)); } $path = $this->normalizeSVNPath($path); return $path; }
public function processRequest() { $provider = $this->getLDAProvider(); $ldap_info = $this->getLDAPInfo(); $request = $this->getRequest(); $errors = array(); $e_username = true; $e_email = true; $e_realname = true; $user = new PhabricatorUser(); $user->setUsername(); $user->setRealname($provider->retrieveUserRealName()); $new_email = $provider->retrieveUserEmail(); if ($new_email) { // If the user's LDAP provider account has an email address but the // email address domain is not allowed by the Phabricator configuration, // we just pretend the provider did not supply an address. // // For instance, if the user uses LDAP Auth and their email address // is "*****@*****.**" but Phabricator is configured to require users // use "@company.com" addresses, we show a prompt below and tell the user // to provide their "@company.com" address. They can still use the LDAP // account to login, they just need to associate their account with an // allowed address. // // If the email address is fine, we just use it and don't prompt the user. if (!PhabricatorUserEmail::isAllowedAddress($new_email)) { $new_email = null; } } $show_email_input = $new_email === null; if ($request->isFormPost()) { $user->setUsername($request->getStr('username')); $username = $user->getUsername(); if (!strlen($user->getUsername())) { $e_username = '******'; $errors[] = 'Username is required.'; } else { if (!PhabricatorUser::validateUsername($username)) { $e_username = '******'; $errors[] = PhabricatorUser::describeValidUsername(); } else { $e_username = null; } } if (!$new_email) { $new_email = trim($request->getStr('email')); if (!$new_email) { $e_email = 'Required'; $errors[] = 'Email is required.'; } else { $e_email = null; } } if ($new_email) { if (!PhabricatorUserEmail::isAllowedAddress($new_email)) { $e_email = 'Invalid'; $errors[] = PhabricatorUserEmail::describeAllowedAddresses(); } } if (!strlen($user->getRealName())) { $user->setRealName($request->getStr('realname')); if (!strlen($user->getRealName())) { $e_realname = 'Required'; $errors[] = 'Real name is required.'; } else { $e_realname = null; } } if (!$errors) { try { // NOTE: We don't verify LDAP email addresses by default because // LDAP providers might associate email addresses with accounts that // haven't actually verified they own them. We could selectively // auto-verify some providers that we trust here, but the stakes for // verifying an email address are high because having a corporate // address at a company is sometimes the key to the castle. $email_obj = id(new PhabricatorUserEmail())->setAddress($new_email)->setIsVerified(0); id(new PhabricatorUserEditor())->setActor($user)->createNewUser($user, $email_obj); $ldap_info->setUserID($user->getID()); $ldap_info->save(); $session_key = $user->establishSession('web'); $request->setCookie('phusr', $user->getUsername()); $request->setCookie('phsid', $session_key); $email_obj->sendVerificationEmail($user); return id(new AphrontRedirectResponse())->setURI('/'); } catch (AphrontQueryDuplicateKeyException $exception) { $same_username = id(new PhabricatorUser())->loadOneWhere('userName = %s', $user->getUserName()); $same_email = id(new PhabricatorUserEmail())->loadOneWhere('address = %s', $new_email); if ($same_username) { $e_username = '******'; $errors[] = 'That username or email is not unique.'; } else { if ($same_email) { $e_email = 'Duplicate'; $errors[] = 'That email is not unique.'; } else { throw $exception; } } } } } $error_view = null; if ($errors) { $error_view = new AphrontErrorView(); $error_view->setTitle('Registration Failed'); $error_view->setErrors($errors); } // Strip the URI down to the path, because otherwise we'll trigger // external CSRF protection (by having a protocol in the form "action") // and generate a form with no CSRF token. $action_uri = new PhutilURI('/ldap/login/'); $action_path = $action_uri->getPath(); $form = new AphrontFormView(); $form->setUser($request->getUser())->setAction($action_path)->appendChild(id(new AphrontFormTextControl())->setLabel('Username')->setName('username')->setValue($user->getUsername())->setError($e_username)); $form->appendChild(id(new AphrontFormPasswordControl())->setLabel('Password')->setName('password')); if ($show_email_input) { $form->appendChild(id(new AphrontFormTextControl())->setLabel('Email')->setName('email')->setValue($request->getStr('email'))->setError($e_email)); } if ($provider->retrieveUserRealName() === null) { $form->appendChild(id(new AphrontFormTextControl())->setLabel('Real Name')->setName('realname')->setValue($request->getStr('realname'))->setError($e_realname)); } $form->appendChild(id(new AphrontFormSubmitControl())->setValue('Create Account')); $panel = new AphrontPanelView(); $panel->setHeader('Create New Account'); $panel->setWidth(AphrontPanelView::WIDTH_FORM); $panel->appendChild($form); return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Create New Account')); }
public function processRequest() { $request = $this->getRequest(); $uri = $request->getStr('uri'); $id = $request->getStr('id'); $repositories = id(new PhabricatorRepository())->loadAll(); if ($uri) { $uri_path = id(new PhutilURI($uri))->getPath(); $matches = array(); // Try to figure out which tracked repository this external lives in by // comparing repository metadata. We look for an exact match, but accept // a partial match. foreach ($repositories as $key => $repository) { $remote_uri = new PhutilURI($repository->getRemoteURI()); if ($remote_uri->getPath() == $uri_path) { $matches[$key] = 1; } if ($repository->getPublicRemoteURI() == $uri) { $matches[$key] = 2; } if ($repository->getRemoteURI() == $uri) { $matches[$key] = 3; } } arsort($matches); $best_match = head_key($matches); if ($best_match) { $repository = $repositories[$best_match]; $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repository->getCallsign(), 'branch' => $repository->getDefaultBranch(), 'commit' => $id)); return id(new AphrontRedirectResponse())->setURI($redirect); } } // TODO: This is a rare query but does a table scan, add a key? $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere('commitIdentifier = %s', $id); if (empty($commits)) { $desc = null; if ($uri) { $desc = phutil_escape_html($uri) . ', at '; } $desc .= phutil_escape_html($id); $content = id(new AphrontErrorView())->setTitle('Unknown External')->setSeverity(AphrontErrorView::SEVERITY_WARNING)->appendChild("<p>This external ({$desc}) does not appear in any tracked " . "repository. It may exist in an untracked repository that " . "Diffusion does not know about.</p>"); } else { if (count($commits) == 1) { $commit = head($commits); $repo = $repositories[$commit->getRepositoryID()]; $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier())); return id(new AphrontRedirectResponse())->setURI($redirect); } else { $rows = array(); foreach ($commits as $commit) { $repo = $repositories[$commit->getRepositoryID()]; $href = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier())); $rows[] = array(phutil_render_tag('a', array('href' => $href), phutil_escape_html('r' . $repo->getCallsign() . $commit->getCommitIdentifier())), phutil_escape_html($commit->loadCommitData()->getSummary())); } $table = new AphrontTableView($rows); $table->setHeaders(array('Commit', 'Description')); $table->setColumnClasses(array('pri', 'wide')); $content = new AphrontPanelView(); $content->setHeader('Multiple Matching Commits'); $content->setCaption('This external reference matches multiple known commits.'); $content->appendChild($table); } } return $this->buildStandardPageResponse($content, array('title' => 'Unresolvable External')); }
/** * Extract the revision ID from a commit message. * * @param string Raw commit message. * @return int|null Revision ID, if the commit message contains one. */ private function parseRevisionIDFromRawCorpus($corpus) { $match = null; if (!preg_match('/^Differential Revision:\\s*(.+)/im', $corpus, $match)) { return null; } $revision_value = trim($match[1]); $revision_pattern = '/^[dD]([1-9]\\d*)\\z/'; // Accept a bare revision ID like "D123". if (preg_match($revision_pattern, $revision_value, $match)) { return (int) $match[1]; } // Otherwise, try to find a full URI. $uri = new PhutilURI($revision_value); $path = $uri->getPath(); $path = trim($path, '/'); if (preg_match($revision_pattern, $path, $match)) { return (int) $match[1]; } throw new ArcanistUsageException(pht('Invalid "Differential Revision" field in commit message. This field ' . 'should have a revision identifier like "%s" or a Phabricator URI ' . 'like "%s", but has "%s".', 'D123', 'https://phabricator.example.com/D123', $revision_value)); }
private static function getPathFromGitURI($raw_uri) { $uri = new PhutilURI($raw_uri); if ($uri->getProtocol()) { return $uri->getPath(); } $uri = new PhutilGitURI($raw_uri); if ($uri->getDomain()) { return $uri->getPath(); } return $raw_uri; }
private function makeInternalURI($uri_string) { $uri = new PhutilURI($uri_string); $proto = $uri->getProtocol(); if ($proto !== 'svn+ssh') { throw new Exception(pht('Protocol for URI "%s" MUST be "svn+ssh".', $uri_string)); } $path = $uri->getPath(); // Subversion presumably deals with this, but make sure there's nothing // skethcy going on with the URI. if (preg_match('(/\\.\\./)', $path)) { throw new Exception(pht('String "/../" is invalid in path specification "%s".', $uri_string)); } $repository = $this->loadRepository($path); $path = preg_replace('(^/diffusion/[A-Z]+)', rtrim($repository->getLocalPath(), '/'), $path); if (preg_match('(^/diffusion/[A-Z]+/\\z)', $path)) { $path = rtrim($path, '/'); } $uri->setPath($path); // If this is happening during the handshake, these are the base URIs for // the request. if ($this->externalBaseURI === null) { $pre = (string) id(clone $uri)->setPath(''); $this->externalBaseURI = $pre . '/diffusion/' . $repository->getCallsign(); $this->internalBaseURI = $pre . rtrim($repository->getLocalPath(), '/'); } return (string) $uri; }
private function getRawHTTPCloneURIObject() { $uri = PhabricatorEnv::getProductionURI($this->getURI()); $uri = new PhutilURI($uri); if ($this->isGit()) { $uri->setPath($uri->getPath() . $this->getCloneName() . '.git'); } else { if ($this->isHg()) { $uri->setPath($uri->getPath() . $this->getCloneName() . '/'); } } return $uri; }
public function handleRequest(AphrontRequest $request) { $uri = $request->getStr('uri'); $id = $request->getStr('id'); $repositories = id(new PhabricatorRepositoryQuery())->setViewer($request->getUser())->execute(); if ($uri) { $uri_path = id(new PhutilURI($uri))->getPath(); $matches = array(); // Try to figure out which tracked repository this external lives in by // comparing repository metadata. We look for an exact match, but accept // a partial match. foreach ($repositories as $key => $repository) { $remote_uri = new PhutilURI($repository->getRemoteURI()); if ($remote_uri->getPath() == $uri_path) { $matches[$key] = 1; } if ($repository->getPublicCloneURI() == $uri) { $matches[$key] = 2; } if ($repository->getRemoteURI() == $uri) { $matches[$key] = 3; } } arsort($matches); $best_match = head_key($matches); if ($best_match) { $repository = $repositories[$best_match]; $redirect = $repository->generateURI(array('action' => 'browse', 'branch' => $repository->getDefaultBranch(), 'commit' => $id)); return id(new AphrontRedirectResponse())->setURI($redirect); } } // TODO: This is a rare query but does a table scan, add a key? $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere('commitIdentifier = %s', $id); if (empty($commits)) { $desc = null; if (strlen($uri)) { $desc = pht('"%s", at "%s"', $uri, $id); } else { $desc = pht('"%s"', $id); } $content = id(new PHUIInfoView())->setTitle(pht('Unknown External'))->setSeverity(PHUIInfoView::SEVERITY_WARNING)->appendChild(phutil_tag('p', array(), pht('This external (%s) does not appear in any tracked ' . 'repository. It may exist in an untracked repository that ' . 'Diffusion does not know about.', $desc))); } else { if (count($commits) == 1) { $commit = head($commits); $repo = $repositories[$commit->getRepositoryID()]; $redirect = $repo->generateURI(array('action' => 'browse', 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier())); return id(new AphrontRedirectResponse())->setURI($redirect); } else { $rows = array(); foreach ($commits as $commit) { $repo = $repositories[$commit->getRepositoryID()]; $href = $repo->generateURI(array('action' => 'browse', 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier())); $rows[] = array(phutil_tag('a', array('href' => $href), $commit->getURI()), $commit->loadCommitData()->getSummary()); } $table = new AphrontTableView($rows); $table->setHeaders(array(pht('Commit'), pht('Description'))); $table->setColumnClasses(array('pri', 'wide')); $caption = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->appendChild(pht('This external reference matches multiple known commits.')); $content = new PHUIObjectBoxView(); $content->setHeaderText(pht('Multiple Matching Commits')); $content->setInfoView($caption); $content->setTable($table); } } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('External')); return $this->newPage()->setTitle(pht('Unresolvable External'))->setCrumbs($crumbs)->appendChild($content); }
/** * 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 static function getJIRAIssueBrowseURIFromJIRARestURI($uri, $object_id) { $uri = new PhutilURI($uri); // The JIRA install might not be at the domain root, so we may need to // keep an initial part of the path, like "/jira/". Find the API specific // part of the URI, strip it off, then replace it with the web version. $path = $uri->getPath(); $pos = strrpos($path, 'rest/api/2/issue/'); if ($pos === false) { return null; } $path = substr($path, 0, $pos); $path = $path . 'browse/' . $object_id; $uri->setPath($path); return (string) $uri; }
private function getPath(HTTPSFuture $future) { $uri = new PhutilURI($future->getURI()); return $uri->getPath(); }
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()); }
public function testGitURIParsing() { $uri = new PhutilURI('git@host.com:path/to/something'); $this->assertEqual('ssh', $uri->getProtocol()); $this->assertEqual('git', $uri->getUser()); $this->assertEqual('host.com', $uri->getDomain()); $this->assertEqual('path/to/something', $uri->getPath()); $this->assertEqual('git@host.com:path/to/something', (string) $uri); $uri = new PhutilURI('host.com:path/to/something'); $this->assertEqual('ssh', $uri->getProtocol()); $this->assertEqual('', $uri->getUser()); $this->assertEqual('host.com', $uri->getDomain()); $this->assertEqual('path/to/something', $uri->getPath()); $this->assertEqual('host.com:path/to/something', (string) $uri); $uri_1 = new PhutilURI('host.com:path/to/something'); $uri_2 = new PhutilURI($uri_1); $this->assertEqual((string) $uri_1, (string) $uri_2); }
/** * Get the repository's HTTP clone/checkout URI, if one exists. */ public function getHTTPCloneURIObject() { if (!$this->isHosted()) { if ($this->shouldUseHTTP()) { return $this->getRemoteURIObject(); } else { return null; } } $serve_http = $this->getServeOverHTTP(); if ($serve_http === self::SERVE_OFF) { return null; } $uri = PhabricatorEnv::getProductionURI($this->getURI()); $uri = new PhutilURI($uri); if ($this->isGit()) { $uri->setPath($uri->getPath() . $this->getCloneName() . '.git'); } else { if ($this->isHg()) { $uri->setPath($uri->getPath() . $this->getCloneName() . '/'); } } return $uri; }
public function didMarkupText() { $engine = $this->getEngine(); $metadata = $engine->getTextMetadata(self::KEY_RULE_PHRICTION_LINK, array()); if (!$metadata) { return; } $slugs = ipull($metadata, 'link'); foreach ($slugs as $key => $slug) { $slugs[$key] = PhabricatorSlug::normalize($slug); } // We have to make two queries here to distinguish between // documents the user can't see, and documents that don't // exist. $visible_documents = id(new PhrictionDocumentQuery())->setViewer($engine->getConfig('viewer'))->withSlugs($slugs)->needContent(true)->execute(); $existant_documents = id(new PhrictionDocumentQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withSlugs($slugs)->execute(); $visible_documents = mpull($visible_documents, null, 'getSlug'); $existant_documents = mpull($existant_documents, null, 'getSlug'); foreach ($metadata as $spec) { $link = $spec['link']; $slug = PhabricatorSlug::normalize($link); $name = $spec['explicitName']; $class = 'phriction-link'; // If the name is something meaningful to humans, we'll render this // in text as: "Title" <link>. Otherwise, we'll just render: <link>. $is_interesting_name = (bool) strlen($name); if (idx($existant_documents, $slug) === null) { // The target document doesn't exist. if ($name === null) { $name = explode('/', trim($link, '/')); $name = end($name); } $class = 'phriction-link-missing'; } else { if (idx($visible_documents, $slug) === null) { // The document exists, but the user can't see it. if ($name === null) { $name = explode('/', trim($link, '/')); $name = end($name); } $class = 'phriction-link-lock'; } else { if ($name === null) { // Use the title of the document if no name is set. $name = $visible_documents[$slug]->getContent()->getTitle(); $is_interesting_name = true; } } } $uri = new PhutilURI($link); $slug = $uri->getPath(); $slug = PhabricatorSlug::normalize($slug); $slug = PhrictionDocument::getSlugURI($slug); $anchor = idx($spec, 'anchor'); $href = (string) id(new PhutilURI($slug))->setFragment($anchor); $text_mode = $this->getEngine()->isTextMode(); $mail_mode = $this->getEngine()->isHTMLMailMode(); if ($this->getEngine()->getState('toc')) { $text = $name; } else { if ($text_mode || $mail_mode) { $href = PhabricatorEnv::getProductionURI($href); if ($is_interesting_name) { $text = pht('"%s" <%s>', $name, $href); } else { $text = pht('<%s>', $href); } } else { if ($class === 'phriction-link-lock') { $name = array($this->newTag('i', array('class' => 'phui-icon-view phui-font-fa fa-lock'), ''), ' ', $name); } $text = $this->newTag('a', array('href' => $href, 'class' => $class), $name); } } $this->getEngine()->overwriteStoredText($spec['token'], $text); } }