Example #1
0
 /**
  * Test whether exception from silent callbacks are correctly forwarded.
  */
 public function testSilencedException()
 {
     $verification = microtime();
     $this->setExpectedException('\\RuntimeException', $verification);
     Silencer::call(function () use($verification) {
         throw new \RuntimeException($verification);
     });
 }
Example #2
0
 /**
  * @param IOInterface $io
  * @param string      $cacheDir   location of the cache
  * @param string      $whitelist  List of characters that are allowed in path names (used in a regex character class)
  * @param Filesystem  $filesystem optional filesystem instance
  */
 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
 {
     $this->io = $io;
     $this->root = rtrim($cacheDir, '/\\') . '/';
     $this->whitelist = $whitelist;
     $this->filesystem = $filesystem ?: new Filesystem();
     if (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true) || !is_writable($this->root)) {
         $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
         $this->enabled = false;
     }
 }
Example #3
0
 protected static function getUniqueTmpDirectory()
 {
     $attempts = 5;
     $root = sys_get_temp_dir();
     do {
         $unique = $root . DIRECTORY_SEPARATOR . uniqid('composer-test-' . rand(1000, 9000));
         if (!file_exists($unique) && Silencer::call('mkdir', $unique, 0777)) {
             return realpath($unique);
         }
     } while (--$attempts);
     throw new \RuntimeException('Failed to create a unique temporary directory.');
 }
Example #4
0
 public function __construct()
 {
     static $shutdownRegistered = false;
     if (function_exists('ini_set') && extension_loaded('xdebug')) {
         ini_set('xdebug.show_exception_trace', false);
         ini_set('xdebug.scream', false);
     }
     if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
         date_default_timezone_set(Silencer::call('date_default_timezone_get'));
     }
     if (!$shutdownRegistered) {
         $shutdownRegistered = true;
         register_shutdown_function(function () {
             $lastError = error_get_last();
             if ($lastError && $lastError['message'] && (strpos($lastError['message'], 'Allowed memory') !== false || strpos($lastError['message'], 'exceeded memory') !== false)) {
                 echo "\n" . 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
             }
         });
     }
     parent::__construct('Composer', Composer::VERSION);
 }
Example #5
0
 /**
  * @param  IOInterface|null $io
  * @return Config
  */
 public static function createConfig(IOInterface $io = null, $cwd = null)
 {
     $cwd = $cwd ?: getcwd();
     $config = new Config(true, $cwd);
     // determine and add main dirs to the config
     $home = self::getHomeDir();
     $config->merge(array('config' => array('home' => $home, 'cache-dir' => self::getCacheDir($home), 'data-dir' => self::getDataDir($home))));
     // Protect directory against web access. Since HOME could be
     // the www-data's user home and be web-accessible it is a
     // potential security risk
     $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
     foreach ($dirs as $dir) {
         if (!file_exists($dir . '/.htaccess')) {
             if (!is_dir($dir)) {
                 Silencer::call('mkdir', $dir, 0777, true);
             }
             Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
         }
     }
     // load global config
     $file = new JsonFile($config->get('home') . '/config.json');
     if ($file->exists()) {
         if ($io && $io->isDebug()) {
             $io->writeError('Loading config file ' . $file->getPath());
         }
         $config->merge($file->read());
     }
     $config->setConfigSource(new JsonConfigSource($file));
     // load global auth file
     $file = new JsonFile($config->get('home') . '/auth.json');
     if ($file->exists()) {
         if ($io && $io->isDebug()) {
             $io->writeError('Loading config file ' . $file->getPath());
         }
         $config->merge(array('config' => $file->read()));
     }
     $config->setAuthConfigSource(new JsonConfigSource($file, true));
     // load COMPOSER_AUTH environment variable if set
     if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
         $authData = json_decode($composerAuthEnv, true);
         if (is_null($authData)) {
             throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
         }
         if ($io && $io->isDebug()) {
             $io->writeError('Loading auth config from COMPOSER_AUTH');
         }
         $config->merge(array('config' => $authData));
     }
     return $config;
 }
