diff options
Diffstat (limited to 'lib/private/Updater')
-rw-r--r-- | lib/private/Updater/Changes.php | 3 | ||||
-rw-r--r-- | lib/private/Updater/ChangesCheck.php | 2 | ||||
-rw-r--r-- | lib/private/Updater/ChangesMapper.php | 2 | ||||
-rw-r--r-- | lib/private/Updater/Exceptions/ReleaseMetadataException.php | 17 | ||||
-rw-r--r-- | lib/private/Updater/ReleaseMetadata.php | 79 | ||||
-rw-r--r-- | lib/private/Updater/VersionCheck.php | 25 |
6 files changed, 115 insertions, 13 deletions
diff --git a/lib/private/Updater/Changes.php b/lib/private/Updater/Changes.php index bdf799a0100..c941dfb3fa5 100644 --- a/lib/private/Updater/Changes.php +++ b/lib/private/Updater/Changes.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace OC\Updater; use OCP\AppFramework\Db\Entity; +use OCP\DB\Types; /** * Class Changes @@ -39,7 +40,7 @@ class Changes extends Entity { public function __construct() { $this->addType('version', 'string'); $this->addType('etag', 'string'); - $this->addType('lastCheck', 'int'); + $this->addType('lastCheck', Types::INTEGER); $this->addType('data', 'string'); } } diff --git a/lib/private/Updater/ChangesCheck.php b/lib/private/Updater/ChangesCheck.php index df017b09040..e88969f62a8 100644 --- a/lib/private/Updater/ChangesCheck.php +++ b/lib/private/Updater/ChangesCheck.php @@ -32,7 +32,7 @@ class ChangesCheck { /** * @throws DoesNotExistException - * @return array{changelogURL: string, whatsNew: array<string, array{admin: string[], regular: string[]}>} + * @return array{changelogURL: string, whatsNew: array<string, array{admin: list<string>, regular: list<string>}>} */ public function getChangesForVersion(string $version): array { $version = $this->normalizeVersion($version); diff --git a/lib/private/Updater/ChangesMapper.php b/lib/private/Updater/ChangesMapper.php index 5583cf5a1a6..c399948ff10 100644 --- a/lib/private/Updater/ChangesMapper.php +++ b/lib/private/Updater/ChangesMapper.php @@ -32,7 +32,7 @@ class ChangesMapper extends QBMapper { $result = $qb->select('*') ->from(self::TABLE_NAME) ->where($qb->expr()->eq('version', $qb->createNamedParameter($version))) - ->execute(); + ->executeQuery(); $data = $result->fetch(); $result->closeCursor(); diff --git a/lib/private/Updater/Exceptions/ReleaseMetadataException.php b/lib/private/Updater/Exceptions/ReleaseMetadataException.php new file mode 100644 index 00000000000..bc82e4e03df --- /dev/null +++ b/lib/private/Updater/Exceptions/ReleaseMetadataException.php @@ -0,0 +1,17 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Updater\Exceptions; + +use Exception; + +/** + * @since 30.0.0 + */ +class ReleaseMetadataException extends Exception { +} diff --git a/lib/private/Updater/ReleaseMetadata.php b/lib/private/Updater/ReleaseMetadata.php new file mode 100644 index 00000000000..665847037e7 --- /dev/null +++ b/lib/private/Updater/ReleaseMetadata.php @@ -0,0 +1,79 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Updater; + +use Exception; +use JsonException; +use OC\Updater\Exceptions\ReleaseMetadataException; +use OCP\Http\Client\IClientService; + +/** retrieve releases metadata from official servers + * + * @since 30.0.0 + */ +class ReleaseMetadata { + public function __construct( + private readonly IClientService $clientService, + ) { + } + + /** + * returns metadata based on release version + * + * - version is a stable release, metadata is downloaded from official releases folder + * - version is not a table release, metadata is downloaded from official prereleases folder + * - version is a major version (30, 31, 32, ...), latest metadata are downloaded + * + * @param string $version + * + * @return array + * @throws ReleaseMetadataException + * @since 30.0.0 + */ + public function getMetadata(string $version): array { + if (!str_contains($version, '.')) { + $url = 'https://download.nextcloud.com/server/releases/latest-' . $version . '.metadata'; + } else { + [,,$minor] = explode('.', $version); + if (ctype_digit($minor)) { + $url = 'https://download.nextcloud.com/server/releases/nextcloud-' . $version . '.metadata'; + } else { + $url = 'https://download.nextcloud.com/server/prereleases/nextcloud-' . $version . '.metadata'; + } + } + return $this->downloadMetadata($url); + } + + /** + * download Metadata from a link + * + * @param string $url + * + * @return array + * @throws ReleaseMetadataException + * @since 30.0.0 + */ + public function downloadMetadata(string $url): array { + $client = $this->clientService->newClient(); + try { + $response = $client->get($url, [ + 'timeout' => 10, + 'connect_timeout' => 10 + ]); + } catch (Exception $e) { + throw new ReleaseMetadataException('could not reach metadata at ' . $url, previous: $e); + } + + try { + return json_decode($response->getBody(), true, flags: JSON_THROW_ON_ERROR); + } catch (JsonException) { + throw new ReleaseMetadataException('remote document is not valid'); + } + } +} diff --git a/lib/private/Updater/VersionCheck.php b/lib/private/Updater/VersionCheck.php index 9ad129db1a4..be410b06c3e 100644 --- a/lib/private/Updater/VersionCheck.php +++ b/lib/private/Updater/VersionCheck.php @@ -11,12 +11,14 @@ use OCP\Http\Client\IClientService; use OCP\IAppConfig; use OCP\IConfig; use OCP\IUserManager; +use OCP\ServerVersion; use OCP\Support\Subscription\IRegistry; use OCP\Util; use Psr\Log\LoggerInterface; class VersionCheck { public function __construct( + private ServerVersion $serverVersion, private IClientService $clientService, private IConfig $config, private IAppConfig $appConfig, @@ -54,14 +56,14 @@ class VersionCheck { $version = Util::getVersion(); $version['installed'] = $this->config->getAppValue('core', 'installedat'); $version['updated'] = $this->appConfig->getValueInt('core', 'lastupdatedat'); - $version['updatechannel'] = \OC_Util::getChannel(); + $version['updatechannel'] = $this->serverVersion->getChannel(); $version['edition'] = ''; - $version['build'] = \OC_Util::getBuild(); + $version['build'] = $this->serverVersion->getBuild(); $version['php_major'] = PHP_MAJOR_VERSION; $version['php_minor'] = PHP_MINOR_VERSION; $version['php_release'] = PHP_RELEASE_VERSION; $version['category'] = $this->computeCategory(); - $version['isSubscriber'] = (int) $this->registry->delegateHasValidSubscription(); + $version['isSubscriber'] = (int)$this->registry->delegateHasValidSubscription(); $versionString = implode('x', $version); //fetch xml data from updater @@ -103,17 +105,20 @@ class VersionCheck { } /** - * @codeCoverageIgnore - * @param string $url - * @return resource|string * @throws \Exception */ - protected function getUrlContent($url) { - $client = $this->clientService->newClient(); - $response = $client->get($url, [ + protected function getUrlContent(string $url): string { + $response = $this->clientService->newClient()->get($url, [ 'timeout' => 5, ]); - return $response->getBody(); + + $content = $response->getBody(); + + // IResponse.getBody responds with null|resource if returning a stream response was requested. + // As that's not the case here, we can just ignore the psalm warning by adding an assertion. + assert(is_string($content)); + + return $content; } private function computeCategory(): int { |