Skip to content
Snippets Groups Projects
Commit 2b08659f authored by Vincent Petry's avatar Vincent Petry
Browse files

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.
parent 045f8cc9
No related branches found
No related tags found
No related merge requests found
......@@ -211,20 +211,47 @@ class Updater extends BasicEmitter {
return $success;
}
/**
* 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
......
......@@ -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() {
......
......@@ -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 = '';
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment