From bae227ec2d2fe593bdae406687caab8901b7619f Mon Sep 17 00:00:00 2001 From: Simon Berger Date: Mon, 7 Sep 2020 20:06:55 +0200 Subject: [PATCH 1/3] Changed all substr calls used to compare fragments of text to strpos Some additional code cleanups in those classes Reverted change causing issues --- src/Composer/Autoload/ClassMapGenerator.php | 2 +- src/Composer/Command/ConfigCommand.php | 2 +- src/Composer/Command/DiagnoseCommand.php | 2 +- src/Composer/Command/InitCommand.php | 4 +-- src/Composer/Command/SelfUpdateCommand.php | 2 +- src/Composer/Config/JsonConfigSource.php | 5 ++-- src/Composer/Console/Application.php | 2 +- .../DependencyResolver/DefaultPolicy.php | 4 +-- .../EventDispatcher/EventDispatcher.php | 16 +++++------ src/Composer/Factory.php | 2 +- src/Composer/Installer/LibraryInstaller.php | 4 +-- src/Composer/Json/JsonManipulator.php | 12 ++++----- src/Composer/Package/Loader/ArrayLoader.php | 2 +- .../Package/Loader/ValidatingArrayLoader.php | 2 +- .../Package/Version/VersionGuesser.php | 7 +++-- .../Package/Version/VersionParser.php | 2 +- .../Repository/ComposerRepository.php | 5 +--- src/Composer/Repository/RepositoryFactory.php | 2 +- src/Composer/Repository/VcsRepository.php | 7 ++--- src/Composer/Util/Filesystem.php | 4 +-- src/Composer/Util/RemoteFilesystem.php | 27 +++++++++---------- src/Composer/Util/StreamContextFactory.php | 6 ++--- src/Composer/Util/Svn.php | 2 +- 23 files changed, 57 insertions(+), 66 deletions(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index ae6371fa40a2..a71cb1a4b2fc 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -251,7 +251,7 @@ private static function findClasses($path) // strip strings $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents); // strip leading non-php code if needed - if (substr($contents, 0, 2) !== 'getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) { + if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || strpos($settingKey, 'extra.') === 0)) { throw new \InvalidArgumentException('The '.$settingKey.' property can not be set in the global config.json file. Use `composer global config` to apply changes to the global composer.json'); } if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) { diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index c0b82ada795b..664324098a78 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -148,7 +148,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $io->write('Checking disk free space: ', false); $this->outputResult($this->checkDiskSpace($config)); - if ('phar:' === substr(__FILE__, 0, 5)) { + if (strpos(__FILE__, 'phar:') === 0) { $io->write('Checking pubkeys: ', false); $this->outputResult($this->checkPubKeys($config)); diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index a4456e79b140..19812fcb0b56 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -120,7 +120,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } $file = new JsonFile(Factory::getComposerFile()); - $json = $file->encode($options); + $json = JsonFile::encode($options); if ($input->isInteractive()) { $io->writeError(array('', $json, '')); @@ -655,7 +655,7 @@ protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/') if (file_exists($ignoreFile)) { $contents = file_get_contents($ignoreFile); - if ("\n" !== substr($contents, 0, -1)) { + if (strpos($contents, "\n") !== 0) { $contents .= "\n"; } } diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index fab414deb99f..d0bc4ec958f3 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -166,7 +166,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - if ($requestedChannel && is_numeric($requestedChannel) && substr($latestStable['version'], 0, 1) !== $requestedChannel) { + if ($requestedChannel && is_numeric($requestedChannel) && strpos($latestStable['version'], $requestedChannel) !== 0) { $io->writeError('Warning: You forced the install of '.$latestVersion.' via --'.$requestedChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); } diff --git a/src/Composer/Config/JsonConfigSource.php b/src/Composer/Config/JsonConfigSource.php index 67634f0c5121..e03e0f274e4d 100644 --- a/src/Composer/Config/JsonConfigSource.php +++ b/src/Composer/Config/JsonConfigSource.php @@ -135,7 +135,7 @@ public function removeConfigSetting($name) public function addProperty($name, $value) { $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) { - if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') { + if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0) { $bits = explode('.', $key); $last = array_pop($bits); $arr = &$config[reset($bits)]; @@ -157,9 +157,8 @@ public function addProperty($name, $value) */ public function removeProperty($name) { - $authConfig = $this->authConfig; $this->manipulateJson('removeProperty', $name, function (&$config, $key) { - if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') { + if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0) { $bits = explode('.', $key); $last = array_pop($bits); $arr = &$config[reset($bits)]; diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index acd0e4c0a2e8..cd78b595b21d 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -473,7 +473,7 @@ protected function getDefaultCommands() new Command\FundCommand(), )); - if ('phar:' === substr(__FILE__, 0, 5)) { + if (strpos(__FILE__, 'phar:') === 0) { $commands[] = new Command\SelfUpdateCommand(); } diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index 4f3bdefa3af7..e26555bf7dbc 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -116,8 +116,8 @@ public function compareByPriority(Pool $pool, PackageInterface $a, PackageInterf if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) { $requiredVendor = substr($requiredPackage, 0, $pos); - $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor; - $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor; + $aIsSameVendor = strpos($a->getName(), $requiredVendor) === 0; + $bIsSameVendor = strpos($b->getName(), $requiredVendor) === 0; if ($bIsSameVendor !== $aIsSameVendor) { return $aIsSameVendor ? -1 : 1; diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 3aed66f761bb..949aaf157bed 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -12,17 +12,12 @@ namespace Composer\EventDispatcher; -use Composer\DependencyResolver\PolicyInterface; -use Composer\DependencyResolver\Request; -use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Transaction; use Composer\Installer\InstallerEvent; use Composer\IO\IOInterface; use Composer\Composer; use Composer\DependencyResolver\Operation\OperationInterface; -use Composer\Repository\CompositeRepository; use Composer\Repository\RepositoryInterface; -use Composer\Repository\RepositorySet; use Composer\Script; use Composer\Installer\PackageEvent; use Composer\Installer\BinaryInstaller; @@ -177,7 +172,7 @@ protected function doDispatch(Event $event) $args = array_merge($script, $event->getArguments()); $flags = $event->getFlags(); - if (substr($callable, 0, 10) === '@composer ') { + if (strpos($callable, '@composer ') === 0) { $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . ' ' . implode(' ', $args); if (0 !== ($exitCode = $this->executeTty($exec))) { $this->io->writeError(sprintf('Script %s handling the %s event returned with error code '.$exitCode.'', $callable, $event->getName()), true, IOInterface::QUIET); @@ -239,11 +234,12 @@ protected function doDispatch(Event $event) } } - if (substr($exec, 0, 8) === '@putenv ') { + if (strpos($exec, '@putenv ') === 0) { putenv(substr($exec, 8)); continue; - } elseif (substr($exec, 0, 5) === '@php ') { + } + if (strpos($exec, '@php ') === 0) { $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5); } else { $finder = new PhpExecutableFinder(); @@ -257,7 +253,7 @@ protected function doDispatch(Event $event) // if composer is being executed, make sure it runs the expected composer from current path // resolution, even if bin-dir contains composer too because the project requires composer/composer // see https://github.com/composer/composer/issues/8748 - if (substr($exec, 0, 9) === 'composer ') { + if (strpos($exec, 'composer ') === 0) { $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($exec, 8); } @@ -472,7 +468,7 @@ protected function isPhpScript($callable) */ protected function isComposerScript($callable) { - return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5) && '@putenv ' !== substr($callable, 0, 8); + return strpos($callable, '@') === 0 && strpos($callable, '@php ') !== 0 && strpos($callable, '@putenv ') !== 0; } /** diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 218a5345778e..7e1dd83eb9ba 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -651,7 +651,7 @@ public static function createHttpDownloader(IOInterface $io, Config $config, $op private static function useXdg() { foreach (array_keys($_SERVER) as $key) { - if (substr($key, 0, 4) === 'XDG_') { + if (strpos($key, 'XDG_') === 0) { return true; } } diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index d70cd4f63654..3c916fc12366 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -262,8 +262,8 @@ protected function updateCode(PackageInterface $initial, PackageInterface $targe if ($targetDownloadPath !== $initialDownloadPath) { // if the target and initial dirs intersect, we force a remove + install // to avoid the rename wiping the target dir as part of the initial dir cleanup - if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath - || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath + if (strpos($initialDownloadPath, $targetDownloadPath) === 0 + || strpos($targetDownloadPath, $initialDownloadPath) === 0 ) { $promise = $this->removeCode($initial); if (!$promise instanceof PromiseInterface) { diff --git a/src/Composer/Json/JsonManipulator.php b/src/Composer/Json/JsonManipulator.php index 5f50cee5bb19..8ab6b33f552f 100644 --- a/src/Composer/Json/JsonManipulator.php +++ b/src/Composer/Json/JsonManipulator.php @@ -167,15 +167,15 @@ public function removeConfigSetting($name) public function addProperty($name, $value) { - if (substr($name, 0, 8) === 'suggest.') { + if (strpos($name, 'suggest.') === 0) { return $this->addSubNode('suggest', substr($name, 8), $value); } - if (substr($name, 0, 6) === 'extra.') { + if (strpos($name, 'extra.') === 0) { return $this->addSubNode('extra', substr($name, 6), $value); } - if (substr($name, 0, 8) === 'scripts.') { + if (strpos($name, 'scripts.') === 0) { return $this->addSubNode('scripts', substr($name, 8), $value); } @@ -184,15 +184,15 @@ public function addProperty($name, $value) public function removeProperty($name) { - if (substr($name, 0, 8) === 'suggest.') { + if (strpos($name, 'suggest.') === 0) { return $this->removeSubNode('suggest', substr($name, 8)); } - if (substr($name, 0, 6) === 'extra.') { + if (strpos($name, 'extra.') === 0) { return $this->removeSubNode('extra', substr($name, 6)); } - if (substr($name, 0, 8) === 'scripts.') { + if (strpos($name, 'scripts.') === 0) { return $this->removeSubNode('scripts', substr($name, 8)); } diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 3d7b3b614bc2..7f137bf465d7 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -334,7 +334,7 @@ private function createLink($source, $sourceVersion, $description, $target, $pre */ public function getBranchAlias(array $config) { - if ('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4)) { + if (strpos($config['version'], 'dev-') !== 0 && '-dev' !== substr($config['version'], -4)) { return; } diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index 1bcb8b777446..ee63e0aea8c3 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -256,7 +256,7 @@ public function load(array $config, $class = 'Composer\Package\CompletePackage') // check requires for exact constraints ($this->flags & self::CHECK_STRICT_CONSTRAINTS) && 'require' === $linkType - && substr($linkConstraint, 0, 1) === '=' + && strpos($linkConstraint, '=') === 0 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=') ) { $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning'; diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 742758425694..808cf0bde7f2 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -20,8 +20,6 @@ use Composer\Util\HttpDownloader; use Composer\Util\ProcessExecutor; use Composer\Util\Svn as SvnUtil; -use Composer\Util\Platform; -use Composer\Package\Version\VersionParser; /** @@ -96,7 +94,7 @@ public function guessVersion(array $packageConfig, $path) private function postprocess(array $versionData) { - if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version'] && $versionData['feature_pretty_version'] === $versionData['feature_pretty_version']) { + if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version']) { unset($versionData['feature_version'], $versionData['feature_pretty_version']); } @@ -129,7 +127,8 @@ private function guessGitVersion(array $packageConfig, $path) // find current branch and collect all branch names foreach ($this->process->splitLines($output) as $branch) { if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) { - if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') { + if ($match[1] === '(no branch)' || strpos($match[1], '(detached ') === 0 || strpos($match[1], + '(HEAD detached at') === 0) { $version = 'dev-' . $match[2]; $prettyVersion = $version; $isFeatureBranch = true; diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index 7df6e7d70940..88b1873cf917 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -79,7 +79,7 @@ public static function isUpgrade($normalizedFrom, $normalizedTo) $normalizedFrom = str_replace(array('dev-master', 'dev-trunk', 'dev-default'), VersionParser::DEFAULT_BRANCH_ALIAS, $normalizedFrom); $normalizedTo = str_replace(array('dev-master', 'dev-trunk', 'dev-default'), VersionParser::DEFAULT_BRANCH_ALIAS, $normalizedTo); - if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') { + if (strpos($normalizedFrom, 'dev-') === 0 || strpos($normalizedTo, 'dev-') === 0) { return true; } diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 6789c5cb6d7d..77f0288bcdc6 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -20,8 +20,6 @@ use Composer\Json\JsonFile; use Composer\Cache; use Composer\Config; -use Composer\Composer; -use Composer\Factory; use Composer\IO\IOInterface; use Composer\Semver\CompilingMatcher; use Composer\Util\HttpDownloader; @@ -36,7 +34,6 @@ use Composer\Util\Http\Response; use Composer\Util\MetadataMinifier; use Composer\Util\Url; -use React\Promise\Promise; /** * @author Jordi Boggiano @@ -815,7 +812,7 @@ protected function loadRootServerFile() return $this->rootData; } - if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) { + if (!extension_loaded('openssl') && strpos($this->url, 'https') === 0) { throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url); } diff --git a/src/Composer/Repository/RepositoryFactory.php b/src/Composer/Repository/RepositoryFactory.php index 7b7e729d3696..4eeaa14aa5c8 100644 --- a/src/Composer/Repository/RepositoryFactory.php +++ b/src/Composer/Repository/RepositoryFactory.php @@ -46,7 +46,7 @@ public static function configFromString(IOInterface $io, Config $config, $reposi } else { throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository."); } - } elseif ('{' === substr($repository, 0, 1)) { + } elseif (strpos($repository, '{') === 0) { // assume it is a json object that makes a repo config $repoConfig = JsonFile::parseJson($repository); } else { diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 08c831b98e7b..74f8e51bf722 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -302,10 +302,10 @@ protected function initialize() } // make sure branch packages have a dev flag - if ('dev-' === substr($parsedBranch, 0, 4) || VersionParser::DEFAULT_BRANCH_ALIAS === $parsedBranch) { + if (strpos($parsedBranch, 'dev-') === 0 || VersionParser::DEFAULT_BRANCH_ALIAS === $parsedBranch) { $version = 'dev-' . $branch; } else { - $prefix = substr($branch, 0, 1) === 'v' ? 'v' : ''; + $prefix = strpos($branch, 'v') === 0 ? 'v' : ''; $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch); } @@ -314,7 +314,8 @@ protected function initialize() $this->addPackage($cachedPackage); continue; - } elseif ($cachedPackage === false) { + } + if ($cachedPackage === false) { $this->emptyReferences[] = $identifier; continue; diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index d5d818556562..d344d1e433dd 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -444,7 +444,7 @@ public function findShortestPathCode($from, $to, $directories = false, $staticCo */ public function isAbsolutePath($path) { - return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':' || substr($path, 0, 2) === '\\\\'; + return strpos($path, '/') === 0 || substr($path, 1, 1) === ':' || strpos($path, '\\\\') === 0; } /** @@ -487,7 +487,7 @@ public function normalizePath($path) $path = substr($path, \strlen($prefix)); } - if (substr($path, 0, 1) === '/') { + if (strpos($path, '/') === 0) { $absolute = true; $path = substr($path, 1); } diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 13fe3721bf15..03cd0cce8093 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -17,7 +17,6 @@ use Composer\IO\IOInterface; use Composer\Downloader\TransportException; use Composer\CaBundle\CaBundle; -use Composer\Util\HttpDownloader; use Composer\Util\Http\Response; /** @@ -41,7 +40,6 @@ class RemoteFilesystem private $options = array(); private $peerCertificateMap = array(); private $disableTls = false; - private $retryAuthFailure; private $lastHeaders; private $storeAuth; private $authHelper; @@ -206,13 +204,13 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file $this->fileName = $fileName; $this->progress = $progress; $this->lastProgress = null; - $this->retryAuthFailure = true; + $retryAuthFailure = true; $this->lastHeaders = array(); $this->redirects = 1; // The first request counts. $tempAdditionalOptions = $additionalOptions; if (isset($tempAdditionalOptions['retry-auth-failure'])) { - $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure']; + $retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure']; unset($tempAdditionalOptions['retry-auth-failure']); } @@ -239,7 +237,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file $options['http']['ignore_errors'] = true; } - if ($this->degradedMode && substr($fileUrl, 0, 26) === 'http://repo.packagist.org/') { + if ($this->degradedMode && strpos($fileUrl, 'http://repo.packagist.org/') === 0) { // access packagist using the resolved IPv4 instead of the hostname to force IPv4 protocol $fileUrl = 'http://' . gethostbyname('repo.packagist.org') . substr($fileUrl, 20); $degradedPackagist = true; @@ -255,7 +253,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file $actualContextOptions = stream_context_get_options($ctx); $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : ''; - $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . Url::sanitize($origFileUrl) . $usingProxy, true, IOInterface::DEBUG); + $this->io->writeError((strpos($origFileUrl, 'http') === 0 ? 'Downloading ' : 'Reading ') . Url::sanitize($origFileUrl) . $usingProxy, true, IOInterface::DEBUG); unset($origFileUrl, $actualContextOptions); // Check for secure HTTP, but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256 @@ -283,12 +281,12 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header, $maxFileSize); if (!empty($http_response_header[0])) { - $statusCode = $this->findStatusCode($http_response_header); + $statusCode = self::findStatusCode($http_response_header); if ($statusCode >= 400 && Response::findHeaderValue($http_response_header, 'content-type') === 'application/json') { HttpDownloader::outputWarnings($this->io, $originUrl, json_decode($result, true)); } - if (in_array($statusCode, array(401, 403)) && $this->retryAuthFailure) { + if (in_array($statusCode, array(401, 403)) && $retryAuthFailure) { $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), $http_response_header); } } @@ -298,7 +296,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file // alas, this is not possible via the stream callback because STREAM_NOTIFY_COMPLETED is documented, but not implemented anywhere in PHP $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength); $e->setHeaders($http_response_header); - $e->setStatusCode($this->findStatusCode($http_response_header)); + $e->setStatusCode(self::findStatusCode($http_response_header)); try { $e->setResponse($this->decodeResult($result, $http_response_header)); } catch (\Exception $e) { @@ -324,7 +322,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file } catch (\Exception $e) { if ($e instanceof TransportException && !empty($http_response_header[0])) { $e->setHeaders($http_response_header); - $e->setStatusCode($this->findStatusCode($http_response_header)); + $e->setStatusCode(self::findStatusCode($http_response_header)); } if ($e instanceof TransportException && $result !== false) { $e->setResponse($this->decodeResult($result, $http_response_header)); @@ -354,7 +352,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file $contentType = null; $locationHeader = null; if (!empty($http_response_header[0])) { - $statusCode = $this->findStatusCode($http_response_header); + $statusCode = self::findStatusCode($http_response_header); $contentType = Response::findHeaderValue($http_response_header, 'content-type'); $locationHeader = Response::findHeaderValue($http_response_header, 'location'); } @@ -367,7 +365,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file && $contentType && preg_match('{^text/html\b}i', $contentType) ) { $result = false; - if ($this->retryAuthFailure) { + if ($retryAuthFailure) { $this->promptAuthAndRetry(401); } } @@ -378,7 +376,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file && false !== strpos($fileUrl, 'archive.zip') ) { $result = false; - if ($this->retryAuthFailure) { + if ($retryAuthFailure) { $this->promptAuthAndRetry(401); } } @@ -411,7 +409,7 @@ protected function get($originUrl, $fileUrl, $additionalOptions = array(), $file } // decode gzip - if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) { + if ($result && extension_loaded('zlib') && strpos($fileUrl, 'http') === 0 && !$hasFollowedRedirect) { try { $result = $this->decodeResult($result, $http_response_header); } catch (\Exception $e) { @@ -558,6 +556,7 @@ protected function getRemoteContents($originUrl, $fileUrl, $context, array &$res throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . Platform::strlen($result) . ' of allowed ' . $maxFileSize . ' bytes'); } + // https://www.php.net/manual/en/reserved.variables.httpresponseheader.php $responseHeaders = isset($http_response_header) ? $http_response_header : array(); if (null !== $e) { diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index e91707ab3833..5fe3815c5847 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -57,7 +57,7 @@ public static function getContext($url, array $defaultOptions = array(), array $ /** * @param string $url * @param array $options - * @psalm-return array{http:{header: string[], proxy?: string, request_fulluri: bool}, ssl: array} + * @psalm-return array{http:{header: string[], proxy?: string, request_fulluri: bool}, ssl: array} * @return array formatted as a stream context array */ public static function initOptions($url, array $options) @@ -99,9 +99,9 @@ public static function initOptions($url, array $options) if (isset($proxy['port'])) { $proxyURL .= ":" . $proxy['port']; - } elseif ('http://' == substr($proxyURL, 0, 7)) { + } elseif (strpos($proxyURL, 'http://') === 0) { $proxyURL .= ":80"; - } elseif ('https://' == substr($proxyURL, 0, 8)) { + } elseif (strpos($proxyURL, 'https://') === 0) { $proxyURL .= ":443"; } diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index be1a81c9160f..6d91016bd553 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -139,7 +139,7 @@ private function executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose) if ($type !== 'out') { return; } - if ('Redirecting to URL ' === substr($buffer, 0, 19)) { + if (strpos($buffer, 'Redirecting to URL ') === 0) { return; } $output .= $buffer; From 9dc125f79c5ecb9ce92b56b5d977d999518e8725 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 8 Sep 2020 11:14:13 +0200 Subject: [PATCH 2/3] Fix cleanup of useless feature_versions --- src/Composer/Package/Version/VersionGuesser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 808cf0bde7f2..610f17333b84 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -94,7 +94,7 @@ public function guessVersion(array $packageConfig, $path) private function postprocess(array $versionData) { - if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version']) { + if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version'] && $versionData['feature_pretty_version'] === $versionData['pretty_version']) { unset($versionData['feature_version'], $versionData['feature_pretty_version']); } From 7859fe72e88adc5221281a6b2cb1e3b57ee616ef Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 8 Sep 2020 11:15:24 +0200 Subject: [PATCH 3/3] Fix line wrapping --- src/Composer/Package/Version/VersionGuesser.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 610f17333b84..6e71e7d5e9d9 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -127,8 +127,11 @@ private function guessGitVersion(array $packageConfig, $path) // find current branch and collect all branch names foreach ($this->process->splitLines($output) as $branch) { if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) { - if ($match[1] === '(no branch)' || strpos($match[1], '(detached ') === 0 || strpos($match[1], - '(HEAD detached at') === 0) { + if ( + $match[1] === '(no branch)' + || strpos($match[1], '(detached ') === 0 + || strpos($match[1], '(HEAD detached at') === 0 + ) { $version = 'dev-' . $match[2]; $prettyVersion = $version; $isFeatureBranch = true;