diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 9e1502486..e7a0a19bc 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -47,7 +47,9 @@ class CreateProjectCommand extends Command new InputArgument('version', InputArgument::OPTIONAL, 'Version, will defaults to latest'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'Pick a different repository url to look for the package.'), - new InputOption('dev', null, InputOption::VALUE_NONE, 'Whether to install dependencies for development.') + new InputOption('dev', null, InputOption::VALUE_NONE, 'Whether to install dependencies for development.'), + new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'Whether to disable custom installers.'), + new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.') )) ->setHelp(<<create-project command creates a new project from a given @@ -79,11 +81,13 @@ EOT $input->getArgument('version'), $input->getOption('prefer-source'), $input->getOption('dev'), - $input->getOption('repository-url') + $input->getOption('repository-url'), + $input->getOption('no-custom-installers'), + $input->getOption('no-scripts') ); } - public function installProject(IOInterface $io, $packageName, $directory = null, $version = null, $preferSource = false, $installDevPackages = false, $repositoryUrl = null) + public function installProject(IOInterface $io, $packageName, $directory = null, $version = null, $preferSource = false, $installDevPackages = false, $repositoryUrl = null, $disableCustomInstallers = false, $noScripts = false) { $dm = $this->createDownloadManager($io); if ($preferSource) { @@ -120,6 +124,11 @@ EOT } $io->write('Installing ' . $package->getName() . ' (' . VersionParser::formatVersion($package, false) . ')', true); + + if ($disableCustomInstallers) { + $io->write('Custom installers have been disabled.'); + } + if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) { $package->setSourceReference(substr($package->getPrettyVersion(), 4)); } @@ -138,10 +147,15 @@ EOT $composer = Factory::create($io); $installer = Installer::create($io, $composer); - $installer - ->setPreferSource($preferSource) + $installer->setPreferSource($preferSource) ->setDevMode($installDevPackages) - ->run(); + ->setRunScripts( ! $noScripts); + + if ($disableCustomInstallers) { + $installer->disableCustomInstallers(); + } + + $installer->run(); } protected function createDownloadManager(IOInterface $io) diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 18914303c..be5824a64 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -33,6 +33,7 @@ class InstallCommand extends Command new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of dev-require packages.'), + new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'Disables all custom installers.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), )) ->setHelp(<<setRunScripts(!$input->getOption('no-scripts')) ; + if ($input->getOption('no-custom-installers')) { + $install->disableCustomInstallers(); + } + return $install->run() ? 0 : 1; } } diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index ceb8ff86a..7bede7d25 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -33,6 +33,7 @@ class UpdateCommand extends Command new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of dev-require packages.'), + new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'Disables all custom installers.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), )) ->setHelp(<<setUpdateWhitelist($input->getArgument('packages')) ; + if ($input->getOption('no-custom-installers')) { + $install->disableCustomInstallers(); + } + return $install->run() ? 0 : 1; } } diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 8c0669511..a52055a67 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -722,4 +722,16 @@ class Installer return $this; } + + /** + * Disables custom installers. + * + * Call this if you want to ensure that third-party code never gets + * executed. The default is to automatically install, and execute + * custom third-party installers. + */ + public function disableCustomInstallers() + { + $this->installationManager->disableCustomInstallers(); + } } diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 6ac4fca50..e013673f5 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -46,6 +46,24 @@ class InstallationManager $this->cache = array(); } + /** + * Disables custom installers. + * + * We prevent any custom installers from being instantiated by simply + * deactivating the installer for them. This ensure that no third-party + * code is ever executed. + */ + public function disableCustomInstallers() + { + foreach ($this->installers as $i => $installer) { + if ( ! $installer instanceof InstallerInstaller) { + continue; + } + + unset($this->installers[$i]); + } + } + /** * Returns installer for a specific package type. *