aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Updater
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Updater')
-rw-r--r--lib/private/Updater/Changes.php3
-rw-r--r--lib/private/Updater/ChangesCheck.php2
-rw-r--r--lib/private/Updater/ChangesMapper.php2
-rw-r--r--lib/private/Updater/Exceptions/ReleaseMetadataException.php17
-rw-r--r--lib/private/Updater/ReleaseMetadata.php79
-rw-r--r--lib/private/Updater/VersionCheck.php25
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 {