Example #6
0
 /**
  * {@inheritDoc}
  */
 public function doRun(InputInterface $input, OutputInterface $output)
 {
     $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
     $io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
     ErrorHandler::register($io);
     // switch working dir
     if ($newWorkDir = $this->getNewWorkingDir($input)) {
         $oldWorkingDir = getcwd();
         chdir($newWorkDir);
         $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
     }
     // determine command name to be executed without including plugin commands
     $commandName = '';
     if ($name = $this->getCommandName($input)) {
         try {
             $commandName = $this->find($name)->getName();
         } catch (\InvalidArgumentException $e) {
         }
     }
     if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
         try {
             foreach ($this->getPluginCommands() as $command) {
                 if ($this->has($command->getName())) {
                     $io->writeError('<warning>Plugin command ' . $command->getName() . ' (' . get_class($command) . ') would override a Composer command and has been skipped</warning>');
                 } else {
                     $this->add($command);
                 }
             }
         } catch (NoSslException $e) {
             // suppress these as they are not relevant at this point
         }
         $this->hasPluginCommands = true;
     }
     // determine command name to be executed incl plugin commands, and check if it's a proxy command
     $isProxyCommand = false;
     if ($name = $this->getCommandName($input)) {
         try {
             $command = $this->find($name);
             $commandName = $command->getName();
             $isProxyCommand = $command instanceof Command\BaseCommand && $command->isProxyCommand();
         } catch (\InvalidArgumentException $e) {
         }
     }
     if (!$isProxyCommand) {
         $io->writeError(sprintf('Running %s (%s) with %s on %s', Composer::VERSION, Composer::RELEASE_DATE, defined('HHVM_VERSION') ? 'HHVM ' . HHVM_VERSION : 'PHP ' . PHP_VERSION, php_uname('s') . ' / ' . php_uname('r')), true, IOInterface::DEBUG);
         if (PHP_VERSION_ID < 50302) {
             $io->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP ' . PHP_VERSION . ', upgrading is strongly recommended.</warning>');
         }
         if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
             $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
         }
         if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
             $io->writeError(sprintf('<warning>Warning: This development build of composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.</warning>', $_SERVER['PHP_SELF']));
         }
         if (getenv('COMPOSER_NO_INTERACTION')) {
             $input->setInteractive(false);
         }
         if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
             if (function_exists('posix_getuid') && posix_getuid() === 0) {
                 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
                     $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
                 }
                 if ($uid = (int) getenv('SUDO_UID')) {
                     // Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on
                     // ref. https://github.com/composer/composer/issues/5119
                     Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
                 }
             }
             // Silently clobber any remaining sudo leases on the current user as well to avoid privilege escalations
             Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
         }
         // Check system temp folder for usability as it can cause weird runtime issues otherwise
         Silencer::call(function () use($io) {
             $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
             if (!(file_put_contents($tempfile, __FILE__) && file_get_contents($tempfile) == __FILE__ && unlink($tempfile) && !file_exists($tempfile))) {
                 $io->writeError(sprintf('<error>PHP temp directory (%s) does not exist or is not writable to Composer. Set sys_temp_dir in your php.ini</error>', sys_get_temp_dir()));
             }
         });
         // add non-standard scripts as own commands
         $file = Factory::getComposerFile();
         if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
             if (isset($composer['scripts']) && is_array($composer['scripts'])) {
                 foreach ($composer['scripts'] as $script => $dummy) {
                     if (!defined('Composer\\Script\\ScriptEvents::' . str_replace('-', '_', strtoupper($script)))) {
                         if ($this->has($script)) {
                             $io->writeError('<warning>A script named ' . $script . ' would override a Composer command and has been skipped</warning>');
                         } else {
                             $this->add(new Command\ScriptAliasCommand($script));
                         }
                     }
                 }
             }
         }
     }
     try {
         if ($input->hasParameterOption('--profile')) {
             $startTime = microtime(true);
             $this->io->enableDebugging($startTime);
         }
         $result = parent::doRun($input, $output);
         if (isset($oldWorkingDir)) {
             chdir($oldWorkingDir);
         }
         if (isset($startTime)) {
             $io->writeError('<info>Memory usage: ' . round(memory_get_usage() / 1024 / 1024, 2) . 'MB (peak: ' . round(memory_get_peak_usage() / 1024 / 1024, 2) . 'MB), time: ' . round(microtime(true) - $startTime, 2) . 's');
         }
         restore_error_handler();
         return $result;
     } catch (ScriptExecutionException $e) {
         return $e->getCode();
     } catch (\Exception $e) {
         $this->hintCommonErrors($e);
         restore_error_handler();
         throw $e;
     }
 }
 /**
  * {@inheritDoc}
  */
 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
 {
     if (!$repo->hasPackage($package)) {
         throw new \InvalidArgumentException('Package is not installed: ' . $package);
     }
     $this->removeCode($package);
     $this->binaryInstaller->removeBinaries($package);
     $repo->removePackage($package);
     $downloadPath = $this->getPackageBasePath($package);
     if (strpos($package->getName(), '/')) {
         $packageVendorDir = dirname($downloadPath);
         if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
             Silencer::call('rmdir', $packageVendorDir);
         }
     }
 }
 public function installProject(IOInterface $io, Config $config, InputInterface $input, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repository = null, $disablePlugins = false, $noScripts = false, $keepVcs = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true)
 {
     $oldCwd = getcwd();
     // we need to manually load the configuration to pass the auth credentials to the io interface!
     $io->loadConfiguration($config);
     $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
     if ($packageName !== null) {
         $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $keepVcs, $noProgress, $ignorePlatformReqs, $secureHttp);
     } else {
         $installedFromVcs = false;
     }
     $composer = Factory::create($io, null, $disablePlugins);
     $composer->getDownloadManager()->setOutputProgress(!$noProgress);
     $fs = new Filesystem();
     if ($noScripts === false) {
         // dispatch event
         $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
     }
     $rootPackageConfig = $composer->getConfig();
     $this->updatePreferredOptions($rootPackageConfig, $input, $preferSource, $preferDist);
     // install dependencies of the created project
     if ($noInstall === false) {
         $installer = Installer::create($io, $composer);
         $installer->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode($installDevPackages)->setRunScripts(!$noScripts)->setIgnorePlatformRequirements($ignorePlatformReqs)->setSuggestedPackagesReporter($this->suggestedPackagesReporter);
         if ($disablePlugins) {
             $installer->disablePlugins();
         }
         $status = $installer->run();
         if (0 !== $status) {
             return $status;
         }
     }
     $hasVcs = $installedFromVcs;
     if (!$keepVcs && $installedFromVcs && (!$io->isInteractive() || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true))) {
         $finder = new Finder();
         $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
         foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg') as $vcsName) {
             $finder->name($vcsName);
         }
         try {
             $dirs = iterator_to_array($finder);
             unset($finder);
             foreach ($dirs as $dir) {
                 if (!$fs->removeDirectory($dir)) {
                     throw new \RuntimeException('Could not remove ' . $dir);
                 }
             }
         } catch (\Exception $e) {
             $io->writeError('<error>An error occurred while removing the VCS metadata: ' . $e->getMessage() . '</error>');
         }
         $hasVcs = false;
     }
     // rewriting self.version dependencies with explicit version numbers if the package's vcs metadata is gone
     if (!$hasVcs) {
         $package = $composer->getPackage();
         $configSource = new JsonConfigSource(new JsonFile('composer.json'));
         foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
             foreach ($package->{'get' . $meta['method']}() as $link) {
                 if ($link->getPrettyConstraint() === 'self.version') {
                     $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
                 }
             }
         }
     }
     if ($noScripts === false) {
         // dispatch event
         $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
     }
     chdir($oldCwd);
     $vendorComposerDir = $composer->getConfig()->get('vendor-dir') . '/composer';
     if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
         Silencer::call('rmdir', $vendorComposerDir);
         $vendorDir = $composer->getConfig()->get('vendor-dir');
         if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
             Silencer::call('rmdir', $vendorDir);
         }
     }
     return 0;
 }
