From 4d85e217c30ebcc67618e0978cd99544f7aeb634 Mon Sep 17 00:00:00 2001 From: Andreas Schempp Date: Sat, 16 Feb 2019 18:46:59 +0100 Subject: [PATCH] Extract the ZIP utility functions from ArtifactRepository --- .../Repository/ArtifactRepository.php | 66 +------------ src/Composer/Util/Zip.php | 96 +++++++++++++++++++ 2 files changed, 100 insertions(+), 62 deletions(-) create mode 100644 src/Composer/Util/Zip.php diff --git a/src/Composer/Repository/ArtifactRepository.php b/src/Composer/Repository/ArtifactRepository.php index 079d34c54..223ea4aef 100644 --- a/src/Composer/Repository/ArtifactRepository.php +++ b/src/Composer/Repository/ArtifactRepository.php @@ -16,6 +16,7 @@ use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\LoaderInterface; +use Composer\Util\Zip; /** * @author Serge Smertin @@ -80,73 +81,14 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito } } - /** - * Find a file by name, returning the one that has the shortest path. - * - * @param \ZipArchive $zip - * @param string $filename - * @return bool|int - */ - private function locateFile(\ZipArchive $zip, $filename) - { - $indexOfShortestMatch = false; - $lengthOfShortestMatch = -1; - - for ($i = 0; $i < $zip->numFiles; $i++) { - $stat = $zip->statIndex($i); - if (strcmp(basename($stat['name']), $filename) === 0) { - $directoryName = dirname($stat['name']); - if ($directoryName == '.') { - //if composer.json is in root directory - //it has to be the one to use. - return $i; - } - - if (strpos($directoryName, '\\') !== false || - strpos($directoryName, '/') !== false) { - //composer.json files below first directory are rejected - continue; - } - - $length = strlen($stat['name']); - if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) { - //Check it's not a directory. - $contents = $zip->getFromIndex($i); - if ($contents !== false) { - $indexOfShortestMatch = $i; - $lengthOfShortestMatch = $length; - } - } - } - } - - return $indexOfShortestMatch; - } - private function getComposerInformation(\SplFileInfo $file) { - $zip = new \ZipArchive(); - if ($zip->open($file->getPathname()) !== true) { + $composerFile = Zip::findFile($file->getPathname(), 'composer.json'); + + if (null === $composerFile) { return false; } - if (0 == $zip->numFiles) { - $zip->close(); - - return false; - } - - $foundFileIndex = $this->locateFile($zip, 'composer.json'); - if (false === $foundFileIndex) { - $zip->close(); - - return false; - } - - $configurationFileName = $zip->getNameIndex($foundFileIndex); - $zip->close(); - - $composerFile = "zip://{$file->getPathname()}#$configurationFileName"; $json = file_get_contents($composerFile); $package = JsonFile::parseJson($json, $composerFile); diff --git a/src/Composer/Util/Zip.php b/src/Composer/Util/Zip.php new file mode 100644 index 000000000..1dfd99d39 --- /dev/null +++ b/src/Composer/Util/Zip.php @@ -0,0 +1,96 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Util; + +/** + * @author Jordi Boggiano + */ +class Zip +{ + /** + * Finds the path to a file inside a ZIP archive. + * + * @param $pathToZip + * @param $filename + * + * @return string|null + */ + public static function findFile($pathToZip, $filename) + { + $zip = new \ZipArchive(); + if ($zip->open($pathToZip) !== true) { + return null; + } + + if (0 == $zip->numFiles) { + $zip->close(); + + return null; + } + + $foundFileIndex = static::locateFile($zip, $filename); + if (false === $foundFileIndex) { + $zip->close(); + + return null; + } + + $configurationFileName = $zip->getNameIndex($foundFileIndex); + $zip->close(); + + return "zip://{$pathToZip}#$configurationFileName"; + } + + /** + * Find a file by name, returning the one that has the shortest path. + * + * @param \ZipArchive $zip + * @param string $filename + * @return bool|int + */ + private static function locateFile(\ZipArchive $zip, $filename) + { + $indexOfShortestMatch = false; + $lengthOfShortestMatch = -1; + + for ($i = 0; $i < $zip->numFiles; $i++) { + $stat = $zip->statIndex($i); + if (strcmp(basename($stat['name']), $filename) === 0) { + $directoryName = dirname($stat['name']); + if ($directoryName == '.') { + //if composer.json is in root directory + //it has to be the one to use. + return $i; + } + + if (strpos($directoryName, '\\') !== false || + strpos($directoryName, '/') !== false) { + //composer.json files below first directory are rejected + continue; + } + + $length = strlen($stat['name']); + if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) { + //Check it's not a directory. + $contents = $zip->getFromIndex($i); + if ($contents !== false) { + $indexOfShortestMatch = $i; + $lengthOfShortestMatch = $length; + } + } + } + } + + return $indexOfShortestMatch; + } +}