private function getBareHostAndPort($host) { // Split out port information, since the command-line client requires a // separate flag for the port. $uri = new PhutilURI('mysql://' . $host); if ($uri->getPort()) { $port = $uri->getPort(); $bare_hostname = $uri->getDomain(); } else { $port = null; $bare_hostname = $host; } return array($bare_hostname, $port); }
protected function getProxyCommand() { $uri = new PhutilURI($this->proxyURI); $username = AlmanacKeys::getClusterSSHUser(); if ($username === null) { throw new Exception(pht('Unable to determine the username to connect with when trying ' . 'to proxy an SSH request within the Phabricator cluster.')); } $port = $uri->getPort(); $host = $uri->getDomain(); $key_path = AlmanacKeys::getKeyPath('device.key'); if (!Filesystem::pathExists($key_path)) { throw new Exception(pht('Unable to proxy this SSH request within the cluster: this device ' . 'is not registered and has a missing device key (expected to ' . 'find key at "%s").', $key_path)); } $options = array(); $options[] = '-o'; $options[] = 'StrictHostKeyChecking=no'; $options[] = '-o'; $options[] = 'UserKnownHostsFile=/dev/null'; // This is suppressing "added <address> to the list of known hosts" // messages, which are confusing and irrelevant when they arise from // proxied requests. It might also be suppressing lots of useful errors, // of course. Ideally, we would enforce host keys eventually. $options[] = '-o'; $options[] = 'LogLevel=quiet'; // NOTE: We prefix the command with "@username", which the far end of the // connection will parse in order to act as the specified user. This // behavior is only available to cluster requests signed by a trusted // device key. return csprintf('ssh %Ls -l %s -i %s -p %s %s -- %s %Ls', $options, $username, $key_path, $port, $host, '@' . $this->getUser()->getUsername(), $this->getOriginalArguments()); }
/** * 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; }
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 function testURIParsing() { $uri = new PhutilURI('http://*****:*****@host:99/path/?query=value#fragment'); $this->assertEqual('http', $uri->getProtocol(), pht('protocol')); $this->assertEqual('user', $uri->getUser(), pht('user')); $this->assertEqual('pass', $uri->getPass(), pht('password')); $this->assertEqual('host', $uri->getDomain(), pht('domain')); $this->assertEqual('99', $uri->getPort(), pht('port')); $this->assertEqual('/path/', $uri->getPath(), pht('path')); $this->assertEqual(array('query' => 'value'), $uri->getQueryParams(), 'query params'); $this->assertEqual('fragment', $uri->getFragment(), pht('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(), pht('protocol')); $this->assertEqual('git', $uri->getUser(), pht('user')); $this->assertEqual('', $uri->getPass(), pht('password')); $this->assertEqual('example.com', $uri->getDomain(), pht('domain')); $this->assertEqual('', $uri->getPort(), 'port'); $this->assertEqual('/example/example.git', $uri->getPath(), pht('path')); $this->assertEqual(array(), $uri->getQueryParams(), pht('query parameters')); $this->assertEqual('', $uri->getFragment(), pht('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); // These tests are covering cases where cURL and parse_url() behavior // may differ in potentially dangerous ways. See T6755 for discussion. // In general, we defuse these attacks by emitting URIs which escape // special characters so that they are interpreted unambiguously by // cURL in the same way that parse_url() interpreted them. $uri = new PhutilURI('http://*****:*****@evil.com?@good.com'); $this->assertEqual('u', $uri->getUser()); $this->assertEqual('p', $uri->getPass()); $this->assertEqual('evil.com', $uri->getDomain()); $this->assertEqual('http://*****:*****@evil.com?%40good.com=', (string) $uri); $uri = new PhutilURI('http://good.com#u:p@evil.com/'); $this->assertEqual('good.com#u', $uri->getUser()); $this->assertEqual('p', $uri->getPass()); $this->assertEqual('evil.com', $uri->getDomain()); $this->assertEqual('http://good.com%23u:p@evil.com/', (string) $uri); $uri = new PhutilURI('http://good.com?u:p@evil.com/'); $this->assertEqual('', $uri->getUser()); $this->assertEqual('', $uri->getPass()); $this->assertEqual('good.com', $uri->getDomain()); $this->assertEqual('http://good.com?u%3Ap%40evil.com%2F=', (string) $uri); }
protected final function launch($debug = false) { $console = PhutilConsole::getConsole(); if ($debug) { $console->writeOut(pht("Starting Aphlict server in foreground...\n")); } else { Filesystem::writeFile($this->getPIDPath(), getmypid()); } $server_uri = PhabricatorEnv::getEnvConfig('notification.server-uri'); $server_uri = new PhutilURI($server_uri); $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); $client_uri = new PhutilURI($client_uri); $user = PhabricatorEnv::getEnvConfig('notification.user'); $log = PhabricatorEnv::getEnvConfig('notification.log'); $server_argv = array(); $server_argv[] = csprintf('--port=%s', $client_uri->getPort()); $server_argv[] = csprintf('--admin=%s', $server_uri->getPort()); $server_argv[] = csprintf('--host=%s', $server_uri->getDomain()); if ($user) { $server_argv[] = csprintf('--user=%s', $user); } if (!$debug) { $server_argv[] = csprintf('--log=%s', $log); } $command = csprintf('%s %s %C', $this->getNodeBinary(), dirname(__FILE__) . '/../../../../support/aphlict/server/aphlict_server.js', implode(' ', $server_argv)); if (!$debug) { declare (ticks=1); pcntl_signal(SIGINT, array($this, 'cleanup')); pcntl_signal(SIGTERM, array($this, 'cleanup')); } register_shutdown_function(array($this, 'cleanup')); if ($debug) { $console->writeOut("Launching server:\n\n \$ " . $command . "\n\n"); $err = phutil_passthru('%C', $command); $console->writeOut(">>> Server exited!\n"); exit($err); } else { while (true) { global $g_future; $g_future = new ExecFuture('exec %C', $command); $g_future->resolve(); // If the server exited, wait a couple of seconds and restart it. unset($g_future); sleep(2); } } }
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); }
} // Use always the version from the commandline if it is defined $next_version = isset($options['v']) ? (int) $options['v'] : null; $conf = DatabaseConfigurationProvider::getConfiguration(); if ($options['u']) { $conn_user = $options['u']; $conn_pass = $options['p']; } else { $conn_user = $conf->getUser(); $conn_pass = $conf->getPassword(); } $conn_host = $conf->getHost(); // Split out port information, since the command-line client requires a // separate flag for the port. $uri = new PhutilURI('mysql://' . $conn_host); if ($uri->getPort()) { $conn_port = $uri->getPort(); $conn_bare_hostname = $uri->getDomain(); } else { $conn_port = null; $conn_bare_hostname = $conn_host; } $conn = new AphrontMySQLDatabaseConnection(array('user' => $conn_user, 'pass' => $conn_pass, 'host' => $conn_host, 'database' => null)); try { $create_sql = <<<END CREATE DATABASE IF NOT EXISTS `phabricator_meta_data`; END; queryfx($conn, $create_sql); $create_sql = <<<END CREATE TABLE IF NOT EXISTS phabricator_meta_data.`schema_version` ( `version` INTEGER not null
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; }
list($err) = exec_manual('node -v'); if ($err) { throw new Exception('`node` is not in $PATH. You must install Node.js to run the Aphlict ' . 'server.'); } $server_uri = PhabricatorEnv::getEnvConfig('notification.server-uri'); $server_uri = new PhutilURI($server_uri); $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); $client_uri = new PhutilURI($client_uri); $user = PhabricatorEnv::getEnvConfig('notification.user'); $log = PhabricatorEnv::getEnvConfig('notification.log'); $g_pidfile = PhabricatorEnv::getEnvConfig('notification.pidfile'); $g_future = null; $foreground = $args->getArg('foreground'); // Build the argument list for the server itself. $server_argv = array(); $server_argv[] = csprintf('--port=%s', $client_uri->getPort()); $server_argv[] = csprintf('--admin=%s', $server_uri->getPort()); if ($user) { $server_argv[] = csprintf('--user=%s', $user); } if ($log) { $server_argv[] = csprintf('--log=%s', $log); } // >>> Foreground / Background ------------------------------------------------- // If we start in the foreground, we use phutil_passthru() below to show any // output from the server to the console, but this means *this* process won't // receive signals until the child exits. If we write our pid to the pidfile // and then another process starts, it will try to SIGTERM us but we won't // receive the signal. Since the effect is the same and this is simpler, just // ignore the pidfile if launched in `--foreground` mode; this is a debugging // mode anyway.
/** * Build a string describing the host for this request. * * This method builds strings in two modes: with explicit ports for request * signing (which always include the port number) and with implicit ports * for use in the "Host:" header of requests (which omit the port number if * the port is the same as the default port for the protocol). * * This implicit port behavior is similar to what browsers do, so it is less * likely to get us into trouble with webserver configurations. * * @param bool True to include the port explicitly. * @return string String describing the host for the request. */ private function newHostString($with_explicit_port) { $host = $this->getHost(); $uri = new PhutilURI($this->uri); $protocol = $uri->getProtocol(); $port = $uri->getPort(); $implicit_ports = array('https' => 443); $default_port = 80; $implicit_port = idx($implicit_ports, $protocol, $default_port); if ($with_explicit_port) { if (!$port) { $port = $implicit_port; } } else { if ($port == $implicit_port) { $port = null; } } if (!$port) { $result = $host; } else { $result = $host . ':' . $port; } return $result; }
protected function getBody() { $console = $this->getConsole(); $tabs = array(); foreach ($this->tabs as $name => $tab) { $tab_markup = phutil_render_tag('a', array('href' => idx($tab, 'href')), phutil_escape_html(idx($tab, 'name'))); $tab_markup = phutil_render_tag('td', array('class' => $name == $this->selectedTab ? 'phabricator-selected-tab' : null), $tab_markup); $tabs[] = $tab_markup; } $tabs = implode('', $tabs); $login_stuff = null; $request = $this->getRequest(); $user = null; if ($request) { $user = $request->getUser(); // NOTE: user may not be set here if we caught an exception early // in the execution workflow. if ($user && $user->getPHID()) { $login_stuff = phutil_render_tag('a', array('href' => '/p/' . $user->getUsername() . '/'), phutil_escape_html($user->getUsername())) . ' · ' . '<a href="/settings/">Settings</a>' . ' · ' . phabricator_render_form($user, array('action' => '/search/', 'method' => 'post', 'style' => 'display: inline'), '<input type="text" name="query" id="standard-search-box" />' . ' in ' . AphrontFormSelectControl::renderSelectTag($this->getSearchDefaultScope(), PhabricatorSearchScope::getScopeOptions(), array('name' => 'scope')) . ' ' . '<button>Search</button>'); } } $foot_links = array(); $version = PhabricatorEnv::getEnvConfig('phabricator.version'); $foot_links[] = phutil_escape_html('Phabricator ' . $version); $foot_links[] = '<a href="https://secure.phabricator.com/maniphest/task/create/">' . 'Report a Bug' . '</a>'; if (PhabricatorEnv::getEnvConfig('darkconsole.enabled') && !PhabricatorEnv::getEnvConfig('darkconsole.always-on')) { if ($console) { $link = javelin_render_tag('a', array('href' => '/~/', 'sigil' => 'workflow'), 'Disable DarkConsole'); } else { $link = javelin_render_tag('a', array('href' => '/~/', 'sigil' => 'workflow'), 'Enable DarkConsole'); } $foot_links[] = $link; } if ($user && $user->getPHID()) { // This ends up very early in tab order at the top of the page and there's // a bunch of junk up there anyway, just shove it down here. $foot_links[] = phabricator_render_form($user, array('action' => '/logout/', 'method' => 'post', 'style' => 'display: inline'), '<button class="link">Logout</button>'); } $foot_links = implode(' · ', $foot_links); $admin_class = null; if ($this->getIsAdminInterface()) { $admin_class = 'phabricator-admin-page-view'; } $custom_logo = null; $with_custom = null; $custom_conf = PhabricatorEnv::getEnvConfig('phabricator.custom.logo'); if ($custom_conf) { $with_custom = 'phabricator-logo-with-custom'; $custom_logo = phutil_render_tag('a', array('class' => 'logo-custom', 'href' => $custom_conf), ' '); } $notification_indicator = ''; $notification_dropdown = ''; $notification_container = ''; if (PhabricatorEnv::getEnvConfig('notification.enabled') && $user && $user->isLoggedIn()) { $aphlict_object_id = 'aphlictswfobject'; $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); $client_uri = new PhutilURI($client_uri); if ($client_uri->getDomain() == 'localhost') { $this_host = $this->getRequest()->getHost(); $this_host = new PhutilURI('http://' . $this_host . '/'); $client_uri->setDomain($this_host->getDomain()); } $enable_debug = PhabricatorEnv::getEnvConfig('notification.debug'); Javelin::initBehavior('aphlict-listen', array('id' => $aphlict_object_id, 'server' => $client_uri->getDomain(), 'port' => $client_uri->getPort(), 'debug' => $enable_debug, 'pageObjects' => array_fill_keys($this->pageObjects, true))); Javelin::initBehavior('aphlict-dropdown', array()); $notification_count = id(new PhabricatorFeedStoryNotification())->countUnread($user); $indicator_classes = array('phabricator-notification-indicator'); if ($notification_count) { $indicator_classes[] = 'phabricator-notification-indicator-unread'; } $notification_indicator = javelin_render_tag('div', array('id' => 'phabricator-notification-indicator', 'class' => implode(' ', $indicator_classes)), $notification_count); $notification_indicator = javelin_render_tag('div', array('id' => 'phabricator-notification-menu', 'class' => 'phabricator-icon-menu icon-menu-notifications', 'sigil' => 'aphlict-indicator'), $notification_indicator); $notification_indicator = javelin_render_tag('td', array('class' => 'phabricator-icon-menu-cell'), $notification_indicator); $notification_container = '<div id="aphlictswf-container" style="height:0px; width:0px;">' . '</div>'; $notification_dropdown = javelin_render_tag('div', array('sigil' => 'aphlict-dropdown', 'id' => 'phabricator-notification-dropdown', 'style' => 'display: none'), ''); } $header_chrome = null; $footer_chrome = null; if ($this->getShowChrome()) { $header_chrome = '<table class="phabricator-standard-header">' . '<tr>' . '<td class="phabricator-logo ' . $with_custom . '">' . $custom_logo . '<a class="logo-standard" href="/"> </a>' . '</td>' . $notification_indicator . '<td>' . '<table class="phabricator-primary-navigation">' . '<tr>' . '<th>' . phutil_render_tag('a', array('href' => $this->getBaseURI(), 'class' => 'phabricator-head-appname'), phutil_escape_html($this->getApplicationName())) . '</th>' . $tabs . '</tr>' . '</table>' . '</td>' . '<td class="phabricator-login-details">' . $login_stuff . '</td>' . '</tr>' . '</table>' . $notification_dropdown . $notification_container; $footer_chrome = '<div class="phabricator-page-foot">' . $foot_links . '</div>'; } $developer_warning = null; if (PhabricatorEnv::getEnvConfig('phabricator.show-error-callout') && DarkConsoleErrorLogPluginAPI::getErrors()) { $developer_warning = '<div class="aphront-developer-error-callout">' . 'This page raised PHP errors. Find them in DarkConsole ' . 'or the error log.' . '</div>'; } Javelin::initBehavior('device', array('id' => 'base-page')); $agent = idx($_SERVER, 'HTTP_USER_AGENT'); // Try to guess the device resolution based on UA strings to avoid a flash // of incorrectly-styled content. $device_guess = 'device-desktop'; if (preg_match('/iPhone|iPod/', $agent)) { $device_guess = 'device-phone'; } else { if (preg_match('/iPad/', $agent)) { $device_guess = 'device-tablet'; } } $classes = array('phabricator-standard-page', $admin_class, $device_guess); $classes = implode(' ', $classes); return ($console ? '<darkconsole />' : null) . $developer_warning . phutil_render_tag('div', array('id' => 'base-page', 'class' => $classes), $header_chrome . $this->bodyContent . '<div style="clear: both;"></div>') . $footer_chrome; }
protected function getTail() { $request = $this->getRequest(); $user = $request->getUser(); $tail = array(parent::getTail()); $response = CelerityAPI::getStaticResourceResponse(); if (PhabricatorEnv::getEnvConfig('notification.enabled')) { if ($user && $user->isLoggedIn()) { $aphlict_object_id = celerity_generate_unique_node_id(); $aphlict_container_id = celerity_generate_unique_node_id(); $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); $client_uri = new PhutilURI($client_uri); if ($client_uri->getDomain() == 'localhost') { $this_host = $this->getRequest()->getHost(); $this_host = new PhutilURI('http://' . $this_host . '/'); $client_uri->setDomain($this_host->getDomain()); } $map = CelerityResourceMap::getNamedInstance('phabricator'); $swf_uri = $response->getURI($map, 'rsrc/swf/aphlict.swf', true); $enable_debug = PhabricatorEnv::getEnvConfig('notification.debug'); $subscriptions = $this->pageObjects; if ($user) { $subscriptions[] = $user->getPHID(); } Javelin::initBehavior('aphlict-listen', array('id' => $aphlict_object_id, 'containerID' => $aphlict_container_id, 'server' => $client_uri->getDomain(), 'port' => $client_uri->getPort(), 'debug' => $enable_debug, 'swfURI' => $swf_uri, 'pageObjects' => array_fill_keys($this->pageObjects, true), 'subscriptions' => $subscriptions)); $tail[] = phutil_tag('div', array('id' => $aphlict_container_id, 'style' => 'position: absolute; width: 0; height: 0; overflow: hidden;'), ''); } } $tail[] = $response->renderHTMLFooter(); return $tail; }
private function getHostString() { $host = $this->getHost(); $uri = new PhutilURI($this->uri); $port = $uri->getPort(); if (!$port) { switch ($uri->getProtocol()) { case 'https': $port = 443; break; default: $port = 80; break; } } return $host . ':' . $port; }
protected function getTail() { $request = $this->getRequest(); $user = $request->getUser(); $container = null; if (PhabricatorEnv::getEnvConfig('notification.enabled') && $user->isLoggedIn()) { $aphlict_object_id = celerity_generate_unique_node_id(); $aphlict_container_id = celerity_generate_unique_node_id(); $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); $client_uri = new PhutilURI($client_uri); if ($client_uri->getDomain() == 'localhost') { $this_host = $this->getRequest()->getHost(); $this_host = new PhutilURI('http://' . $this_host . '/'); $client_uri->setDomain($this_host->getDomain()); } $enable_debug = PhabricatorEnv::getEnvConfig('notification.debug'); Javelin::initBehavior('aphlict-listen', array('id' => $aphlict_object_id, 'containerID' => $aphlict_container_id, 'server' => $client_uri->getDomain(), 'port' => $client_uri->getPort(), 'debug' => $enable_debug, 'pageObjects' => array_fill_keys($this->pageObjects, true))); $container = phutil_render_tag('div', array('id' => $aphlict_container_id, 'style' => 'position: absolute; width: 0; height: 0;'), ''); } $response = CelerityAPI::getStaticResourceResponse(); return $response->renderResourcesOfType('js') . $container . $response->renderHTMLFooter(); }
public function testAmbiguousURIs() { // It's important that this be detected as a Javascript URI, because that // is how browsers will treat it. $uri = new PhutilURI('javascript:evil'); $this->assertEqual('javascript', $uri->getProtocol()); // This is "wrong", in that the user probably intends for this to be a // Git-style URI, but we can not easily parse it as one without making the // "javascript" case above unsafe. $uri = new PhutilURI('localhost:todo.txt'); $this->assertEqual('localhost', $uri->getProtocol()); // These variants are unambiguous and safe. $uri = new PhutilURI('localhost.com:todo.txt'); $this->assertEqual('localhost.com', $uri->getDomain()); $uri = new PhutilURI('user@localhost:todo.txt'); $this->assertEqual('localhost', $uri->getDomain()); // This could either be a Git URI with relative path "22", or a normal URI // with port "22". We should assume it is a port number because this is // relatively common, while relative Git URIs pointing at numeric filenames // are bizarre. $uri = new PhutilURI('domain.com:22'); $this->assertEqual('domain.com', $uri->getDomain()); $this->assertEqual('22', $uri->getPort()); }
/** * 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; }
private function getServerArgv() { $ssl_key = PhabricatorEnv::getEnvConfig('notification.ssl-key'); $ssl_cert = PhabricatorEnv::getEnvConfig('notification.ssl-cert'); $server_uri = PhabricatorEnv::getEnvConfig('notification.server-uri'); $server_uri = new PhutilURI($server_uri); $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); $client_uri = new PhutilURI($client_uri); $log = $this->getLogPath(); $server_argv = array(); $server_argv[] = '--client-port=' . coalesce($this->clientPort, $client_uri->getPort()); $server_argv[] = '--admin-port=' . $server_uri->getPort(); $server_argv[] = '--admin-host=' . $server_uri->getDomain(); if ($ssl_key) { $server_argv[] = '--ssl-key=' . $ssl_key; } if ($ssl_cert) { $server_argv[] = '--ssl-cert=' . $ssl_cert; } $server_argv[] = '--log=' . $log; if ($this->clientHost) { $server_argv[] = '--client-host=' . $this->clientHost; } return $server_argv; }