Example #9
0
 protected function manipulateJson($method, $args, $fallback)
 {
     $args = func_get_args();
     // remove method & fallback
     array_shift($args);
     $fallback = array_pop($args);
     if ($this->file->exists()) {
         $contents = file_get_contents($this->file->getPath());
     } elseif ($this->authConfig) {
         $contents = "{\n}\n";
     } else {
         $contents = "{\n    \"config\": {\n    }\n}\n";
     }
     $manipulator = new JsonManipulator($contents);
     $newFile = !$this->file->exists();
     // override manipulator method for auth config files
     if ($this->authConfig && $method === 'addConfigSetting') {
         $method = 'addSubNode';
         list($mainNode, $name) = explode('.', $args[0], 2);
         $args = array($mainNode, $name, $args[1]);
     } elseif ($this->authConfig && $method === 'removeConfigSetting') {
         $method = 'removeSubNode';
         list($mainNode, $name) = explode('.', $args[0], 2);
         $args = array($mainNode, $name);
     }
     // try to update cleanly
     if (call_user_func_array(array($manipulator, $method), $args)) {
         file_put_contents($this->file->getPath(), $manipulator->getContents());
     } else {
         // on failed clean update, call the fallback and rewrite the whole file
         $config = $this->file->read();
         $this->arrayUnshiftRef($args, $config);
         call_user_func_array($fallback, $args);
         $this->file->write($config);
     }
     if ($newFile) {
         Silencer::call('chmod', $this->file->getPath(), 0600);
     }
 }
