diff --git a/index.php b/index.php index 95900b1a..5461998c 100644 --- a/index.php +++ b/index.php @@ -572,11 +572,9 @@ private function getUpdateServerResponse(): array { * * @throws \Exception */ - public function downloadUpdate(): void { + public function downloadUpdate(?string $url = null): void { $this->silentLog('[info] downloadUpdate()'); - $response = $this->getUpdateServerResponse(); - $storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOptionMandatoryString('instanceid') . '/downloads/'; if (file_exists($storageLocation)) { $this->silentLog('[info] storage location exists'); @@ -587,12 +585,26 @@ public function downloadUpdate(): void { throw new \Exception('Could not mkdir storage location'); } - if (!isset($response['url']) || !is_string($response['url'])) { - throw new \Exception('Response from update server is missing url'); + $downloadURL = ''; + if ($url) { + // If a URL is provided, use it directly + $downloadURL = $url; + } else { + // Otherwise, get the download URLs from the update server + $response = $this->getUpdateServerResponse(); + + if (!isset($response['url']) || !is_string($response['url'])) { + throw new \Exception('Response from update server is missing url'); + } + $downloadURL = $response['url']; + } + + if (!$downloadURL) { + throw new \Exception('No download URL provided or available from update server'); } - $fp = fopen($storageLocation . basename($response['url']), 'w+'); - $ch = curl_init($response['url']); + $fp = fopen($storageLocation . basename($downloadURL), 'w+'); + $ch = curl_init($downloadURL); curl_setopt_array($ch, [ CURLOPT_FILE => $fp, CURLOPT_USERAGENT => 'Nextcloud Updater', @@ -636,7 +648,7 @@ public function downloadUpdate(): void { $message .= ' - curl error message: ' . $curlErrorMessage; } - $message .= ' - URL: ' . htmlentities($response['url']); + $message .= ' - URL: ' . htmlentities($downloadURL); throw new \Exception($message); } @@ -669,7 +681,7 @@ private function getDownloadedFilePath(): string { * * @throws \Exception */ - public function verifyIntegrity(): void { + public function verifyIntegrity(?string $urlOverride = null): void { $this->silentLog('[info] verifyIntegrity()'); if ($this->getCurrentReleaseChannel() === 'daily') { @@ -677,6 +689,11 @@ public function verifyIntegrity(): void { return; } + if ($urlOverride) { + $this->silentLog('[info] custom download url provided, cannot verify signature'); + return; + } + $response = $this->getUpdateServerResponse(); if (empty($response['signature'])) { throw new \Exception('No signature specified for defined update'); diff --git a/lib/UpdateCommand.php b/lib/UpdateCommand.php index 2c7c75bb..8015e5d8 100644 --- a/lib/UpdateCommand.php +++ b/lib/UpdateCommand.php @@ -39,6 +39,7 @@ class UpdateCommand extends Command { protected bool $shouldStop = false; protected bool $skipBackup = false; protected bool $skipUpgrade = false; + protected string $urlOverride = ''; /** @var list strings of text for stages of updater */ protected array $checkTexts = [ @@ -63,7 +64,8 @@ protected function configure(): void { ->setDescription('Updates the code of an Nextcloud instance') ->setHelp("This command fetches the latest code that is announced via the updater server and safely replaces the existing code with the new one.") ->addOption('no-backup', null, InputOption::VALUE_NONE, 'Skip backup of current Nextcloud version') - ->addOption('no-upgrade', null, InputOption::VALUE_NONE, "Don't automatically run occ upgrade"); + ->addOption('no-upgrade', null, InputOption::VALUE_NONE, "Don't automatically run occ upgrade") + ->addOption('url', null, InputOption::VALUE_OPTIONAL, 'The URL of the Nextcloud release to download'); } public static function getUpdaterVersion(): string { @@ -78,6 +80,7 @@ public static function getUpdaterVersion(): string { protected function execute(InputInterface $input, OutputInterface $output) { $this->skipBackup = (bool)$input->getOption('no-backup'); $this->skipUpgrade = (bool)$input->getOption('no-upgrade'); + $this->urlOverride = (string)$input->getOption('url'); $version = static::getUpdaterVersion(); $output->writeln('Nextcloud Updater - version: ' . $version); @@ -151,7 +154,12 @@ protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln('Current version is ' . $this->updater->getCurrentVersion() . '.'); // needs to be called that early because otherwise updateAvailable() returns false - $updateString = $this->updater->checkForUpdate(); + if ($this->urlOverride) { + $this->updater->log('[info] Using URL override: ' . $this->urlOverride); + $updateString = 'Update check forced with URL override: ' . $this->urlOverride; + } else { + $updateString = $this->updater->checkForUpdate(); + } $output->writeln(''); @@ -164,9 +172,11 @@ protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln(''); - if (!$this->updater->updateAvailable() && $stepNumber === 0) { - $output->writeln('Nothing to do.'); - return 0; + if (!$this->urlOverride) { + if (!$this->updater->updateAvailable() && $stepNumber === 0) { + $output->writeln('Nothing to do.'); + return 0; + } } $questionText = 'Start update'; @@ -378,10 +388,10 @@ protected function executeStep(int $step): array { } break; case 4: - $this->updater->downloadUpdate(); + $this->updater->downloadUpdate($this->urlOverride); break; case 5: - $this->updater->verifyIntegrity(); + $this->updater->verifyIntegrity($this->urlOverride); break; case 6: $this->updater->extractDownload(); diff --git a/lib/Updater.php b/lib/Updater.php index ea31dca2..f6d3c687 100644 --- a/lib/Updater.php +++ b/lib/Updater.php @@ -3,25 +3,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2016-2017 Lukas Reschke - * @copyright Copyright (c) 2016 Morris Jobke - * @copyright Copyright (c) 2018 Jonas Sulzer - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace NC\Updater; @@ -534,11 +517,9 @@ private function getUpdateServerResponse(): array { * * @throws \Exception */ - public function downloadUpdate(): void { + public function downloadUpdate(?string $url = null): void { $this->silentLog('[info] downloadUpdate()'); - $response = $this->getUpdateServerResponse(); - $storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOptionMandatoryString('instanceid') . '/downloads/'; if (file_exists($storageLocation)) { $this->silentLog('[info] storage location exists'); @@ -549,12 +530,26 @@ public function downloadUpdate(): void { throw new \Exception('Could not mkdir storage location'); } - if (!isset($response['url']) || !is_string($response['url'])) { - throw new \Exception('Response from update server is missing url'); + $downloadURL = ''; + if ($url) { + // If a URL is provided, use it directly + $downloadURL = $url; + } else { + // Otherwise, get the download URLs from the update server + $response = $this->getUpdateServerResponse(); + + if (!isset($response['url']) || !is_string($response['url'])) { + throw new \Exception('Response from update server is missing url'); + } + $downloadURL = $response['url']; + } + + if (!$downloadURL) { + throw new \Exception('No download URL provided or available from update server'); } - $fp = fopen($storageLocation . basename($response['url']), 'w+'); - $ch = curl_init($response['url']); + $fp = fopen($storageLocation . basename($downloadURL), 'w+'); + $ch = curl_init($downloadURL); curl_setopt_array($ch, [ CURLOPT_FILE => $fp, CURLOPT_USERAGENT => 'Nextcloud Updater', @@ -598,7 +593,7 @@ public function downloadUpdate(): void { $message .= ' - curl error message: ' . $curlErrorMessage; } - $message .= ' - URL: ' . htmlentities($response['url']); + $message .= ' - URL: ' . htmlentities($downloadURL); throw new \Exception($message); } @@ -631,7 +626,7 @@ private function getDownloadedFilePath(): string { * * @throws \Exception */ - public function verifyIntegrity(): void { + public function verifyIntegrity(?string $urlOverride = null): void { $this->silentLog('[info] verifyIntegrity()'); if ($this->getCurrentReleaseChannel() === 'daily') { @@ -639,6 +634,11 @@ public function verifyIntegrity(): void { return; } + if ($urlOverride) { + $this->silentLog('[info] custom download url provided, cannot verify signature'); + return; + } + $response = $this->getUpdateServerResponse(); if (empty($response['signature'])) { throw new \Exception('No signature specified for defined update'); diff --git a/updater.phar b/updater.phar index a652b802..bb10f2fe 100755 Binary files a/updater.phar and b/updater.phar differ diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 2d4a8348..79f895d6 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '9adb775ee0ca02d832347ddfea2b4c248f2805bc', + 'reference' => '088152d70d870f9021ea6231578e59d7dbbd6fd0', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,7 +13,7 @@ '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '9adb775ee0ca02d832347ddfea2b4c248f2805bc', + 'reference' => '088152d70d870f9021ea6231578e59d7dbbd6fd0', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php index 580fa960..d2225c7d 100644 --- a/vendor/composer/platform_check.php +++ b/vendor/composer/platform_check.php @@ -19,8 +19,7 @@ echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; } } - trigger_error( - 'Composer detected issues in your platform: ' . implode(' ', $issues), - E_USER_ERROR + throw new \RuntimeException( + 'Composer detected issues in your platform: ' . implode(' ', $issues) ); }