protected function processParams($params, $actualParams)
 {
     if (!$this->io->isInteractive()) {
         return $actualParams;
     }
     $this->io->write('<comment>Some parameters are missing. Please provide them.</comment>');
     foreach ($params as $key => $value) {
         $result = $this->io->ask(sprintf("<question>%s</question> (<comment>%s</comment>): ", $this->messages[$key], $value));
         if (!empty($result)) {
             $actualParams[$key] = $result;
         }
     }
     return $actualParams;
 }
Example #2
0
 /**
  * Print choices
  *
  * @param   string  $label
  * @param   array   $choices
  * @return  void
  */
 public function printChoices($label, array $choices)
 {
     if ($this->io->isInteractive() && !empty($choices)) {
         $this->io->write(static::PADDING . $label);
         foreach ($choices as $choice => $description) {
             $this->io->write(static::PADDING . " * <info>{$choice}</info>: {$description}");
         }
     }
 }
Example #3
0
 /**
  * Get actual params and display Q&A.
  *
  * @param  array $expectedParams
  * @param  array $actualValues
  * @param  string $realFile
  * @return array $values
  *
  * @since 0.0.3
  */
 private function getParams(array $expectedParams, array $actualValues, $realFile)
 {
     // Simply use the expectedParams value as default for the missing params.
     if (!$this->io->isInteractive()) {
         $this->io->write(sprintf("<comment>Interactions are not permitted.\nPlease, edit your \"%s\" file manually to define properly your parameters.</comment>\n", $realFile));
         return array_replace($expectedParams, $actualValues);
     }
     // Get forgotten keys
     $keys = $this->keyMatch($expectedParams, $actualValues);
     // Iterate on expectedParams and display Q&A
     return $this->treatParams($keys);
 }
Example #4
0
 /**
  * Repositories requests credentials, let's put them in.
  *
  * @throws \RuntimeException
  * @return \Composer\Util\Svn
  */
 protected function doAuthDance()
 {
     // cannot ask for credentials in non interactive mode
     if (!$this->io->isInteractive()) {
         throw new \RuntimeException('can not ask for authentication in non interactive mode');
     }
     $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
     $this->hasAuth = true;
     $this->credentials['username'] = $this->io->ask("Username: "******"Password: "******"Should Subversion cache these credentials? (yes/no) ", true);
     return $this;
 }
Example #5
0
 public function promptAuth(HttpGetResponse $res, CConfig $config, IO\IOInterface $io)
 {
     $httpCode = $res->info['http_code'];
     $message = "\nCould not fetch {$this->getURL()}, please create a GitHub OAuth token ";
     if (404 === $httpCode) {
         $message .= 'to access private repos';
     } else {
         $message .= 'to go over the API rate limit';
     }
     $github = new Util\GitHub($io, $config, null);
     if ($github->authorizeOAuth($this->origin)) {
         return true;
     }
     if ($io->isInteractive() && $github->authorizeOAuthInteractively($this->origin, $message)) {
         return true;
     }
     throw new Downloader\TransportException("Could not authenticate against {$this->origin}", 401);
 }