Example #10
0
 public function removeBinaries(PackageInterface $package)
 {
     $this->initializeBinDir();
     $binaries = $this->getBinaries($package);
     if (!$binaries) {
         return;
     }
     foreach ($binaries as $bin) {
         $link = $this->binDir . '/' . basename($bin);
         if (is_link($link) || file_exists($link)) {
             $this->filesystem->unlink($link);
         }
         if (file_exists($link . '.bat')) {
             $this->filesystem->unlink($link . '.bat');
         }
     }
     // attempt removing the bin dir in case it is left empty
     if (is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) {
         Silencer::call('rmdir', $this->binDir);
     }
 }
Example #11
0
 /**
  * @param  IOInterface|null $io
  * @return Config
  */
 public static function createConfig(IOInterface $io = null, $cwd = null)
 {
     $cwd = $cwd ?: getcwd();
     $config = new Config(true, $cwd);
     // determine and add main dirs to the config
     $home = self::getHomeDir();
     $config->merge(array('config' => array('home' => $home, 'cache-dir' => self::getCacheDir($home), 'data-dir' => self::getDataDir($home))));
     // Protect directory against web access. Since HOME could be
     // the www-data's user home and be web-accessible it is a
     // potential security risk
     $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
     foreach ($dirs as $dir) {
         if (!file_exists($dir . '/.htaccess')) {
             if (!is_dir($dir)) {
                 Silencer::call('mkdir', $dir, 0777, true);
             }
             Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
         }
     }
     // load global config
     $file = new JsonFile($config->get('home') . '/config.json');
     if ($file->exists()) {
         if ($io && $io->isDebug()) {
             $io->writeError('Loading config file ' . $file->getPath());
         }
         $config->merge($file->read());
     }
     $config->setConfigSource(new JsonConfigSource($file));
     // load global auth file
     $file = new JsonFile($config->get('home') . '/auth.json');
     if ($file->exists()) {
         if ($io && $io->isDebug()) {
             $io->writeError('Loading config file ' . $file->getPath());
         }
         $config->merge(array('config' => $file->read()));
     }
     $config->setAuthConfigSource(new JsonConfigSource($file, true));
     return $config;
 }
Example #12
0
 /**
  * Copy a file out of the cache
  */
 public function copyTo($file, $target)
 {
     $file = preg_replace('{[^' . $this->whitelist . ']}i', '-', $file);
     if ($this->enabled && file_exists($this->root . $file)) {
         try {
             touch($this->root . $file, filemtime($this->root . $file), time());
         } catch (\ErrorException $e) {
             // fallback in case the above failed due to incorrect ownership
             // see https://github.com/composer/composer/issues/4070
             Silencer::call('touch', $this->root . $file);
         }
         $this->io->writeError('Reading ' . $this->root . $file . ' from cache', true, IOInterface::DEBUG);
         return copy($this->root . $file, $target);
     }
     return false;
 }
 /**
  * Load composer and the composer class loader.
  *
  * @SuppressWarnings(PHPMD.ShortVariable)
  */
 public static function createComposer(IOInterface $io)
 {
     chdir(COMPOSER_DIR_ABSOULTE);
     // try to increase memory limit
     static::increaseMemoryLimit();
     // register composer class loader
     static::registerComposerClassLoader();
     // create composer factory
     /** @var \Composer\Factory $factory */
     $factory = new Factory();
     // create composer
     if (class_exists('\\Composer\\Util\\Silencer')) {
         $composer = Silencer::call(array($factory, 'createComposer'), $io);
     } else {
         $composer = $factory->createComposer($io);
     }
     return $composer;
 }
