From eb0aaa7472870898d3405ebe24108838caa80848 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 29 Mar 2022 11:44:25 +0100 Subject: [PATCH 1/3] Bitbucket: handle missing authentication response from API returning 404 status code (#10657) --- src/Composer/Repository/Vcs/GitBitbucketDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index dd4033991..8659d214d 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -390,7 +390,7 @@ class GitBitbucketDriver extends VcsDriver } catch (TransportException $e) { $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->httpDownloader); - if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) { + if (in_array($e->getCode(), array(403, 404), true) || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) { if (!$this->io->hasAuthentication($this->originUrl) && $bitbucketUtil->authorizeOAuth($this->originUrl) ) { From dca0a655976ca6414d98214564369a781db82094 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 29 Mar 2022 15:57:04 +0200 Subject: [PATCH 2/3] Add source/dist keys to root schema, fixes #10655 --- res/composer-schema.json | 82 +++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/res/composer-schema.json b/res/composer-schema.json index f636fc9f5..1d99030ff 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -132,6 +132,12 @@ } } }, + "source": { + "$ref": "#/definitions/source" + }, + "dist": { + "$ref": "#/definitions/dist" + }, "_comment": { "type": ["array", "string"], "description": "A key to store comments in" @@ -953,46 +959,52 @@ } }, "source": { - "type": "object", - "required": ["type", "url", "reference"], - "properties": { - "type": { - "type": "string" - }, - "url": { - "type": "string" - }, - "reference": { - "type": "string" - }, - "mirrors": { - "type": "array" - } - } + "$ref": "#/definitions/source" }, "dist": { - "type": "object", - "required": ["type", "url"], - "properties": { - "type": { - "type": "string" - }, - "url": { - "type": "string" - }, - "reference": { - "type": "string" - }, - "shasum": { - "type": "string" - }, - "mirrors": { - "type": "array" - } - } + "$ref": "#/definitions/dist" } }, "additionalProperties": true + }, + "source": { + "type": "object", + "required": ["type", "url", "reference"], + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "mirrors": { + "type": "array" + } + } + }, + "dist": { + "type": "object", + "required": ["type", "url"], + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + }, + "mirrors": { + "type": "array" + } + } } } } From 2dbe66ad203460453c49f7011e539a806dfde9a8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 29 Mar 2022 18:57:30 +0200 Subject: [PATCH 3/3] Fix deletion of corrupt 0-bytes zip archives from the cache, fixes #10580 (#10666) --- src/Composer/Downloader/ArchiveDownloader.php | 4 +++- src/Composer/Downloader/ZipDownloader.php | 9 ++++++++- .../Test/Downloader/ZipDownloaderTest.php | 19 ++++++++++++------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/Composer/Downloader/ArchiveDownloader.php b/src/Composer/Downloader/ArchiveDownloader.php index 570de63d8..4f2467d71 100644 --- a/src/Composer/Downloader/ArchiveDownloader.php +++ b/src/Composer/Downloader/ArchiveDownloader.php @@ -120,7 +120,9 @@ abstract class ArchiveDownloader extends FileDownloader } return $promise->then(function () use ($self, $package, $filesystem, $fileName, $temporaryDir, $path) { - $filesystem->unlink($fileName); + if (file_exists($fileName)) { + $filesystem->unlink($fileName); + } /** * Returns the folder content, excluding .DS_Store diff --git a/src/Composer/Downloader/ZipDownloader.php b/src/Composer/Downloader/ZipDownloader.php index a86d1da6b..fe1bfdc69 100644 --- a/src/Composer/Downloader/ZipDownloader.php +++ b/src/Composer/Downloader/ZipDownloader.php @@ -184,7 +184,12 @@ class ZipDownloader extends ArchiveDownloader $zipArchive = $this->zipArchiveObject ?: new ZipArchive(); try { - if (true === ($retval = $zipArchive->open($file))) { + if (!file_exists($file) || ($filesize = filesize($file)) === false || $filesize === 0) { + $retval = -1; + } else { + $retval = $zipArchive->open($file); + } + if (true === $retval) { $extractResult = $zipArchive->extractTo($path); if (true === $extractResult) { @@ -251,6 +256,8 @@ class ZipDownloader extends ArchiveDownloader return sprintf("Zip read error (%s)", $file); case ZipArchive::ER_SEEK: return sprintf("Zip seek error (%s)", $file); + case -1: + return sprintf("'%s' is a corrupted zip archive (0 bytes), try again.", $file); default: return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval); } diff --git a/tests/Composer/Test/Downloader/ZipDownloaderTest.php b/tests/Composer/Test/Downloader/ZipDownloaderTest.php index b8e148f2b..0db2da237 100644 --- a/tests/Composer/Test/Downloader/ZipDownloaderTest.php +++ b/tests/Composer/Test/Downloader/ZipDownloaderTest.php @@ -31,6 +31,8 @@ class ZipDownloaderTest extends TestCase private $config; /** @var \Composer\Package\PackageInterface&\PHPUnit\Framework\MockObject\MockObject */ private $package; + /** @var string */ + private $filename; public function setUp() { @@ -40,6 +42,9 @@ class ZipDownloaderTest extends TestCase $dlConfig = $this->getMockBuilder('Composer\Config')->getMock(); $this->httpDownloader = new HttpDownloader($this->io, $dlConfig); $this->package = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock(); + + $this->filename = $this->testDir.'/composer-test.zip'; + file_put_contents($this->filename, 'zip'); } public function tearDown() @@ -123,7 +128,7 @@ class ZipDownloaderTest extends TestCase ->will($this->returnValue(false)); $this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); - $promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir'); + $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); $this->wait($promise); } @@ -145,7 +150,7 @@ class ZipDownloaderTest extends TestCase ->will($this->throwException(new \ErrorException('Not a directory'))); $this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); - $promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir'); + $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); $this->wait($promise); } @@ -166,7 +171,7 @@ class ZipDownloaderTest extends TestCase ->will($this->returnValue(true)); $this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); - $promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir'); + $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); $this->wait($promise); } @@ -194,7 +199,7 @@ class ZipDownloaderTest extends TestCase ->will($this->returnValue(\React\Promise\resolve($procMock))); $downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); - $promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir'); + $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); $this->wait($promise); } @@ -221,7 +226,7 @@ class ZipDownloaderTest extends TestCase ->will($this->returnValue(\React\Promise\resolve($procMock))); $downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); - $promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir'); + $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); $this->wait($promise); } @@ -260,7 +265,7 @@ class ZipDownloaderTest extends TestCase $downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); $this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); - $promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir'); + $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); $this->wait($promise); } @@ -300,7 +305,7 @@ class ZipDownloaderTest extends TestCase $downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); $this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); - $promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir'); + $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); $this->wait($promise); }