Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Update Directory #420

Merged
merged 8 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 32 additions & 57 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public function __construct($baseDir) {
return;
}

$dataDir = $this->getDataDirectoryLocation();
$dataDir = $this->getUpdateDirectoryLocation();
if (empty($dataDir) || !is_string($dataDir)) {
throw new \Exception('Could not read data directory from config.php.');
}
Expand All @@ -201,10 +201,7 @@ public function __construct($baseDir) {
$buildTime = $OC_Build;
}

if ($version === null) {
return;
}
if ($buildTime === null) {
if ($version === null || $buildTime === null) {
return;
}

Expand Down Expand Up @@ -305,8 +302,8 @@ public function getConfigOption($key) {
*
* @return string
*/
private function getDataDirectoryLocation() {
return $this->configValues['datadirectory'];
private function getUpdateDirectoryLocation() {
return $this->configValues['updatedirectory'] ?? $this->configValues['datadirectory'];
}

/**
Expand Down Expand Up @@ -487,7 +484,7 @@ public function createBackup() {
];

// Create new folder for the backup
$backupFolderLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid').'/backups/nextcloud-'.$this->getConfigOption('version') . '-' . time() . '/';
$backupFolderLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid').'/backups/nextcloud-'.$this->getConfigOption('version') . '-' . time() . '/';
$this->silentLog('[info] backup folder location: ' . $backupFolderLocation);

$state = mkdir($backupFolderLocation, 0750, true);
Expand Down Expand Up @@ -638,7 +635,8 @@ public function downloadUpdate() {
$this->silentLog('[info] downloadUpdate()');

$response = $this->getUpdateServerResponse();
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';

$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
if (file_exists($storageLocation)) {
$this->silentLog('[info] storage location exists');
$this->recursiveDelete($storageLocation);
Expand Down Expand Up @@ -706,7 +704,7 @@ public function downloadUpdate() {
* @throws \Exception
*/
private function getDownloadedFilePath() {
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
$this->silentLog('[info] storage location: ' . $storageLocation);

$filesInStorageLocation = scandir($storageLocation);
Expand Down Expand Up @@ -926,7 +924,7 @@ public function deleteOldFiles() {
throw new \Exception('core/shipped.json is not available');
}

$newShippedAppsFile = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
$newShippedAppsFile = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
if (!file_exists($newShippedAppsFile)) {
throw new \Exception('core/shipped.json is not available in the new release');
}
Expand Down Expand Up @@ -1084,7 +1082,7 @@ public function moveNewVersionInPlace() {
'ocs/v1.php',
'ocs/v2.php',
];
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, $excludedElements);

Expand All @@ -1100,14 +1098,15 @@ public function moveNewVersionInPlace() {
public function finalize() {
$this->silentLog('[info] finalize()');

$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, []);
$state = rmdir($storageLocation);
if ($state === false) {
throw new \Exception('Could not rmdir $storagelocation');
}
$state = unlink($this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');

$state = unlink($this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');
if ($state === false) {
throw new \Exception('Could not rmdir .step');
}
Expand All @@ -1126,7 +1125,7 @@ public function finalize() {
* @throws \Exception
*/
private function writeStep($state, $step) {
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if (!file_exists($updaterDir . '/.step')) {
if (!file_exists($updaterDir)) {
$result = mkdir($updaterDir);
Expand Down Expand Up @@ -1171,7 +1170,7 @@ public function endStep($step) {
public function currentStep() {
$this->silentLog('[info] currentStep()');

$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$jsonData = [];
if (file_exists($updaterDir. '/.step')) {
$state = file_get_contents($updaterDir . '/.step');
Expand All @@ -1196,7 +1195,7 @@ public function currentStep() {
public function rollbackChanges($step) {
$this->silentLog('[info] rollbackChanges("' . $step . '")');

$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if (file_exists($updaterDir . '/.step')) {
$this->silentLog('[info] unlink .step');
$state = unlink($updaterDir . '/.step');
Expand Down Expand Up @@ -1240,7 +1239,7 @@ public function logException(\Exception $e) {
* @throws LogException
*/
public function log($message) {
$updaterLogPath = $this->getDataDirectoryLocation() . '/updater.log';
$updaterLogPath = $this->getUpdateDirectoryLocation() . '/updater.log';

$fh = fopen($updaterLogPath, 'a');
if ($fh === false) {
Expand Down Expand Up @@ -1750,77 +1749,53 @@ public function logVersion() {
<button id="retryUpdateButton" class="hidden">Retry update</button>
</div>
</li>
<li id="step-check-files" class="step <?php if ($stepNumber >= 1) {
echo 'passed-step';
}?>">
<li id="step-check-files" class="step <?php if ($stepNumber >= 1) { echo 'passed-step'; }?>">
<h2>Check for expected files</h2>
<div class="output hidden"></div>
</li>
<li id="step-check-permissions" class="step <?php if ($stepNumber >= 2) {
echo 'passed-step';
}?>">
<li id="step-check-permissions" class="step <?php if ($stepNumber >= 2) { echo 'passed-step'; }?>">
<h2>Check for write permissions</h2>
<div class="output hidden"></div>
</li>
<li id="step-backup" class="step <?php if ($stepNumber >= 3) {
echo 'passed-step';
}?>">
<li id="step-backup" class="step <?php if ($stepNumber >= 3) { echo 'passed-step'; }?>">
<h2>Create backup</h2>
<div class="output hidden"></div>
</li>
<li id="step-download" class="step <?php if ($stepNumber >= 4) {
echo 'passed-step';
}?>">
<li id="step-download" class="step <?php if ($stepNumber >= 4) { echo 'passed-step'; }?>">
<h2>Downloading</h2>
<div class="output hidden"></div>
</li>
<li id="step-verify-integrity" class="step <?php if ($stepNumber >= 5) {
echo 'passed-step';
}?>">
<li id="step-verify-integrity" class="step <?php if ($stepNumber >= 5) { echo 'passed-step'; }?>">
<h2>Verifying integrity</h2>
<div class="output hidden"></div>
</li>
<li id="step-extract" class="step <?php if ($stepNumber >= 6) {
echo 'passed-step';
}?>">
<li id="step-extract" class="step <?php if ($stepNumber >= 6) { echo 'passed-step'; }?>">
<h2>Extracting</h2>
<div class="output hidden"></div>
</li>
<li id="step-enable-maintenance" class="step <?php if ($stepNumber >= 7) {
echo 'passed-step';
}?>">
<li id="step-enable-maintenance" class="step <?php if ($stepNumber >= 7) { echo 'passed-step'; }?>">
<h2>Enable maintenance mode</h2>
<div class="output hidden"></div>
</li>
<li id="step-entrypoints" class="step <?php if ($stepNumber >= 8) {
echo 'passed-step';
}?>">
<li id="step-entrypoints" class="step <?php if ($stepNumber >= 8) { echo 'passed-step'; }?>">
<h2>Replace entry points</h2>
<div class="output hidden"></div>
</li>
<li id="step-delete" class="step <?php if ($stepNumber >= 9) {
echo 'passed-step';
}?>">
<li id="step-delete" class="step <?php if ($stepNumber >= 9) { echo 'passed-step'; }?>">
<h2>Delete old files</h2>
<div class="output hidden"></div>
</li>
<li id="step-move" class="step <?php if ($stepNumber >= 10) {
echo 'passed-step';
}?>">
<li id="step-move" class="step <?php if ($stepNumber >= 10) { echo 'passed-step'; }?>">
<h2>Move new files in place</h2>
<div class="output hidden"></div>
</li>
<li id="step-maintenance-mode" class="step <?php if ($stepNumber >= 11) {
echo 'passed-step';
}?>">
<li id="step-maintenance-mode" class="step <?php if ($stepNumber >= 11) { echo 'passed-step'; }?>">
<h2>Continue with web based updater</h2>
<div class="output hidden">
<button id="maintenance-disable">Disable maintenance mode and continue in the web based updater</button>
</div>
</li>
<li id="step-done" class="step <?php if ($stepNumber >= 12) {
echo 'passed-step';
}?>">
<li id="step-done" class="step <?php if ($stepNumber >= 12) { echo 'passed-step'; }?>">
<h2>Done</h2>
<div class="output hidden">
<a class="button" href="<?php echo htmlspecialchars(str_replace('/index.php', '/../', $updaterUrl), ENT_QUOTES); ?>">Go back to your Nextcloud instance to finish the update</a>
Expand All @@ -1833,7 +1808,7 @@ public function logVersion() {
<p>To login you need to provide the unhashed value of "updater.secret" in your config file.</p>
<p>If you don't know that value, you can access this updater directly via the Nextcloud admin screen or generate
your own secret:</p>
<code>php -r '$password = trim(shell_exec("openssl rand -base64 48"));if(strlen($password) === 64) {$hash = password_hash($password, PASSWORD_DEFAULT) . "\n"; echo "Insert as \"updater.secret\": ".$hash; echo "The plaintext value is: ".$password."\n";}else{echo "Could not execute OpenSSL.\n";};'</code>
<code>php -r '$password = trim(shell_exec("openssl rand -base64 48"));if (strlen($password) === 64) {$hash = password_hash($password, PASSWORD_DEFAULT) . "\n"; echo "Insert as \"updater.secret\": ".$hash; echo "The plaintext value is: ".$password."\n";}else{echo "Could not execute OpenSSL.\n";};'</code>
<form method="post" name="login">
<fieldset>
<input type="password" name="updater-secret-input" value=""
Expand All @@ -1852,7 +1827,8 @@ public function logVersion() {
</div>

</body>
<?php if ($auth->isAuthenticated()): ?>

<?php if ($auth->isAuthenticated()) : ?>
<script>
function escapeHTML(s) {
return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('>').join('&gt;').split('"').join('&quot;').split('\'').join('&#039;');
Expand Down Expand Up @@ -2240,4 +2216,3 @@ function confirmExit() {
<?php endif; ?>

</html>

35 changes: 17 additions & 18 deletions lib/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function __construct($baseDir) {
return;
}

$dataDir = $this->getDataDirectoryLocation();
$dataDir = $this->getUpdateDirectoryLocation();
if (empty($dataDir) || !is_string($dataDir)) {
throw new \Exception('Could not read data directory from config.php.');
}
Expand All @@ -84,10 +84,7 @@ public function __construct($baseDir) {
$buildTime = $OC_Build;
}

if ($version === null) {
return;
}
if ($buildTime === null) {
if ($version === null || $buildTime === null) {
return;
}

Expand Down Expand Up @@ -188,8 +185,8 @@ public function getConfigOption($key) {
*
* @return string
*/
private function getDataDirectoryLocation() {
return $this->configValues['datadirectory'];
private function getUpdateDirectoryLocation() {
return $this->configValues['updatedirectory'] ?? $this->configValues['datadirectory'];
}

/**
Expand Down Expand Up @@ -370,7 +367,7 @@ public function createBackup() {
];

// Create new folder for the backup
$backupFolderLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid').'/backups/nextcloud-'.$this->getConfigOption('version') . '-' . time() . '/';
$backupFolderLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid').'/backups/nextcloud-'.$this->getConfigOption('version') . '-' . time() . '/';
$this->silentLog('[info] backup folder location: ' . $backupFolderLocation);

$state = mkdir($backupFolderLocation, 0750, true);
Expand Down Expand Up @@ -521,7 +518,8 @@ public function downloadUpdate() {
$this->silentLog('[info] downloadUpdate()');

$response = $this->getUpdateServerResponse();
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';

$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
if (file_exists($storageLocation)) {
$this->silentLog('[info] storage location exists');
$this->recursiveDelete($storageLocation);
Expand Down Expand Up @@ -589,7 +587,7 @@ public function downloadUpdate() {
* @throws \Exception
*/
private function getDownloadedFilePath() {
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
$this->silentLog('[info] storage location: ' . $storageLocation);

$filesInStorageLocation = scandir($storageLocation);
Expand Down Expand Up @@ -809,7 +807,7 @@ public function deleteOldFiles() {
throw new \Exception('core/shipped.json is not available');
}

$newShippedAppsFile = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
$newShippedAppsFile = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
if (!file_exists($newShippedAppsFile)) {
throw new \Exception('core/shipped.json is not available in the new release');
}
Expand Down Expand Up @@ -967,7 +965,7 @@ public function moveNewVersionInPlace() {
'ocs/v1.php',
'ocs/v2.php',
];
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, $excludedElements);

Expand All @@ -983,14 +981,15 @@ public function moveNewVersionInPlace() {
public function finalize() {
$this->silentLog('[info] finalize()');

$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, []);
$state = rmdir($storageLocation);
if ($state === false) {
throw new \Exception('Could not rmdir $storagelocation');
}
$state = unlink($this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');

$state = unlink($this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');
if ($state === false) {
throw new \Exception('Could not rmdir .step');
}
Expand All @@ -1009,7 +1008,7 @@ public function finalize() {
* @throws \Exception
*/
private function writeStep($state, $step) {
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if (!file_exists($updaterDir . '/.step')) {
if (!file_exists($updaterDir)) {
$result = mkdir($updaterDir);
Expand Down Expand Up @@ -1054,7 +1053,7 @@ public function endStep($step) {
public function currentStep() {
$this->silentLog('[info] currentStep()');

$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$jsonData = [];
if (file_exists($updaterDir. '/.step')) {
$state = file_get_contents($updaterDir . '/.step');
Expand All @@ -1079,7 +1078,7 @@ public function currentStep() {
public function rollbackChanges($step) {
$this->silentLog('[info] rollbackChanges("' . $step . '")');

$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if (file_exists($updaterDir . '/.step')) {
$this->silentLog('[info] unlink .step');
$state = unlink($updaterDir . '/.step');
Expand Down Expand Up @@ -1123,7 +1122,7 @@ public function logException(\Exception $e) {
* @throws LogException
*/
public function log($message) {
$updaterLogPath = $this->getDataDirectoryLocation() . '/updater.log';
$updaterLogPath = $this->getUpdateDirectoryLocation() . '/updater.log';

$fh = fopen($updaterLogPath, 'a');
if ($fh === false) {
Expand Down