Example #14
0
 /**
  * This method was adapted from Sslurp.
  * https://github.com/EvanDotPro/Sslurp
  *
  * (c) Evan Coury <*****@*****.**>
  *
  * For the full copyright and license information, please see below:
  *
  * Copyright (c) 2013, Evan Coury
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  *     * Redistributions of source code must retain the above copyright notice,
  *       this list of conditions and the following disclaimer.
  *
  *     * Redistributions in binary form must reproduce the above copyright notice,
  *       this list of conditions and the following disclaimer in the documentation
  *       and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * @return string
  */
 private function getSystemCaRootBundlePath()
 {
     static $caPath = null;
     if ($caPath !== null) {
         return $caPath;
     }
     // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
     // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
     $envCertFile = getenv('SSL_CERT_FILE');
     if ($envCertFile && is_readable($envCertFile) && $this->validateCaFile($envCertFile)) {
         // Possibly throw exception instead of ignoring SSL_CERT_FILE if it's invalid?
         return $caPath = $envCertFile;
     }
     $configured = ini_get('openssl.cafile');
     if ($configured && strlen($configured) > 0 && is_readable($configured) && $this->validateCaFile($configured)) {
         return $caPath = $configured;
     }
     $caBundlePaths = array('/etc/pki/tls/certs/ca-bundle.crt', '/etc/ssl/certs/ca-certificates.crt', '/etc/ssl/ca-bundle.pem', '/usr/local/share/certs/ca-root-nss.crt', '/usr/ssl/certs/ca-bundle.crt', '/opt/local/share/curl/curl-ca-bundle.crt', '/usr/local/share/curl/curl-ca-bundle.crt', '/usr/share/ssl/certs/ca-bundle.crt', '/etc/ssl/cert.pem', '/usr/local/etc/ssl/cert.pem');
     foreach ($caBundlePaths as $caBundle) {
         if (Silencer::call('is_readable', $caBundle) && $this->validateCaFile($caBundle)) {
             return $caPath = $caBundle;
         }
     }
     foreach ($caBundlePaths as $caBundle) {
         $caBundle = dirname($caBundle);
         if (is_dir($caBundle) && glob($caBundle . '/*')) {
             return $caPath = $caBundle;
         }
     }
     return $caPath = __DIR__ . '/../../../res/cacert.pem';
     // Bundled with Composer, last resort
 }