Example #6
0
 /**
  * Asks the user for confirmation on some action to be taken.
  *
  * @param IOInterface $io IO interface to write to console.
  * @param string $question
  * @param boolean $default Default answer
  * @return boolean
  */
 protected static function confirmAction(IOInterface $io, $question, $default = true)
 {
     if (!$io->isInteractive()) {
         return $default;
     }
     $validator = function ($arg) {
         if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
             return $arg;
         }
         throw new Exception('This is not a valid answer. Please choose Y or n.');
     };
     $defaultAnswer = $default ? 'Y' : 'n';
     $msg = '<question>' . $question . '</question> ' . '<info>(Default to ' . $defaultAnswer . ')</info> ' . '[<comment>Y,n</comment>]: ';
     $answer = $io->askAndValidate($msg, $validator, 10, $defaultAnswer);
     if (in_array($answer, ['Y', 'y'])) {
         return true;
     }
     return $default;
 }
 /**
  * Prompt for missing values. If IO isn't interactive, use all defaults.
  *
  * @param array $missing List 
  * @param boolean $isStarted Shared state if the header was already outputed.
  * @return array
  */
 protected function processIO(array $missing, &$isStarted = false, $prefix = '')
 {
     // Simply use the expectedParams value as default for the missing params.
     if (!$this->io->isInteractive()) {
         return $missing;
     }
     foreach ($missing as $key => $default) {
         $fqk = $prefix . $key;
         if (is_array($default)) {
             $missing[$key] = $this->processIO($default, $isStarted, $fqk . '.');
             continue;
         }
         if (!$isStarted) {
             $isStarted = true;
             $this->io->write(sprintf('<comment>Some %s parameters are missing. Please provide them.</comment>', $this->name));
         }
         $missing[$key] = $this->askIO($fqk, $default);
     }
     return $missing;
 }
Example #8
0
 private static function getParams(IOInterface $io, array $expectedParams, array $actualParams)
 {
     // Simply use the expectedParams value as default for the missing params.
     if (!$io->isInteractive()) {
         return array_replace($expectedParams, $actualParams);
     }
     $isStarted = false;
     foreach ($expectedParams as $key => $message) {
         if (array_key_exists($key, $actualParams)) {
             continue;
         }
         if (!$isStarted) {
             $isStarted = true;
             $io->write('<comment>Some parameters are missing. Please provide them.</comment>');
         }
         $default = Inline::dump($message);
         $value = $io->ask(sprintf('<question>%s</question> (<comment>%s</comment>):', $key, $default), $default);
         $actualParams[$key] = Inline::parse($value);
     }
     return $actualParams;
 }
Example #9
0
 /**
  * Execute an SVN command and try to fix up the process with credentials
  * if necessary.
  *
  * @param string $command SVN command to run
  * @param string $url     SVN url
  * @param string $cwd     Working directory
  * @param string $path    Target for a checkout
  * @param bool   $verbose Output all output to the user
  *
  * @return string
  *
  * @throws \RuntimeException
  */
 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
 {
     $svnCommand = $this->getCommand($command, $url, $path);
     $output = null;
     $io = $this->io;
     $handler = function ($type, $buffer) use(&$output, $io, $verbose) {
         if ($type !== 'out') {
             return;
         }
         if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
             return;
         }
         $output .= $buffer;
         if ($verbose) {
             $io->write($buffer, false);
         }
     };
     $status = $this->process->execute($svnCommand, $handler, $cwd);
     if (0 === $status) {
         return $output;
     }
     if (empty($output)) {
         $output = $this->process->getErrorOutput();
     }
     // the error is not auth-related
     if (false === stripos($output, 'Could not authenticate to server:') && false === stripos($output, 'authorization failed') && false === stripos($output, 'svn: E170001:') && false === stripos($output, 'svn: E215004:')) {
         throw new \RuntimeException($output);
     }
     // no auth supported for non interactive calls
     if (!$this->io->isInteractive()) {
         throw new \RuntimeException('can not ask for authentication in non interactive mode (' . $output . ')');
     }
     // try to authenticate if maximum quantity of tries not reached
     if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES || !$this->hasAuth()) {
         $this->doAuthDance();
         // restart the process
         return $this->execute($command, $url, $cwd, $path, $verbose);
     }
     throw new \RuntimeException('wrong credentials provided (' . $output . ')');
 }
