Example #1
0
 /**
  * normalize url and authentication info
  * @param string $origin domain text
  * @param string $url
  * @param IO/IOInterface $io
  */
 public function __construct($origin, $url, IO\IOInterface $io)
 {
     // normalize github origin
     if (substr($origin, -10) === 'github.com') {
         $origin = 'github.com';
         $this->special = 'github';
     }
     $this->origin = $origin;
     $this->importURL($url);
     if ($this->username && $this->password) {
         $io->setAuthentication($origin, $this->username, $this->password);
     } elseif ($io->hasAuthentication($origin)) {
         $auth = $io->getAuthentication($origin);
         $this->username = $auth['username'];
         $this->password = $auth['password'];
     }
 }
Example #2
0
 /**
  * @param $io
  * @param bool $useRedirector
  * @param $githubDomains
  * @param $gitlabDomains
  */
 protected function setupAuthentication(IO\IOInterface $io, $useRedirector, array $githubDomains, array $gitlabDomains)
 {
     if (preg_match('/\\.github\\.com$/', $this->host)) {
         $authKey = 'github.com';
         if ($useRedirector) {
             if ($this->host === 'api.github.com' && preg_match('%^/repos(/[^/]+/[^/]+/)zipball(.+)$%', $this->path, $_)) {
                 $this->host = 'codeload.github.com';
                 $this->path = $_[1] . 'legacy.zip' . $_[2];
             }
         }
     } else {
         $authKey = $this->host;
     }
     if (!$io->hasAuthentication($authKey)) {
         if ($this->user || $this->pass) {
             $io->setAuthentication($authKey, $this->user, $this->pass);
         } else {
             return;
         }
     }
     $auth = $io->getAuthentication($authKey);
     // is github
     if (in_array($authKey, $githubDomains) && 'x-oauth-basic' === $auth['password']) {
         $this->addParam('access_token', $auth['username']);
         $this->user = $this->pass = null;
         return;
     }
     // is gitlab
     if (in_array($authKey, $gitlabDomains) && 'oauth2' === $auth['password']) {
         $this->addHeader('authorization', 'Bearer ' . $auth['username']);
         $this->user = $this->pass = null;
         return;
     }
     // others, includes bitbucket
     $this->user = $auth['username'];
     $this->pass = $auth['password'];
 }