Example #15
0
 /**
  * Extract the classes in the given file
  *
  * @param  string            $path The file to check
  * @throws \RuntimeException
  * @return array             The found classes
  */
 private static function findClasses($path)
 {
     $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
     if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
         $extraTypes .= '|enum';
     }
     try {
         $contents = Silencer::call('php_strip_whitespace', $path);
         if (!$contents) {
             if (!file_exists($path)) {
                 throw new \Exception('File does not exist');
             }
             if (!is_readable($path)) {
                 throw new \Exception('File is not readable');
             }
         }
     } catch (\Exception $e) {
         throw new \RuntimeException('Could not scan for classes inside ' . $path . ": \n" . $e->getMessage(), 0, $e);
     }
     // return early if there is no chance of matching anything in this file
     if (!preg_match('{\\b(?:class|interface' . $extraTypes . ')\\s}i', $contents)) {
         return array();
     }
     // strip heredocs/nowdocs
     $contents = preg_replace('{<<<\\s*(\'?)(\\w+)\\1(?:\\r\\n|\\n|\\r)(?:.*?)(?:\\r\\n|\\n|\\r)\\2(?=\\r\\n|\\n|\\r|;)}s', 'null', $contents);
     // strip strings
     $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
     // strip leading non-php code if needed
     if (substr($contents, 0, 2) !== '<?') {
         $contents = preg_replace('{^.+?<\\?}s', '<?', $contents, 1, $replacements);
         if ($replacements === 0) {
             return array();
         }
     }
     // strip non-php blocks in the file
     $contents = preg_replace('{\\?>.+<\\?}s', '?><?', $contents);
     // strip trailing non-php code if needed
     $pos = strrpos($contents, '?>');
     if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
         $contents = substr($contents, 0, $pos);
     }
     preg_match_all('{
         (?:
              \\b(?<![\\$:>])(?P<type>class|interface' . $extraTypes . ') \\s++ (?P<name>[a-zA-Z_\\x7f-\\xff:][a-zA-Z0-9_\\x7f-\\xff:\\-]*+)
            | \\b(?<![\\$:>])(?P<ns>namespace) (?P<nsname>\\s++[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+(?:\\s*+\\\\\\s*+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+)*+)? \\s*+ [\\{;]
         )
     }ix', $contents, $matches);
     $classes = array();
     $namespace = '';
     for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
         if (!empty($matches['ns'][$i])) {
             $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
         } else {
             $name = $matches['name'][$i];
             if ($name[0] === ':') {
                 // This is an XHP class, https://github.com/facebook/xhp
                 $name = 'xhp' . substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
             } elseif ($matches['type'][$i] === 'enum') {
                 // In Hack, something like:
                 //   enum Foo: int { HERP = '123'; }
                 // The regex above captures the colon, which isn't part of
                 // the class name.
                 $name = rtrim($name, ':');
             }
             $classes[] = ltrim($namespace . $name, '\\');
         }
     }
     return $classes;
 }
 /**
  * {@inheritDoc}
  */
 protected function initialize(InputInterface $input, OutputInterface $output)
 {
     parent::initialize($input, $output);
     if ($input->getOption('global') && null !== $input->getOption('file')) {
         throw new \RuntimeException('--file and --global can not be combined');
     }
     $io = $this->getIO();
     $this->config = Factory::createConfig($io);
     // Get the local composer.json, global config.json, or if the user
     // passed in a file to use
     $configFile = $input->getOption('global') ? $this->config->get('home') . '/config.json' : ($input->getOption('file') ?: trim(getenv('COMPOSER')) ?: 'composer.json');
     // Create global composer.json if this was invoked using `composer global config`
     if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) {
         file_put_contents($configFile, "{\n}\n");
     }
     $this->configFile = new JsonFile($configFile, null, $io);
     $this->configSource = new JsonConfigSource($this->configFile);
     $authConfigFile = $input->getOption('global') ? $this->config->get('home') . '/auth.json' : dirname(realpath($configFile)) . '/auth.json';
     $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
     $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
     // Initialize the global file if it's not there, ignoring any warnings or notices
     if ($input->getOption('global') && !$this->configFile->exists()) {
         touch($this->configFile->getPath());
         $this->configFile->write(array('config' => new \ArrayObject()));
         Silencer::call('chmod', $this->configFile->getPath(), 0600);
     }
     if ($input->getOption('global') && !$this->authConfigFile->exists()) {
         touch($this->authConfigFile->getPath());
         $this->authConfigFile->write(array('http-basic' => new \ArrayObject(), 'github-oauth' => new \ArrayObject(), 'gitlab-oauth' => new \ArrayObject()));
         Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
     }
     if (!$this->configFile->exists()) {
         throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
     }
 }
