summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2015-08-30 16:21:55 +0200
committerVincent Petry <pvince81@owncloud.com>2015-08-30 18:04:18 +0200
commit2b08659f7d18d458339bcd89687469d8926f4941 (patch)
treead1ddb3aac8d8d3bb5eff26d65ea4a2eab35dfc1
parent045f8cc97101521cafd664faf7b8f24ea9e88451 (diff)
downloadnextcloud-server-2b08659f7d18d458339bcd89687469d8926f4941.tar.gz
nextcloud-server-2b08659f7d18d458339bcd89687469d8926f4941.zip
Restrict upgrades to explicit allowed version
version.php now contains the previous ownCloud version from which upgrades are allowed. Any other upgrades will show a message that the upgrade/downgrade is not supported.
-rw-r--r--lib/private/updater.php40
-rw-r--r--tests/lib/updater.php74
-rw-r--r--version.php11
3 files changed, 105 insertions, 20 deletions
diff --git a/lib/private/updater.php b/lib/private/updater.php
index f73fa8ff655..0f9ecfe93de 100644
--- a/lib/private/updater.php
+++ b/lib/private/updater.php
@@ -212,19 +212,46 @@ class Updater extends BasicEmitter {
}
/**
+ * Return version from which this version is allowed to upgrade from
+ *
+ * @return string allowed previous version
+ */
+ private function getAllowedPreviousVersion() {
+ // this should really be a JSON file
+ require \OC::$SERVERROOT . '/version.php';
+ return implode('.', $OC_VersionCanBeUpgradedFrom);
+ }
+
+ /**
* Whether an upgrade to a specified version is possible
* @param string $oldVersion
* @param string $newVersion
+ * @param string $allowedPreviousVersion
* @return bool
*/
- public function isUpgradePossible($oldVersion, $newVersion) {
+ public function isUpgradePossible($oldVersion, $newVersion, $allowedPreviousVersion) {
+ // downgrade is never allowed
+ if (version_compare($oldVersion, $newVersion, '>')) {
+ return false;
+ }
+
$oldVersion = explode('.', $oldVersion);
$newVersion = explode('.', $newVersion);
- if($newVersion[0] > ($oldVersion[0] + 1) || $oldVersion[0] > $newVersion[0]) {
- return false;
+ while (count($oldVersion) > 2) {
+ array_pop($oldVersion);
+ }
+
+ while (count($newVersion) > 2) {
+ array_pop($newVersion);
}
- return true;
+
+ $oldVersion = implode('.', $oldVersion);
+ $newVersion = implode('.', $newVersion);
+
+ // either we're updating from an allowed version or the current version
+ return (version_compare($allowedPreviousVersion, $oldVersion) === 0
+ || version_compare($newVersion, $oldVersion) === 0);
}
/**
@@ -259,8 +286,9 @@ class Updater extends BasicEmitter {
*/
private function doUpgrade($currentVersion, $installedVersion) {
// Stop update if the update is over several major versions
- if (!self::isUpgradePossible($installedVersion, $currentVersion)) {
- throw new \Exception('Updates between multiple major versions are unsupported.');
+ $allowedPreviousVersion = $this->getAllowedPreviousVersion();
+ if (!self::isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersion)) {
+ throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
}
// Update .htaccess files
diff --git a/tests/lib/updater.php b/tests/lib/updater.php
index 28577071b4c..763858acf5d 100644
--- a/tests/lib/updater.php
+++ b/tests/lib/updater.php
@@ -67,14 +67,68 @@ class UpdaterTest extends \Test\TestCase {
*/
public function versionCompatibilityTestData() {
return [
- ['1.0.0.0', '2.2.0', true],
- ['1.1.1.1', '2.0.0', true],
- ['5.0.3', '4.0.3', false],
- ['12.0.3', '13.4.5', true],
- ['1', '2', true],
- ['2', '2', true],
- ['6.0.5', '6.0.6', true],
- ['5.0.6', '7.0.4', false],
+ ['1', '2', '1', true],
+ ['2', '2', '2', true],
+ ['6.0.5.0', '6.0.6.0', '5.0', true],
+ ['5.0.6.0', '7.0.4.0', '6.0', false],
+ // allow upgrading within the same major release
+ ['8.0.0.0', '8.0.0.0', '8.0', true],
+ ['8.0.0.0', '8.0.0.4', '8.0', true],
+ ['8.0.0.0', '8.0.1.0', '8.0', true],
+ ['8.0.0.0', '8.0.2.0', '8.0', true],
+ // does not allow downgrading within the same major release
+ ['8.0.1.0', '8.0.0.0', '8.0', false],
+ ['8.0.2.0', '8.0.1.0', '8.0', false],
+ ['8.0.0.4', '8.0.0.0', '8.0', false],
+ // allows upgrading within the patch version
+ ['8.0.0.0', '8.0.0.1', '8.0', true],
+ ['8.0.0.0', '8.0.0.2', '8.0', true],
+ // does not allow downgrading within the same major release
+ ['8.0.0.1', '8.0.0.0', '8.0', false],
+ ['8.0.0.2', '8.0.0.0', '8.0', false],
+ // allow upgrading to the next major release
+ ['8.0.0.0', '8.1.0.0', '8.0', true],
+ ['8.0.0.0', '8.1.1.0', '8.0', true],
+ ['8.0.0.0', '8.1.1.5', '8.0', true],
+ ['8.0.0.2', '8.1.1.5', '8.0', true],
+ ['8.1.0.0', '8.2.0.0', '8.1', true],
+ ['8.1.0.2', '8.2.0.4', '8.1', true],
+ ['8.1.0.5', '8.2.0.1', '8.1', true],
+ ['8.1.0.0', '8.2.1.0', '8.1', true],
+ ['8.1.0.2', '8.2.1.5', '8.1', true],
+ ['8.1.0.5', '8.2.1.1', '8.1', true],
+ // does not allow downgrading to the previous major release
+ ['8.1.0.0', '8.0.0.0', '7.0', false],
+ ['8.1.1.0', '8.0.0.0', '7.0', false],
+ // does not allow skipping major releases
+ ['8.0.0.0', '8.2.0.0', '8.1', false],
+ ['8.0.0.0', '8.2.1.0', '8.1', false],
+ ['8.0.0.0', '9.0.1.0', '8.2', false],
+ ['8.0.0.0', '10.0.0.0', '9.3', false],
+ // allows updating to the next major release
+ ['8.2.0.0', '9.0.0.0', '8.2', true],
+ ['8.2.0.0', '9.0.0.0', '8.2', true],
+ ['8.2.0.0', '9.0.1.0', '8.2', true],
+ ['8.2.0.0', '9.0.1.1', '8.2', true],
+ ['8.2.0.2', '9.0.1.1', '8.2', true],
+ ['8.2.2.0', '9.0.1.0', '8.2', true],
+ ['8.2.2.2', '9.0.1.1', '8.2', true],
+ ['9.0.0.0', '9.1.0.0', '9.0', true],
+ ['9.0.0.0', '9.1.0.2', '9.0', true],
+ ['9.0.0.2', '9.1.0.1', '9.0', true],
+ ['9.1.0.0', '9.2.0.0', '9.1', true],
+ ['9.2.0.0', '9.3.0.0', '9.2', true],
+ ['9.3.0.0', '10.0.0.0', '9.3', true],
+ // does not allow updating to the next major release (first number)
+ ['9.0.0.0', '8.2.0.0', '8.1', false],
+ // other cases
+ ['8.0.0.0', '8.1.5.0', '8.0', true],
+ ['8.2.0.0', '9.0.0.0', '8.2', true],
+ ['8.2.0.0', '9.1.0.0', '9.0', false],
+ ['9.0.0.0', '8.1.0.0', '8.0', false],
+ ['9.0.0.0', '8.0.0.0', '7.0', false],
+ ['9.1.0.0', '8.0.0.0', '7.0', false],
+ ['8.2.0.0', '8.1.0.0', '8.0', false],
];
}
@@ -106,9 +160,9 @@ class UpdaterTest extends \Test\TestCase {
* @param string $newVersion
* @param bool $result
*/
- public function testIsUpgradePossible($oldVersion, $newVersion, $result) {
+ public function testIsUpgradePossible($oldVersion, $newVersion, $allowedVersion, $result) {
$updater = new Updater($this->httpHelper, $this->config);
- $this->assertSame($result, $updater->isUpgradePossible($oldVersion, $newVersion));
+ $this->assertSame($result, $updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersion));
}
public function testCheckInCache() {
diff --git a/version.php b/version.php
index a115f4b26be..a6b49d9dc74 100644
--- a/version.php
+++ b/version.php
@@ -2,6 +2,7 @@
/**
* @author Frank Karlitschek <frank@owncloud.org>
* @author Lukas Reschke <lukas@owncloud.com>
+ * @author Vincent Petry <pvince81@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
@@ -22,14 +23,16 @@
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version=array(8, 2, 0, 4);
+$OC_Version = [8, 2, 0, 4];
// The human readable string
-$OC_VersionString='8.2 pre alpha';
+$OC_VersionString = '8.2 pre alpha';
+
+$OC_VersionCanBeUpgradedFrom = [8, 1];
// The ownCloud channel
-$OC_Channel='git';
+$OC_Channel = 'git';
// The build number
-$OC_Build='';
+$OC_Build = '';