Example #10
0
 /**
  * Execute an SVN command and try to fix up the process with credentials
  * if necessary.
  *
  * @param string  $command SVN command to run
  * @param string  $url     SVN url
  * @param string  $cwd     Working directory
  * @param string  $path    Target for a checkout
  * @param Boolean $verbose Output all output to the user
  *
  * @return string
  *
  * @throws \RuntimeException
  */
 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
 {
     $svnCommand = $this->getCommand($command, $url, $path);
     $output = null;
     $io = $this->io;
     $handler = function ($type, $buffer) use(&$output, $io, $verbose) {
         if ($type !== 'out') {
             return;
         }
         $output .= $buffer;
         if ($verbose) {
             $io->write($buffer, false);
         }
     };
     $status = $this->process->execute($svnCommand, $handler, $cwd);
     if (0 === $status) {
         return $output;
     }
     if (empty($output)) {
         $output = $this->process->getErrorOutput();
     }
     // the error is not auth-related
     if (false === stripos($output, 'authorization failed:')) {
         throw new \RuntimeException($output);
     }
     // no auth supported for non interactive calls
     if (!$this->io->isInteractive()) {
         throw new \RuntimeException('can not ask for authentication in non interactive mode (' . $output . ')');
     }
     // TODO keep a count of user auth attempts and ask 5 times before
     // failing hard (currently it fails hard directly if the URL has credentials)
     // try to authenticate
     if (!$this->hasAuth()) {
         $this->doAuthDance();
         // restart the process
         return $this->execute($command, $url, $cwd, $path, $verbose);
     }
     throw new \RuntimeException('wrong credentials provided (' . $output . ')');
 }
Example #11
0
 /**
  * @brief Ask for a path to a file
  * @param IOInterface $io
  * @param string      $filename parameters.yml or parameters_shared.yml
  * @param string      $pathname file to look for before asking in IO
  * @throws \Exception
  * @internal param Event $event
  */
 protected static function getFromIO(IOInterface $io, $filename, $pathname = "")
 {
     if (!file_exists($pathname . "/" . $filename)) {
         if ($io->isInteractive()) {
             $try = 0;
             while (!file_exists($pathname . '/' . $filename)) {
                 if ($try >= 3) {
                     throw new \InvalidArgumentException("3 attempts exhausted, {$filename} not found!");
                 }
                 if ($try > 0) {
                     $io->write("<error>File <options=bold;fg=yellow>{$pathname}/{$filename}</options=bold;fg=yellow> does not exist!</error>");
                 }
                 $try++;
                 $pathname = $io->ask("<comment>Path to folder containing '{$filename}':</comment> ", $pathname);
             }
         } else {
             throw new \Exception("Failed to retrieve {$filename} from IO: Input is not interactive");
         }
     }
     $dest = self::PARAMETERS_DIR . $filename;
     copy($pathname . '/' . $filename, $dest);
     $io->write("<info>File {$pathname}/{$filename} copied to {$dest}</info>");
 }
Example #12
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);
     }
 }
 protected function fetchKeys(IOInterface $io, Config $config)
 {
     if (!$io->isInteractive()) {
         throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
     }
     $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
     $validator = function ($value) {
         if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
             throw new \UnexpectedValueException('Invalid input');
         }
         return trim($value) . "\n";
     };
     $devKey = '';
     while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
         $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
         while ($line = $io->ask('')) {
             $devKey .= trim($line) . "\n";
             if (trim($line) === '-----END PUBLIC KEY-----') {
                 break;
             }
         }
     }
     file_put_contents($keyPath = $config->get('home') . '/keys.dev.pub', $match[0]);
     $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
     $tagsKey = '';
     while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
         $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
         while ($line = $io->ask('')) {
             $tagsKey .= trim($line) . "\n";
             if (trim($line) === '-----END PUBLIC KEY-----') {
                 break;
             }
         }
     }
     file_put_contents($keyPath = $config->get('home') . '/keys.tags.pub', $match[0]);
     $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
     $io->write('Public keys stored in ' . $config->get('home'));
 }
Example #14
0
 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;
 }
 /**
  * @param IOInterface $io
  * @param $parameters
  * @return bool
  */
 private static function askConfirmation(IOInterface $io, $parameters)
 {
     if (!$io->isInteractive()) {
         return true;
     }
     $confirmation = $io->askConfirmation(sprintf('Do you want to create MySQL database \'%s\' and install Magento on it [Y,n]?', $parameters['db_name']), true);
     return $confirmation;
 }