From 9010937535eb701be6a5891d791e53954123ea97 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Tue, 26 Jan 2021 16:35:43 +0100 Subject: [PATCH] Fix app fetcher php comparison to allow wider ranges When app app specifies php 7.4 as upper limit we have to allow the installation on php>7.4.0. The previous version check didn't do that. This adjusts the regexes to discard any irrelevant suffix after the three version numbers so that we can use more fine granular checks than php's version_compare can do out of the box, like for php 7.4 we only compare the major and minor version numbers and ignore the patch level. Signed-off-by: Christoph Wurst --- lib/private/App/CompareVersion.php | 25 +++++++++++++++---------- tests/lib/App/CompareVersionTest.php | 8 ++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/private/App/CompareVersion.php b/lib/private/App/CompareVersion.php index 5d38d4c358..9df28a457f 100644 --- a/lib/private/App/CompareVersion.php +++ b/lib/private/App/CompareVersion.php @@ -1,4 +1,7 @@ * @@ -24,12 +27,13 @@ namespace OC\App; use InvalidArgumentException; +use function explode; class CompareVersion { - public const REGEX_MAJOR = '/^\d+$/'; - public const REGEX_MAJOR_MINOR = '/^\d+.\d+$/'; - public const REGEX_MAJOR_MINOR_PATCH = '/^\d+.\d+.\d+$/'; - public const REGEX_SERVER = '/^\d+.\d+.\d+(.\d+)?$/'; + private const REGEX_MAJOR = '/^\d+$/'; + private const REGEX_MAJOR_MINOR = '/^\d+\.\d+$/'; + private const REGEX_MAJOR_MINOR_PATCH = '/^\d+\.\d+\.\d+(?!\.\d+)/'; + private const REGEX_ACTUAL = '/^\d+(\.\d+){1,2}/'; /** * Checks if the given server version fulfills the given (app) version requirements. @@ -45,18 +49,19 @@ class CompareVersion { */ public function isCompatible(string $actual, string $required, string $comparator = '>='): bool { - if (!preg_match(self::REGEX_SERVER, $actual)) { - throw new InvalidArgumentException('server version is invalid'); + if (!preg_match(self::REGEX_ACTUAL, $actual, $matches)) { + throw new InvalidArgumentException("version specification $actual is invalid"); } + $cleanActual = $matches[0]; if (preg_match(self::REGEX_MAJOR, $required) === 1) { - return $this->compareMajor($actual, $required, $comparator); + return $this->compareMajor($cleanActual, $required, $comparator); } elseif (preg_match(self::REGEX_MAJOR_MINOR, $required) === 1) { - return $this->compareMajorMinor($actual, $required, $comparator); + return $this->compareMajorMinor($cleanActual, $required, $comparator); } elseif (preg_match(self::REGEX_MAJOR_MINOR_PATCH, $required) === 1) { - return $this->compareMajorMinorPatch($actual, $required, $comparator); + return $this->compareMajorMinorPatch($cleanActual, $required, $comparator); } else { - throw new InvalidArgumentException('required version is invalid'); + throw new InvalidArgumentException("required version $required is invalid"); } } diff --git a/tests/lib/App/CompareVersionTest.php b/tests/lib/App/CompareVersionTest.php index 6db31d0ee6..d94b6f18a0 100644 --- a/tests/lib/App/CompareVersionTest.php +++ b/tests/lib/App/CompareVersionTest.php @@ -1,5 +1,7 @@ * @@ -49,11 +51,17 @@ class CompareVersionTest extends TestCase { ['13.0.0', '13', '>=', true], ['13.0.1', '13', '>=', true], ['13.0.1', '13', '<=', true], + ['13.0.1.9', '13', '<=', true], + ['13.0.1-beta.1', '13', '<=', true], + ['7.4.14', '7.4', '<=', true], + ['7.4.14-ubuntu', '7.4', '<=', true], + ['7.4.14-ubuntu', '7.4.15', '<=', true], // Incompatible major versions ['13.0.0.3', '13.0.0', '<', false], ['12.0.0', '13.0.0', '>=', false], ['12.0.0', '13.0', '>=', false], ['12.0.0', '13', '>=', false], + ['7.4.15-ubuntu', '7.4.15', '>=', true], // Incompatible minor and patch versions ['13.0.0', '13.0.1', '>=', false], ['13.0.0', '13.1', '>=', false],