Example #3
0
 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
 {
     if (preg_match('{^(http|git):}i', $url) && $this->config->get('secure-http')) {
         throw new TransportException("Your configuration does not allow connection to {$url}. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
     }
     if ($initialClone) {
         $origCwd = $cwd;
         $cwd = null;
     }
     if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
         throw new \InvalidArgumentException('The source URL ' . $url . ' is invalid, ssh URLs should have a port number after ":".' . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.');
     }
     if (!$initialClone) {
         // capture username/password from URL if there is one
         $this->process->execute('git remote -v', $output, $cwd);
         if (preg_match('{^(?:composer|origin)\\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
             $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2]));
         }
     }
     $protocols = $this->config->get('github-protocols');
     if (!is_array($protocols)) {
         throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
     }
     // public github, autoswitch protocols
     if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
         $messages = array();
         foreach ($protocols as $protocol) {
             if ('ssh' === $protocol) {
                 $protoUrl = "git@" . $match[1] . ":" . $match[2];
             } else {
                 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
             }
             if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
                 return;
             }
             $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
             if ($initialClone) {
                 $this->filesystem->removeDirectory($origCwd);
             }
         }
         // failed to checkout, first check git accessibility
         $this->throwException('Failed to clone ' . self::sanitizeUrl($url) . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
     }
     // if we have a private github url and the ssh protocol is disabled then we skip it and directly fallback to https
     $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\\.git$}i', $url) && !in_array('ssh', $protocols, true);
     $command = call_user_func($commandCallable, $url);
     $auth = null;
     if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
         // private github repository without git access, try https with auth
         if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\\.git$}i', $url, $match)) {
             if (!$this->io->hasAuthentication($match[1])) {
                 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
                 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
                 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
                     $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
                 }
             }
             if ($this->io->hasAuthentication($match[1])) {
                 $auth = $this->io->getAuthentication($match[1]);
                 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
                 $command = call_user_func($commandCallable, $authUrl);
                 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
                     return;
                 }
             }
         } elseif ($this->isAuthenticationFailure($url, $match)) {
             // private non-github repo that failed to authenticate
             if (strpos($match[2], '@')) {
                 list($authParts, $match[2]) = explode('@', $match[2], 2);
             }
             $storeAuth = false;
             if ($this->io->hasAuthentication($match[2])) {
                 $auth = $this->io->getAuthentication($match[2]);
             } elseif ($this->io->isInteractive()) {
                 $defaultUsername = null;
                 if (isset($authParts) && $authParts) {
                     if (false !== strpos($authParts, ':')) {
                         list($defaultUsername, ) = explode(':', $authParts, 2);
                     } else {
                         $defaultUsername = $authParts;
                     }
                 }
                 $this->io->writeError('    Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
                 $auth = array('username' => $this->io->ask('      Username: '******'password' => $this->io->askAndHideAnswer('      Password: '******'store-auths');
             }
             if ($auth) {
                 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
                 $command = call_user_func($commandCallable, $authUrl);
                 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
                     $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
                     $authHelper = new AuthHelper($this->io, $this->config);
                     $authHelper->storeAuth($match[2], $storeAuth);
                     return;
                 }
             }
         }
         if ($initialClone) {
             $this->filesystem->removeDirectory($origCwd);
         }
         $this->throwException('Failed to execute ' . self::sanitizeUrl($command) . "\n\n" . $this->process->getErrorOutput(), $url);
     }
 }
 public function promptAuth(HttpGetResponse $res, CConfig $config, IO\IOInterface $io)
 {
     $httpCode = $res->info['http_code'];
     // 404s are only handled for github
     if (404 === $httpCode) {
         return false;
     }
     // fail if the console is not interactive
     if (!$io->isInteractive()) {
         switch ($httpCode) {
             case 401:
                 $message = "The '{$this->getURL()}' URL required authentication.\nYou must be using the interactive console to authenticate";
                 break;
             case 403:
                 $message = "The '{$this->getURL()}' URL could not be accessed.";
                 break;
         }
         throw new Downloader\TransportException($message, $httpCode);
     }
     // fail if we already have auth
     if ($io->hasAuthentication($this->origin)) {
         throw new Downloader\TransportException("Invalid credentials for '{$this->getURL()}', aborting.", $httpCode);
     }
     $io->overwrite("    Authentication required (<info>{$this->host}</info>):");
     $username = $io->ask('      Username: '******'      Password: ');
     $io->setAuthentication($this->origin, $username, $password);
     return true;
 }
Example #5
0
 public function notifyInstalls(IOInterface $io)
 {
     foreach ($this->notifiablePackages as $repoUrl => $packages) {
         $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
         if ($io->hasAuthentication($repositoryName)) {
             $auth = $io->getAuthentication($repositoryName);
             $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
             $authHeader = 'Authorization: Basic ' . $authStr;
         }
         // non-batch API, deprecated
         if (strpos($repoUrl, '%package%')) {
             foreach ($packages as $package) {
                 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
                 $params = array('version' => $package->getPrettyVersion(), 'version_normalized' => $package->getVersion());
                 $opts = array('http' => array('method' => 'POST', 'header' => array('Content-type: application/x-www-form-urlencoded'), 'content' => http_build_query($params, '', '&'), 'timeout' => 3));
                 if (isset($authHeader)) {
                     $opts['http']['header'][] = $authHeader;
                 }
                 $context = StreamContextFactory::getContext($url, $opts);
                 @file_get_contents($url, false, $context);
             }
             continue;
         }
         $postData = array('downloads' => array());
         foreach ($packages as $package) {
             $postData['downloads'][] = array('name' => $package->getPrettyName(), 'version' => $package->getVersion());
         }
         $opts = array('http' => array('method' => 'POST', 'header' => array('Content-Type: application/json'), 'content' => json_encode($postData), 'timeout' => 6));
         if (isset($authHeader)) {
             $opts['http']['header'][] = $authHeader;
         }
         $context = StreamContextFactory::getContext($repoUrl, $opts);
         @file_get_contents($repoUrl, false, $context);
     }
     $this->reset();
 }