Example #17
0
 protected function initialize()
 {
     parent::initialize();
     $versionParser = new VersionParser();
     // Add each of the override versions as options.
     // Later we might even replace the extensions instead.
     foreach ($this->overrides as $override) {
         // Check that it's a platform package.
         if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
             throw new \InvalidArgumentException('Invalid platform package name in config.platform: ' . $override['name']);
         }
         $version = $versionParser->normalize($override['version']);
         $package = new CompletePackage($override['name'], $version, $override['version']);
         $package->setDescription('Package overridden via config.platform');
         $package->setExtra(array('config.platform' => true));
         parent::addPackage($package);
     }
     $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
     $version = $versionParser->normalize($prettyVersion);
     $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
     $composerPluginApi->setDescription('The Composer Plugin API');
     $this->addPackage($composerPluginApi);
     try {
         $prettyVersion = PHP_VERSION;
         $version = $versionParser->normalize($prettyVersion);
     } catch (\UnexpectedValueException $e) {
         $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
         $version = $versionParser->normalize($prettyVersion);
     }
     $php = new CompletePackage('php', $version, $prettyVersion);
     $php->setDescription('The PHP interpreter');
     $this->addPackage($php);
     if (PHP_INT_SIZE === 8) {
         $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
         $php64->setDescription('The PHP interpreter, 64bit');
         $this->addPackage($php64);
     }
     // The AF_INET6 constant is only defined if ext-sockets is available but IPv6 support might still be available.
     if (defined('AF_INET6') || function_exists('inet_pton') && Silencer::call('inet_pton', '::') !== false) {
         $phpIpv6 = new CompletePackage('ext-network-ipv6', $version, $prettyVersion);
         $phpIpv6->setDescription('PHP IPv6 support');
         $this->addPackage($phpIpv6);
     }
     $loadedExtensions = get_loaded_extensions();
     // Extensions scanning
     foreach ($loadedExtensions as $name) {
         if (in_array($name, array('standard', 'Core'))) {
             continue;
         }
         $extraDescription = null;
         $reflExt = new \ReflectionExtension($name);
         try {
             $prettyVersion = $reflExt->getVersion();
             $version = $versionParser->normalize($prettyVersion);
         } catch (\UnexpectedValueException $e) {
             $extraDescription = ' (actual version: ' . $prettyVersion . ')';
             if (preg_match('{^(\\d+\\.\\d+\\.\\d+(?:\\.\\d+)?)}', $prettyVersion, $match)) {
                 $prettyVersion = $match[1];
             } else {
                 $prettyVersion = '0';
             }
             $version = $versionParser->normalize($prettyVersion);
         }
         $packageName = $this->buildPackageName($name);
         $ext = new CompletePackage($packageName, $version, $prettyVersion);
         $ext->setDescription('The ' . $name . ' PHP extension' . $extraDescription);
         $this->addPackage($ext);
     }
     // Another quick loop, just for possible libraries
     // Doing it this way to know that functions or constants exist before
     // relying on them.
     foreach ($loadedExtensions as $name) {
         $prettyVersion = null;
         $description = 'The ' . $name . ' PHP library';
         switch ($name) {
             case 'curl':
                 $curlVersion = curl_version();
                 $prettyVersion = $curlVersion['version'];
                 break;
             case 'iconv':
                 $prettyVersion = ICONV_VERSION;
                 break;
             case 'intl':
                 $name = 'ICU';
                 if (defined('INTL_ICU_VERSION')) {
                     $prettyVersion = INTL_ICU_VERSION;
                 } else {
                     $reflector = new \ReflectionExtension('intl');
                     ob_start();
                     $reflector->info();
                     $output = ob_get_clean();
                     preg_match('/^ICU version => (.*)$/m', $output, $matches);
                     $prettyVersion = $matches[1];
                 }
                 break;
             case 'libxml':
                 $prettyVersion = LIBXML_DOTTED_VERSION;
                 break;
             case 'openssl':
                 $prettyVersion = preg_replace_callback('{^(?:OpenSSL\\s*)?([0-9.]+)([a-z]*).*}', function ($match) {
                     if (empty($match[2])) {
                         return $match[1];
                     }
                     // OpenSSL versions add another letter when they reach Z.
                     // e.g. OpenSSL 0.9.8zh 3 Dec 2015
                     if (!preg_match('{^z*[a-z]$}', $match[2])) {
                         // 0.9.8abc is garbage
                         return 0;
                     }
                     $len = strlen($match[2]);
                     $patchVersion = ($len - 1) * 26;
                     // All Z
                     $patchVersion += ord($match[2][$len - 1]) - 96;
                     return $match[1] . '.' . $patchVersion;
                 }, OPENSSL_VERSION_TEXT);
                 $description = OPENSSL_VERSION_TEXT;
                 break;
             case 'pcre':
                 $prettyVersion = preg_replace('{^(\\S+).*}', '$1', PCRE_VERSION);
                 break;
             case 'uuid':
                 $prettyVersion = phpversion('uuid');
                 break;
             case 'xsl':
                 $prettyVersion = LIBXSLT_DOTTED_VERSION;
                 break;
             default:
                 // None handled extensions have no special cases, skip
                 continue 2;
         }
         try {
             $version = $versionParser->normalize($prettyVersion);
         } catch (\UnexpectedValueException $e) {
             continue;
         }
         $lib = new CompletePackage('lib-' . $name, $version, $prettyVersion);
         $lib->setDescription($description);
         $this->addPackage($lib);
     }
     if (defined('HHVM_VERSION')) {
         try {
             $prettyVersion = HHVM_VERSION;
             $version = $versionParser->normalize($prettyVersion);
         } catch (\UnexpectedValueException $e) {
             $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
             $version = $versionParser->normalize($prettyVersion);
         }
         $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
         $hhvm->setDescription('The HHVM Runtime (64bit)');
         $this->addPackage($hhvm);
     }
 }