composer run cs:fix

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
Côme Chilliet 2022-07-25 12:12:34 +02:00
parent 9b1d9d9544
commit 5bda9e4c4e
No known key found for this signature in database
GPG Key ID: A3E2F658B28C760A
7 changed files with 432 additions and 443 deletions

247
index.php
View File

@ -60,7 +60,7 @@ class Auth {
* @param string $password
*/
public function __construct(Updater $updater,
$password) {
$password) {
$this->updater = $updater;
$this->password = $password;
}
@ -131,7 +131,7 @@ class Auth {
$storedHash = $this->updater->getConfigOption('updater.secret');
// As a sanity check the stored hash or the sent password can never be empty
if($storedHash === '' || $storedHash === null || $this->password === null) {
if ($storedHash === '' || $storedHash === null || $this->password === null) {
return false;
}
@ -164,7 +164,7 @@ class Updater {
public function __construct($baseDir) {
$this->baseDir = $baseDir;
if($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
if ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
$configFileName = rtrim($dir, '/') . '/config.php';
} else {
$configFileName = $this->baseDir . '/../config/config.php';
@ -184,7 +184,7 @@ class Updater {
}
$dataDir = $this->getDataDirectoryLocation();
if(empty($dataDir) || !is_string($dataDir)) {
if (empty($dataDir) || !is_string($dataDir)) {
throw new \Exception('Could not read data directory from config.php.');
}
@ -201,16 +201,16 @@ class Updater {
$buildTime = $OC_Build;
}
if($version === null) {
if ($version === null) {
return;
}
if($buildTime === null) {
if ($buildTime === null) {
return;
}
// normalize version to 3 digits
$splittedVersion = explode('.', $version);
if(sizeof($splittedVersion) >= 3) {
if (sizeof($splittedVersion) >= 3) {
$splittedVersion = array_slice($splittedVersion, 0, 3);
}
@ -367,11 +367,11 @@ class Updater {
*/
private function getAppDirectories() {
$expected = [];
if($appsPaths = $this->getConfigOption('apps_paths')) {
if ($appsPaths = $this->getConfigOption('apps_paths')) {
foreach ($appsPaths as $appsPath) {
$parentDir = realpath($this->baseDir . '/../');
$appDir = basename($appsPath['path']);
if(strpos($appsPath['path'], $parentDir) === 0 && $appDir !== 'apps') {
if (strpos($appsPath['path'], $parentDir) === 0 && $appDir !== 'apps') {
$expected[] = $appDir;
}
}
@ -404,7 +404,7 @@ class Updater {
$expectedElements = $this->getExpectedElementsList();
$unexpectedElements = [];
foreach (new \DirectoryIterator($this->baseDir . '/../') as $fileInfo) {
if(array_search($fileInfo->getFilename(), $expectedElements) === false) {
if (array_search($fileInfo->getFilename(), $expectedElements) === false) {
$unexpectedElements[] = $fileInfo->getFilename();
}
}
@ -427,11 +427,11 @@ class Updater {
$it = new \RecursiveIteratorIterator($filter);
foreach ($it as $path => $dir) {
if(!is_writable($path)) {
if (!is_writable($path)) {
$notWritablePaths[] = $path;
}
}
if(count($notWritablePaths) > 0) {
if (count($notWritablePaths) > 0) {
throw new UpdateException($notWritablePaths);
}
@ -447,7 +447,7 @@ class Updater {
public function setMaintenanceMode($state) {
$this->silentLog('[info] setMaintenanceMode("' . ($state ? 'true' : 'false') . '")');
if($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
if ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
$configFileName = rtrim($dir, '/') . '/config.php';
} else {
$configFileName = $this->baseDir . '/../config/config.php';
@ -491,7 +491,7 @@ class Updater {
$this->silentLog('[info] backup folder location: ' . $backupFolderLocation);
$state = mkdir($backupFolderLocation, 0750, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not create backup folder location');
}
@ -507,35 +507,35 @@ class Updater {
$folderStructure = explode('/', $fileName, -1);
// Exclude the exclusions
if(isset($folderStructure[0])) {
if(array_search($folderStructure[0], $excludedElements) !== false) {
if (isset($folderStructure[0])) {
if (array_search($folderStructure[0], $excludedElements) !== false) {
continue;
}
} else {
if(array_search($fileName, $excludedElements) !== false) {
if (array_search($fileName, $excludedElements) !== false) {
continue;
}
}
// Create folder if it doesn't exist
if(!file_exists($backupFolderLocation . '/' . dirname($fileName))) {
if (!file_exists($backupFolderLocation . '/' . dirname($fileName))) {
$state = mkdir($backupFolderLocation . '/' . dirname($fileName), 0750, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not create folder: '.$backupFolderLocation.'/'.dirname($fileName));
}
}
// If it is a file copy it
if($fileInfo->isFile()) {
if ($fileInfo->isFile()) {
$state = copy($fileInfo->getRealPath(), $backupFolderLocation . $fileName);
if($state === false) {
if ($state === false) {
$message = sprintf(
'Could not copy "%s" to "%s"',
$fileInfo->getRealPath(),
$backupFolderLocation . $fileName
);
if(is_readable($fileInfo->getRealPath()) === false) {
if (is_readable($fileInfo->getRealPath()) === false) {
$message = sprintf(
'%s. Source %s is not readable',
$message,
@ -543,7 +543,7 @@ class Updater {
);
}
if(is_writable($backupFolderLocation . $fileName) === false) {
if (is_writable($backupFolderLocation . $fileName) === false) {
$message = sprintf(
'%s. Destination %s is not writable',
$message,
@ -573,7 +573,7 @@ class Updater {
$this->silentLog('[info] getUpdateServerResponse()');
$updaterServer = $this->getConfigOption('updater.server.url');
if($updaterServer === null) {
if ($updaterServer === null) {
// FIXME: used deployed URL
$updaterServer = 'https://updates.nextcloud.com/updater_server/';
}
@ -603,26 +603,26 @@ class Updater {
}
$response = curl_exec($curl);
if($response === false) {
if ($response === false) {
throw new \Exception('Could not do request to updater server: '.curl_error($curl));
}
curl_close($curl);
// Response can be empty when no update is available
if($response === '') {
if ($response === '') {
return [];
}
$xml = simplexml_load_string($response);
if($xml === false) {
if ($xml === false) {
throw new \Exception('Could not parse updater server XML response');
}
$json = json_encode($xml);
if($json === false) {
if ($json === false) {
throw new \Exception('Could not JSON encode updater server response');
}
$response = json_decode($json, true);
if($response === null) {
if ($response === null) {
throw new \Exception('Could not JSON decode updater server response.');
}
$this->silentLog('[info] getUpdateServerResponse response: ' . print_r($response, true));
@ -639,12 +639,12 @@ class Updater {
$response = $this->getUpdateServerResponse();
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
if(file_exists($storageLocation)) {
if (file_exists($storageLocation)) {
$this->silentLog('[info] storage location exists');
$this->recursiveDelete($storageLocation);
}
$state = mkdir($storageLocation, 0750, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not mkdir storage location');
}
@ -663,11 +663,11 @@ class Updater {
]);
}
if(curl_exec($ch) === false) {
if (curl_exec($ch) === false) {
throw new \Exception('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode !== 200) {
if ($httpCode !== 200) {
$statusCodes = [
400 => 'Bad request',
401 => 'Unauthorized',
@ -680,14 +680,14 @@ class Updater {
];
$message = 'Download failed';
if(isset($statusCodes[$httpCode])) {
if (isset($statusCodes[$httpCode])) {
$message .= ' - ' . $statusCodes[$httpCode] . ' (HTTP ' . $httpCode . ')';
} else {
$message .= ' - HTTP status code: ' . $httpCode;
}
$curlErrorMessage = curl_error($ch);
if(!empty($curlErrorMessage)) {
if (!empty($curlErrorMessage)) {
$message .= ' - curl error message: ' . $curlErrorMessage;
}
@ -710,11 +710,11 @@ class Updater {
$this->silentLog('[info] storage location: ' . $storageLocation);
$filesInStorageLocation = scandir($storageLocation);
$files = array_values(array_filter($filesInStorageLocation, function($path){
$files = array_values(array_filter($filesInStorageLocation, function ($path) {
return $path !== '.' && $path !== '..';
}));
// only the downloaded archive
if(count($files) !== 1) {
if (count($files) !== 1) {
throw new \Exception('There are more files than the downloaded archive in the downloads/ folder.');
}
return $storageLocation . '/' . $files[0];
@ -728,13 +728,13 @@ class Updater {
public function verifyIntegrity() {
$this->silentLog('[info] verifyIntegrity()');
if($this->getCurrentReleaseChannel() === 'daily') {
if ($this->getCurrentReleaseChannel() === 'daily') {
$this->silentLog('[info] current channel is "daily" which is not signed. Skipping verification.');
return;
}
$response = $this->getUpdateServerResponse();
if(!isset($response['signature'])) {
if (!isset($response['signature'])) {
throw new \Exception('No signature specified for defined update');
}
@ -775,7 +775,7 @@ EOF;
OPENSSL_ALGO_SHA512
);
if($validSignature === false) {
if ($validSignature === false) {
throw new \Exception('Signature of update is not valid');
}
@ -792,7 +792,7 @@ EOF;
private function getVersionByVersionFile($versionFile) {
require $versionFile;
if(isset($OC_Version)) {
if (isset($OC_Version)) {
/** @var array $OC_Version */
return implode('.', $OC_Version);
}
@ -813,12 +813,12 @@ EOF;
$zipState = $zip->open($downloadedFilePath);
if ($zipState === true) {
$extraction = $zip->extractTo(dirname($downloadedFilePath));
if($extraction === false) {
if ($extraction === false) {
throw new \Exception('Error during unpacking zipfile: '.($zip->getStatusString()));
}
$zip->close();
$state = unlink($downloadedFilePath);
if($state === false) {
if ($state === false) {
throw new \Exception("Can't unlink ". $downloadedFilePath);
}
} else {
@ -828,7 +828,7 @@ EOF;
// Ensure that the downloaded version is not lower
$downloadedVersion = $this->getVersionByVersionFile(dirname($downloadedFilePath) . '/nextcloud/version.php');
$currentVersion = $this->getVersionByVersionFile($this->baseDir . '/../version.php');
if(version_compare($downloadedVersion, $currentVersion, '<')) {
if (version_compare($downloadedVersion, $currentVersion, '<')) {
throw new \Exception('Downloaded version is lower than installed version');
}
@ -853,17 +853,17 @@ EOF;
];
$content = "<?php\nhttp_response_code(503);\ndie('Update in process.');";
foreach($filesToReplace as $file) {
foreach ($filesToReplace as $file) {
$this->silentLog('[info] replace ' . $file);
$parentDir = dirname($this->baseDir . '/../' . $file);
if(!file_exists($parentDir)) {
if (!file_exists($parentDir)) {
$r = mkdir($parentDir);
if($r !== true) {
if ($r !== true) {
throw new \Exception('Can\'t create parent directory for entry point: ' . $file);
}
}
$state = file_put_contents($this->baseDir . '/../' . $file, $content);
if($state === false) {
if ($state === false) {
throw new \Exception('Can\'t replace entry point: '.$file);
}
}
@ -878,7 +878,7 @@ EOF;
* @throws \Exception
*/
private function recursiveDelete($folder) {
if(!file_exists($folder)) {
if (!file_exists($folder)) {
return;
}
$iterator = new \RecursiveIteratorIterator(
@ -908,7 +908,7 @@ EOF;
}
$state = rmdir($folder);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir ' . $folder);
}
}
@ -922,12 +922,12 @@ EOF;
$this->silentLog('[info] deleteOldFiles()');
$shippedAppsFile = $this->baseDir . '/../core/shipped.json';
if(!file_exists($shippedAppsFile)) {
if (!file_exists($shippedAppsFile)) {
throw new \Exception('core/shipped.json is not available');
}
$newShippedAppsFile = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
if(!file_exists($newShippedAppsFile)) {
if (!file_exists($newShippedAppsFile)) {
throw new \Exception('core/shipped.json is not available in the new release');
}
@ -936,12 +936,12 @@ EOF;
json_decode(file_get_contents($shippedAppsFile), true)['shippedApps'],
json_decode(file_get_contents($newShippedAppsFile), true)['shippedApps']
);
foreach($shippedApps as $app) {
foreach ($shippedApps as $app) {
$this->recursiveDelete($this->baseDir . '/../apps/' . $app);
}
$configSampleFile = $this->baseDir . '/../config/config.sample.php';
if(file_exists($configSampleFile)) {
if (file_exists($configSampleFile)) {
$this->silentLog('[info] config sample exists');
// Delete example config
@ -952,7 +952,7 @@ EOF;
}
$themesReadme = $this->baseDir . '/../themes/README';
if(file_exists($themesReadme)) {
if (file_exists($themesReadme)) {
$this->silentLog('[info] themes README exists');
// Delete themes
@ -988,23 +988,23 @@ EOF;
$fileName = explode($currentDir, $path)[1];
$folderStructure = explode('/', $fileName, -1);
// Exclude the exclusions
if(isset($folderStructure[0])) {
if(array_search($folderStructure[0], $excludedElements) !== false) {
if (isset($folderStructure[0])) {
if (array_search($folderStructure[0], $excludedElements) !== false) {
continue;
}
} else {
if(array_search($fileName, $excludedElements) !== false) {
if (array_search($fileName, $excludedElements) !== false) {
continue;
}
}
if($fileInfo->isFile() || $fileInfo->isLink()) {
if ($fileInfo->isFile() || $fileInfo->isLink()) {
$state = unlink($path);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not unlink: '.$path);
}
} elseif($fileInfo->isDir()) {
} elseif ($fileInfo->isDir()) {
$state = rmdir($path);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir: '.$path);
}
}
@ -1039,15 +1039,15 @@ EOF;
}
}
if($fileInfo->isFile()) {
if(!file_exists($this->baseDir . '/../' . dirname($fileName))) {
if ($fileInfo->isFile()) {
if (!file_exists($this->baseDir . '/../' . dirname($fileName))) {
$state = mkdir($this->baseDir . '/../' . dirname($fileName), 0755, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not mkdir ' . $this->baseDir . '/../' . dirname($fileName));
}
}
$state = rename($path, $this->baseDir . '/../' . $fileName);
if($state === false) {
if ($state === false) {
throw new \Exception(
sprintf(
'Could not rename %s to %s',
@ -1057,9 +1057,9 @@ EOF;
);
}
}
if($fileInfo->isDir()) {
if ($fileInfo->isDir()) {
$state = rmdir($path);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir ' . $path);
}
}
@ -1104,11 +1104,11 @@ EOF;
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, []);
$state = rmdir($storageLocation);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir $storagelocation');
}
$state = unlink($this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir .step');
}
@ -1127,21 +1127,21 @@ EOF;
*/
private function writeStep($state, $step) {
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if(!file_exists($updaterDir . '/.step')) {
if(!file_exists($updaterDir)) {
if (!file_exists($updaterDir . '/.step')) {
if (!file_exists($updaterDir)) {
$result = mkdir($updaterDir);
if ($result === false) {
throw new \Exception('Could not create $updaterDir');
}
}
$result = touch($updaterDir . '/.step');
if($result === false) {
if ($result === false) {
throw new \Exception('Could not create .step');
}
}
$result = file_put_contents($updaterDir . '/.step', json_encode(['state' => $state, 'step' => $step]));
if($result === false) {
if ($result === false) {
throw new \Exception('Could not write to .step');
}
}
@ -1173,7 +1173,7 @@ EOF;
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$jsonData = [];
if(file_exists($updaterDir. '/.step')) {
if (file_exists($updaterDir. '/.step')) {
$state = file_get_contents($updaterDir . '/.step');
if ($state === false) {
throw new \Exception('Could not read from .step');
@ -1197,7 +1197,7 @@ EOF;
$this->silentLog('[info] rollbackChanges("' . $step . '")');
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if(file_exists($updaterDir . '/.step')) {
if (file_exists($updaterDir . '/.step')) {
$this->silentLog('[info] unlink .step');
$state = unlink($updaterDir . '/.step');
if ($state === false) {
@ -1205,7 +1205,7 @@ EOF;
}
}
if($step >= 7) {
if ($step >= 7) {
$this->silentLog('[info] rollbackChanges - step >= 7');
// TODO: If it fails after step 7: Rollback
}
@ -1227,7 +1227,7 @@ EOF;
$message .= 'Trace:' . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
$message .= 'File:' . $e->getFile() . PHP_EOL;
$message .= 'Line:' . $e->getLine() . PHP_EOL;
if($e instanceof UpdateException) {
if ($e instanceof UpdateException) {
$message .= 'Data:' . PHP_EOL . print_r($e->getData(), true) . PHP_EOL;
}
$this->log($message);
@ -1243,11 +1243,11 @@ EOF;
$updaterLogPath = $this->getDataDirectoryLocation() . '/updater.log';
$fh = fopen($updaterLogPath, 'a');
if($fh === false) {
if ($fh === false) {
throw new LogException('Could not open updater.log');
}
if($this->requestID === null) {
if ($this->requestID === null) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
@ -1260,7 +1260,7 @@ EOF;
$logLine = date(\DateTime::ISO8601) . ' ' . $this->requestID . ' ' . $message . PHP_EOL;
$result = fwrite($fh, $logLine);
if($result === false) {
if ($result === false) {
throw new LogException('Could not write to updater.log');
}
@ -1311,7 +1311,7 @@ try {
try {
$updater->log('[info] request to updater');
} catch (\Exception $e) {
if(isset($_POST['step'])) {
if (isset($_POST['step'])) {
// mark step as failed
http_response_code(500);
echo(json_encode(['proceed' => false, 'response' => $e->getMessage()]));
@ -1328,31 +1328,31 @@ $auth = new Auth($updater, $password);
// Check if already a step is in process
$currentStep = $updater->currentStep();
$stepNumber = 0;
if($currentStep !== []) {
if ($currentStep !== []) {
$stepState = $currentStep['state'];
$stepNumber = $currentStep['step'];
$updater->log('[info] Step ' . $stepNumber . ' is in state "' . $stepState . '".');
if($stepState === 'start') {
if ($stepState === 'start') {
die(
sprintf(
'Step %s is currently in process. Please reload this page later.',
$stepNumber
sprintf(
'Step %s is currently in process. Please reload this page later.',
$stepNumber
)
);
}
}
if(isset($_POST['step'])) {
if (isset($_POST['step'])) {
$updater->log('[info] POST request for step "' . $_POST['step'] . '"');
set_time_limit(0);
try {
if(!$auth->isAuthenticated()) {
if (!$auth->isAuthenticated()) {
throw new \Exception('Not authenticated');
}
$step = (int)$_POST['step'];
if($step > 12 || $step < 1) {
if ($step > 12 || $step < 1) {
throw new \Exception('Invalid step');
}
@ -1407,7 +1407,7 @@ if(isset($_POST['step'])) {
$message .= ' (and writing to log failed also with: ' . $logE->getMessage() . ')';
}
if(isset($step)) {
if (isset($step)) {
$updater->rollbackChanges($step);
}
http_response_code(500);
@ -1422,7 +1422,7 @@ if(isset($_POST['step'])) {
$message .= ' (and writing to log failed also with: ' . $logE->getMessage() . ')';
}
if(isset($step)) {
if (isset($step)) {
$updater->rollbackChanges($step);
}
http_response_code(500);
@ -1435,7 +1435,7 @@ if(isset($_POST['step'])) {
$updater->log('[info] show HTML page');
$updater->logVersion();
$updaterUrl = explode('?', $_SERVER['REQUEST_URI'], 2)[0];
if(strpos($updaterUrl, 'index.php') === false) {
if (strpos($updaterUrl, 'index.php') === false) {
$updaterUrl = rtrim($updaterUrl, '/') . '/index.php';
}
?>
@ -1730,7 +1730,7 @@ if(strpos($updaterUrl, 'index.php') === false) {
<div id="content">
<div id="app-content">
<?php if($auth->isAuthenticated()): ?>
<?php if ($auth->isAuthenticated()): ?>
<ul id="progress" class="section">
<li id="step-init" class="step icon-loading passed-step">
<h2>Initializing</h2>
@ -1740,64 +1740,87 @@ if(strpos($updaterUrl, 'index.php') === false) {
<?php
if ($updater->updateAvailable() || $stepNumber > 0) {
$buttonText = 'Start update';
if($stepNumber > 0) {
if ($stepNumber > 0) {
$buttonText = 'Continue update';
}
?>
} ?>
<button id="startUpdateButton"><?php echo $buttonText ?></button>
<?php
}
?>
?>
<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>
@ -1819,7 +1842,7 @@ if(strpos($updaterUrl, 'index.php') === false) {
<button id="updater-secret-submit">Login</button>
</fieldset>
</form>
<?php if(isset($_POST['updater-secret-input']) && !$auth->isAuthenticated()): ?>
<?php if (isset($_POST['updater-secret-input']) && !$auth->isAuthenticated()): ?>
<p>Invalid password</p>
<?php endif; ?>
</div>
@ -1829,7 +1852,7 @@ if(strpos($updaterUrl, 'index.php') === false) {
</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;');

View File

@ -39,8 +39,7 @@ class CommandApplication extends Application {
*
* @return string The command name
*/
protected function getCommandName(InputInterface $input)
{
protected function getCommandName(InputInterface $input) {
// This should return the name of your command.
return 'update';
}
@ -50,8 +49,7 @@ class CommandApplication extends Application {
*
* @return array An array of default Command instances
*/
protected function getDefaultCommands()
{
protected function getDefaultCommands() {
// Keep the core default commands to have the HelpCommand
// which is used when using the --help option
$defaultCommands = parent::getDefaultCommands();
@ -65,12 +63,11 @@ class CommandApplication extends Application {
* Overridden so that the application doesn't expect the command
* name to be the first argument.
*/
public function getDefinition()
{
public function getDefinition() {
$inputDefinition = parent::getDefinition();
// clear out the normal first argument, which is the command name
$inputDefinition->setArguments();
return $inputDefinition;
}
}
}

View File

@ -23,7 +23,6 @@
namespace NC\Updater;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -96,7 +95,7 @@ class UpdateCommand extends Command {
return -1;
}
if($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
if ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
$configFileName = rtrim($dir, '/') . '/config.php';
} else {
$configFileName = $path . '/../config/config.php';
@ -123,12 +122,12 @@ class UpdateCommand extends Command {
// Check if already a step is in process
$currentStep = $this->updater->currentStep();
$stepNumber = 0;
if($currentStep !== []) {
if ($currentStep !== []) {
$stepState = $currentStep['state'];
$stepNumber = $currentStep['step'];
$this->updater->log('[info] Step ' . $stepNumber . ' is in state "' . $stepState . '".');
if($stepState === 'start') {
if ($stepState === 'start') {
$output->writeln(
sprintf(
'Step %s is currently in process. Please call this command later.',
@ -157,7 +156,7 @@ class UpdateCommand extends Command {
$output->writeln('');
if(!$this->updater->updateAvailable() && $stepNumber === 0) {
if (!$this->updater->updateAvailable() && $stepNumber === 0) {
$output->writeln('Nothing to do.');
return 0;
}
@ -168,7 +167,6 @@ class UpdateCommand extends Command {
}
if ($input->isInteractive()) {
$this->showCurrentStatus($output, $stepNumber);
$output->writeln('');
@ -191,7 +189,7 @@ class UpdateCommand extends Command {
$output->writeln('');
if(function_exists('pcntl_signal')) {
if (function_exists('pcntl_signal')) {
// being able to handle stop/terminate command (Ctrl - C)
pcntl_signal(SIGTERM, [$this, 'stopCommand']);
pcntl_signal(SIGINT, [$this, 'stopCommand']);
@ -204,7 +202,7 @@ class UpdateCommand extends Command {
}
// print already executed steps
for($i = 1; $i <= $stepNumber; $i++) {
for ($i = 1; $i <= $stepNumber; $i++) {
if ($i === 11) {
// no need to ask for maintenance mode on CLI - skip it
continue;
@ -223,7 +221,7 @@ class UpdateCommand extends Command {
if (function_exists('pcntl_signal_dispatch')) {
pcntl_signal_dispatch();
if ( $this->shouldStop ) {
if ($this->shouldStop) {
break;
}
}
@ -244,7 +242,7 @@ class UpdateCommand extends Command {
$output->writeln('<error>[✘] ' . $this->checkTexts[$i] . ' failed</error>');
if ($i === 1) {
if(is_string($result['response'])) {
if (is_string($result['response'])) {
$output->writeln('<error>' . $result['response'] . '</error>');
} else {
$output->writeln('<error>The following extra files have been found:</error>');
@ -253,7 +251,7 @@ class UpdateCommand extends Command {
}
}
} elseif ($i === 2) {
if(is_string($result['response'])) {
if (is_string($result['response'])) {
$output->writeln('<error>' . $result['response'] . '</error>');
} else {
$output->writeln('<error>The following places can not be written to:</error>');
@ -278,7 +276,6 @@ class UpdateCommand extends Command {
$output->writeln('Update of code successful.');
if ($input->isInteractive()) {
$output->writeln('');
$helper = $this->getHelper('question');
@ -301,7 +298,6 @@ class UpdateCommand extends Command {
$output->writeln('');
if ($input->isInteractive()) {
$helper = $this->getHelper('question');
$question = new ConfirmationQuestion($this->checkTexts[11] . ' [y/N] ', false);
@ -336,16 +332,16 @@ class UpdateCommand extends Command {
}
return -1;
}
}
}
/**
* @param $step integer
* @return array with options 'proceed' which is a boolean and defines if the step succeeded and an optional 'response' string
*/
protected function executeStep($step) {
protected function executeStep($step) {
$this->updater->log('[info] executeStep request for step "' . $step . '"');
try {
if($step > 12 || $step < 1) {
if ($step > 12 || $step < 1) {
throw new \Exception('Invalid step');
}
@ -447,6 +443,4 @@ class UpdateCommand extends Command {
public function stopCommand() {
$this->shouldStop = true;
}
}

View File

@ -47,7 +47,7 @@ class Updater {
public function __construct($baseDir) {
$this->baseDir = $baseDir;
if($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
if ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
$configFileName = rtrim($dir, '/') . '/config.php';
} else {
$configFileName = $this->baseDir . '/../config/config.php';
@ -67,7 +67,7 @@ class Updater {
}
$dataDir = $this->getDataDirectoryLocation();
if(empty($dataDir) || !is_string($dataDir)) {
if (empty($dataDir) || !is_string($dataDir)) {
throw new \Exception('Could not read data directory from config.php.');
}
@ -84,16 +84,16 @@ class Updater {
$buildTime = $OC_Build;
}
if($version === null) {
if ($version === null) {
return;
}
if($buildTime === null) {
if ($buildTime === null) {
return;
}
// normalize version to 3 digits
$splittedVersion = explode('.', $version);
if(sizeof($splittedVersion) >= 3) {
if (sizeof($splittedVersion) >= 3) {
$splittedVersion = array_slice($splittedVersion, 0, 3);
}
@ -250,11 +250,11 @@ class Updater {
*/
private function getAppDirectories() {
$expected = [];
if($appsPaths = $this->getConfigOption('apps_paths')) {
if ($appsPaths = $this->getConfigOption('apps_paths')) {
foreach ($appsPaths as $appsPath) {
$parentDir = realpath($this->baseDir . '/../');
$appDir = basename($appsPath['path']);
if(strpos($appsPath['path'], $parentDir) === 0 && $appDir !== 'apps') {
if (strpos($appsPath['path'], $parentDir) === 0 && $appDir !== 'apps') {
$expected[] = $appDir;
}
}
@ -287,7 +287,7 @@ class Updater {
$expectedElements = $this->getExpectedElementsList();
$unexpectedElements = [];
foreach (new \DirectoryIterator($this->baseDir . '/../') as $fileInfo) {
if(array_search($fileInfo->getFilename(), $expectedElements) === false) {
if (array_search($fileInfo->getFilename(), $expectedElements) === false) {
$unexpectedElements[] = $fileInfo->getFilename();
}
}
@ -310,11 +310,11 @@ class Updater {
$it = new \RecursiveIteratorIterator($filter);
foreach ($it as $path => $dir) {
if(!is_writable($path)) {
if (!is_writable($path)) {
$notWritablePaths[] = $path;
}
}
if(count($notWritablePaths) > 0) {
if (count($notWritablePaths) > 0) {
throw new UpdateException($notWritablePaths);
}
@ -330,7 +330,7 @@ class Updater {
public function setMaintenanceMode($state) {
$this->silentLog('[info] setMaintenanceMode("' . ($state ? 'true' : 'false') . '")');
if($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
if ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
$configFileName = rtrim($dir, '/') . '/config.php';
} else {
$configFileName = $this->baseDir . '/../config/config.php';
@ -374,7 +374,7 @@ class Updater {
$this->silentLog('[info] backup folder location: ' . $backupFolderLocation);
$state = mkdir($backupFolderLocation, 0750, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not create backup folder location');
}
@ -390,35 +390,35 @@ class Updater {
$folderStructure = explode('/', $fileName, -1);
// Exclude the exclusions
if(isset($folderStructure[0])) {
if(array_search($folderStructure[0], $excludedElements) !== false) {
if (isset($folderStructure[0])) {
if (array_search($folderStructure[0], $excludedElements) !== false) {
continue;
}
} else {
if(array_search($fileName, $excludedElements) !== false) {
if (array_search($fileName, $excludedElements) !== false) {
continue;
}
}
// Create folder if it doesn't exist
if(!file_exists($backupFolderLocation . '/' . dirname($fileName))) {
if (!file_exists($backupFolderLocation . '/' . dirname($fileName))) {
$state = mkdir($backupFolderLocation . '/' . dirname($fileName), 0750, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not create folder: '.$backupFolderLocation.'/'.dirname($fileName));
}
}
// If it is a file copy it
if($fileInfo->isFile()) {
if ($fileInfo->isFile()) {
$state = copy($fileInfo->getRealPath(), $backupFolderLocation . $fileName);
if($state === false) {
if ($state === false) {
$message = sprintf(
'Could not copy "%s" to "%s"',
$fileInfo->getRealPath(),
$backupFolderLocation . $fileName
);
if(is_readable($fileInfo->getRealPath()) === false) {
if (is_readable($fileInfo->getRealPath()) === false) {
$message = sprintf(
'%s. Source %s is not readable',
$message,
@ -426,7 +426,7 @@ class Updater {
);
}
if(is_writable($backupFolderLocation . $fileName) === false) {
if (is_writable($backupFolderLocation . $fileName) === false) {
$message = sprintf(
'%s. Destination %s is not writable',
$message,
@ -456,7 +456,7 @@ class Updater {
$this->silentLog('[info] getUpdateServerResponse()');
$updaterServer = $this->getConfigOption('updater.server.url');
if($updaterServer === null) {
if ($updaterServer === null) {
// FIXME: used deployed URL
$updaterServer = 'https://updates.nextcloud.com/updater_server/';
}
@ -486,26 +486,26 @@ class Updater {
}
$response = curl_exec($curl);
if($response === false) {
if ($response === false) {
throw new \Exception('Could not do request to updater server: '.curl_error($curl));
}
curl_close($curl);
// Response can be empty when no update is available
if($response === '') {
if ($response === '') {
return [];
}
$xml = simplexml_load_string($response);
if($xml === false) {
if ($xml === false) {
throw new \Exception('Could not parse updater server XML response');
}
$json = json_encode($xml);
if($json === false) {
if ($json === false) {
throw new \Exception('Could not JSON encode updater server response');
}
$response = json_decode($json, true);
if($response === null) {
if ($response === null) {
throw new \Exception('Could not JSON decode updater server response.');
}
$this->silentLog('[info] getUpdateServerResponse response: ' . print_r($response, true));
@ -522,12 +522,12 @@ class Updater {
$response = $this->getUpdateServerResponse();
$storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
if(file_exists($storageLocation)) {
if (file_exists($storageLocation)) {
$this->silentLog('[info] storage location exists');
$this->recursiveDelete($storageLocation);
}
$state = mkdir($storageLocation, 0750, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not mkdir storage location');
}
@ -546,11 +546,11 @@ class Updater {
]);
}
if(curl_exec($ch) === false) {
if (curl_exec($ch) === false) {
throw new \Exception('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode !== 200) {
if ($httpCode !== 200) {
$statusCodes = [
400 => 'Bad request',
401 => 'Unauthorized',
@ -563,14 +563,14 @@ class Updater {
];
$message = 'Download failed';
if(isset($statusCodes[$httpCode])) {
if (isset($statusCodes[$httpCode])) {
$message .= ' - ' . $statusCodes[$httpCode] . ' (HTTP ' . $httpCode . ')';
} else {
$message .= ' - HTTP status code: ' . $httpCode;
}
$curlErrorMessage = curl_error($ch);
if(!empty($curlErrorMessage)) {
if (!empty($curlErrorMessage)) {
$message .= ' - curl error message: ' . $curlErrorMessage;
}
@ -593,11 +593,11 @@ class Updater {
$this->silentLog('[info] storage location: ' . $storageLocation);
$filesInStorageLocation = scandir($storageLocation);
$files = array_values(array_filter($filesInStorageLocation, function($path){
$files = array_values(array_filter($filesInStorageLocation, function ($path) {
return $path !== '.' && $path !== '..';
}));
// only the downloaded archive
if(count($files) !== 1) {
if (count($files) !== 1) {
throw new \Exception('There are more files than the downloaded archive in the downloads/ folder.');
}
return $storageLocation . '/' . $files[0];
@ -611,13 +611,13 @@ class Updater {
public function verifyIntegrity() {
$this->silentLog('[info] verifyIntegrity()');
if($this->getCurrentReleaseChannel() === 'daily') {
if ($this->getCurrentReleaseChannel() === 'daily') {
$this->silentLog('[info] current channel is "daily" which is not signed. Skipping verification.');
return;
}
$response = $this->getUpdateServerResponse();
if(!isset($response['signature'])) {
if (!isset($response['signature'])) {
throw new \Exception('No signature specified for defined update');
}
@ -658,7 +658,7 @@ EOF;
OPENSSL_ALGO_SHA512
);
if($validSignature === false) {
if ($validSignature === false) {
throw new \Exception('Signature of update is not valid');
}
@ -675,7 +675,7 @@ EOF;
private function getVersionByVersionFile($versionFile) {
require $versionFile;
if(isset($OC_Version)) {
if (isset($OC_Version)) {
/** @var array $OC_Version */
return implode('.', $OC_Version);
}
@ -696,12 +696,12 @@ EOF;
$zipState = $zip->open($downloadedFilePath);
if ($zipState === true) {
$extraction = $zip->extractTo(dirname($downloadedFilePath));
if($extraction === false) {
if ($extraction === false) {
throw new \Exception('Error during unpacking zipfile: '.($zip->getStatusString()));
}
$zip->close();
$state = unlink($downloadedFilePath);
if($state === false) {
if ($state === false) {
throw new \Exception("Can't unlink ". $downloadedFilePath);
}
} else {
@ -711,7 +711,7 @@ EOF;
// Ensure that the downloaded version is not lower
$downloadedVersion = $this->getVersionByVersionFile(dirname($downloadedFilePath) . '/nextcloud/version.php');
$currentVersion = $this->getVersionByVersionFile($this->baseDir . '/../version.php');
if(version_compare($downloadedVersion, $currentVersion, '<')) {
if (version_compare($downloadedVersion, $currentVersion, '<')) {
throw new \Exception('Downloaded version is lower than installed version');
}
@ -736,17 +736,17 @@ EOF;
];
$content = "<?php\nhttp_response_code(503);\ndie('Update in process.');";
foreach($filesToReplace as $file) {
foreach ($filesToReplace as $file) {
$this->silentLog('[info] replace ' . $file);
$parentDir = dirname($this->baseDir . '/../' . $file);
if(!file_exists($parentDir)) {
if (!file_exists($parentDir)) {
$r = mkdir($parentDir);
if($r !== true) {
if ($r !== true) {
throw new \Exception('Can\'t create parent directory for entry point: ' . $file);
}
}
$state = file_put_contents($this->baseDir . '/../' . $file, $content);
if($state === false) {
if ($state === false) {
throw new \Exception('Can\'t replace entry point: '.$file);
}
}
@ -761,7 +761,7 @@ EOF;
* @throws \Exception
*/
private function recursiveDelete($folder) {
if(!file_exists($folder)) {
if (!file_exists($folder)) {
return;
}
$iterator = new \RecursiveIteratorIterator(
@ -791,7 +791,7 @@ EOF;
}
$state = rmdir($folder);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir ' . $folder);
}
}
@ -805,12 +805,12 @@ EOF;
$this->silentLog('[info] deleteOldFiles()');
$shippedAppsFile = $this->baseDir . '/../core/shipped.json';
if(!file_exists($shippedAppsFile)) {
if (!file_exists($shippedAppsFile)) {
throw new \Exception('core/shipped.json is not available');
}
$newShippedAppsFile = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
if(!file_exists($newShippedAppsFile)) {
if (!file_exists($newShippedAppsFile)) {
throw new \Exception('core/shipped.json is not available in the new release');
}
@ -819,12 +819,12 @@ EOF;
json_decode(file_get_contents($shippedAppsFile), true)['shippedApps'],
json_decode(file_get_contents($newShippedAppsFile), true)['shippedApps']
);
foreach($shippedApps as $app) {
foreach ($shippedApps as $app) {
$this->recursiveDelete($this->baseDir . '/../apps/' . $app);
}
$configSampleFile = $this->baseDir . '/../config/config.sample.php';
if(file_exists($configSampleFile)) {
if (file_exists($configSampleFile)) {
$this->silentLog('[info] config sample exists');
// Delete example config
@ -835,7 +835,7 @@ EOF;
}
$themesReadme = $this->baseDir . '/../themes/README';
if(file_exists($themesReadme)) {
if (file_exists($themesReadme)) {
$this->silentLog('[info] themes README exists');
// Delete themes
@ -871,23 +871,23 @@ EOF;
$fileName = explode($currentDir, $path)[1];
$folderStructure = explode('/', $fileName, -1);
// Exclude the exclusions
if(isset($folderStructure[0])) {
if(array_search($folderStructure[0], $excludedElements) !== false) {
if (isset($folderStructure[0])) {
if (array_search($folderStructure[0], $excludedElements) !== false) {
continue;
}
} else {
if(array_search($fileName, $excludedElements) !== false) {
if (array_search($fileName, $excludedElements) !== false) {
continue;
}
}
if($fileInfo->isFile() || $fileInfo->isLink()) {
if ($fileInfo->isFile() || $fileInfo->isLink()) {
$state = unlink($path);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not unlink: '.$path);
}
} elseif($fileInfo->isDir()) {
} elseif ($fileInfo->isDir()) {
$state = rmdir($path);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir: '.$path);
}
}
@ -922,15 +922,15 @@ EOF;
}
}
if($fileInfo->isFile()) {
if(!file_exists($this->baseDir . '/../' . dirname($fileName))) {
if ($fileInfo->isFile()) {
if (!file_exists($this->baseDir . '/../' . dirname($fileName))) {
$state = mkdir($this->baseDir . '/../' . dirname($fileName), 0755, true);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not mkdir ' . $this->baseDir . '/../' . dirname($fileName));
}
}
$state = rename($path, $this->baseDir . '/../' . $fileName);
if($state === false) {
if ($state === false) {
throw new \Exception(
sprintf(
'Could not rename %s to %s',
@ -940,9 +940,9 @@ EOF;
);
}
}
if($fileInfo->isDir()) {
if ($fileInfo->isDir()) {
$state = rmdir($path);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir ' . $path);
}
}
@ -987,11 +987,11 @@ EOF;
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, []);
$state = rmdir($storageLocation);
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir $storagelocation');
}
$state = unlink($this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');
if($state === false) {
if ($state === false) {
throw new \Exception('Could not rmdir .step');
}
@ -1010,21 +1010,21 @@ EOF;
*/
private function writeStep($state, $step) {
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if(!file_exists($updaterDir . '/.step')) {
if(!file_exists($updaterDir)) {
if (!file_exists($updaterDir . '/.step')) {
if (!file_exists($updaterDir)) {
$result = mkdir($updaterDir);
if ($result === false) {
throw new \Exception('Could not create $updaterDir');
}
}
$result = touch($updaterDir . '/.step');
if($result === false) {
if ($result === false) {
throw new \Exception('Could not create .step');
}
}
$result = file_put_contents($updaterDir . '/.step', json_encode(['state' => $state, 'step' => $step]));
if($result === false) {
if ($result === false) {
throw new \Exception('Could not write to .step');
}
}
@ -1056,7 +1056,7 @@ EOF;
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$jsonData = [];
if(file_exists($updaterDir. '/.step')) {
if (file_exists($updaterDir. '/.step')) {
$state = file_get_contents($updaterDir . '/.step');
if ($state === false) {
throw new \Exception('Could not read from .step');
@ -1080,7 +1080,7 @@ EOF;
$this->silentLog('[info] rollbackChanges("' . $step . '")');
$updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
if(file_exists($updaterDir . '/.step')) {
if (file_exists($updaterDir . '/.step')) {
$this->silentLog('[info] unlink .step');
$state = unlink($updaterDir . '/.step');
if ($state === false) {
@ -1088,7 +1088,7 @@ EOF;
}
}
if($step >= 7) {
if ($step >= 7) {
$this->silentLog('[info] rollbackChanges - step >= 7');
// TODO: If it fails after step 7: Rollback
}
@ -1110,7 +1110,7 @@ EOF;
$message .= 'Trace:' . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
$message .= 'File:' . $e->getFile() . PHP_EOL;
$message .= 'Line:' . $e->getLine() . PHP_EOL;
if($e instanceof UpdateException) {
if ($e instanceof UpdateException) {
$message .= 'Data:' . PHP_EOL . print_r($e->getData(), true) . PHP_EOL;
}
$this->log($message);
@ -1126,11 +1126,11 @@ EOF;
$updaterLogPath = $this->getDataDirectoryLocation() . '/updater.log';
$fh = fopen($updaterLogPath, 'a');
if($fh === false) {
if ($fh === false) {
throw new LogException('Could not open updater.log');
}
if($this->requestID === null) {
if ($this->requestID === null) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
@ -1143,7 +1143,7 @@ EOF;
$logLine = date(\DateTime::ISO8601) . ' ' . $this->requestID . ' ' . $message . PHP_EOL;
$result = fwrite($fh, $logLine);
if($result === false) {
if ($result === false) {
throw new LogException('Could not write to updater.log');
}

View File

@ -11,69 +11,68 @@ $libDir = __DIR__ . '/../lib/';
$indexPhpContent = file_get_contents(__DIR__ . '/../index.php');
function findDiffPos($original, $copy) {
$lowerLimit = 0;
$upperLimit = strlen($copy) - 1;
$lowerLimit = 0;
$upperLimit = strlen($copy) - 1;
do {
$index = $lowerLimit + round(($upperLimit - $lowerLimit)/2);
do {
$index = $lowerLimit + round(($upperLimit - $lowerLimit) / 2);
$partOfCopy = substr($copy, 0, $index);
if(strpos($original, $partOfCopy) === false) {
$upperLimit = $index;
} else {
$lowerLimit = $index;
}
} while ($upperLimit - $lowerLimit > 5);
$partOfCopy = substr($copy, 0, $index);
if (strpos($original, $partOfCopy) === false) {
$upperLimit = $index;
} else {
$lowerLimit = $index;
}
} while ($upperLimit - $lowerLimit > 5);
$matchingSubstring = substr($copy, 0, $lowerLimit);
if(strlen($matchingSubstring) <= 20) {
$originalStart = 0;
$copyStart = 0;
} else {
$originalStart = strpos($original, $matchingSubstring) + strlen($matchingSubstring) - 20;
$copyStart = strlen($matchingSubstring) - 20;
}
$stringOriginal = substr($original, $originalStart, 40);
$stringCopy = substr($copy, $copyStart, 40);
$matchingSubstring = substr($copy, 0, $lowerLimit);
if (strlen($matchingSubstring) <= 20) {
$originalStart = 0;
$copyStart = 0;
} else {
$originalStart = strpos($original, $matchingSubstring) + strlen($matchingSubstring) - 20;
$copyStart = strlen($matchingSubstring) - 20;
}
$stringOriginal = substr($original, $originalStart, 40);
$stringCopy = substr($copy, $copyStart, 40);
echo "diff is in here: (between character $lowerLimit and $upperLimit):" . PHP_EOL;
echo '...' . $stringOriginal . '...' . PHP_EOL;
echo '...' . $stringCopy . '...' . PHP_EOL;
echo "diff is in here: (between character $lowerLimit and $upperLimit):" . PHP_EOL;
echo '...' . $stringOriginal . '...' . PHP_EOL;
echo '...' . $stringCopy . '...' . PHP_EOL;
}
$iterator = new \RecursiveDirectoryIterator(
$libDir,
\RecursiveDirectoryIterator::SKIP_DOTS
$libDir,
\RecursiveDirectoryIterator::SKIP_DOTS
);
/**
* @var string $path
* @var SplFileInfo $fileInfo
*/
foreach ($iterator as $path => $fileInfo) {
$fileName = explode($libDir, $path)[1];
$fileName = explode($libDir, $path)[1];
if(array_search($fileName, $excludedFiles) !== false) {
continue;
}
if (array_search($fileName, $excludedFiles) !== false) {
continue;
}
$fileContent = file_get_contents($path);
$fileContent = file_get_contents($path);
$fileContent = explode("namespace NC\\Updater;\n", $fileContent, 2)[1];
$fileContent = explode("namespace NC\\Updater;\n", $fileContent, 2)[1];
$fileContent = trim($fileContent);
$fileContent = trim($fileContent);
if(strpos($indexPhpContent, $fileContent) === false) {
$failedFiles[] = $fileName;
echo "$fileName" . PHP_EOL . PHP_EOL;
findDiffPos($indexPhpContent, $fileContent);
echo PHP_EOL;
}
if (strpos($indexPhpContent, $fileContent) === false) {
$failedFiles[] = $fileName;
echo "$fileName" . PHP_EOL . PHP_EOL;
findDiffPos($indexPhpContent, $fileContent);
echo PHP_EOL;
}
}
if($failedFiles !== []) {
echo "Code is not the same" . PHP_EOL;
exit(1);
if ($failedFiles !== []) {
echo "Code is not the same" . PHP_EOL;
exit(1);
}
echo "Code is the same" . PHP_EOL;
echo "Code is the same" . PHP_EOL;

View File

@ -5,135 +5,130 @@ use Behat\Behat\Context\SnippetAcceptingContext;
/**
* Defines application features from the specific context.
*/
class FeatureContext implements SnippetAcceptingContext
{
protected $buildDir;
protected $serverDir;
protected $updateServerDir;
protected $tmpDownloadDir;
protected $downloadURL = 'https://download.nextcloud.com/server/releases/';
protected $dailyDownloadURL = 'https://download.nextcloud.com/server/daily/latest-';
protected $prereleasesDownloadURL = 'https://download.nextcloud.com/server/prereleases/';
/** @var resource */
protected $updaterServerProcess = null;
/** @var string[] */
protected $CLIOutput;
/** @var integer */
protected $CLIReturnCode;
/** @var string */
protected $autoupdater = '1';
/** @var bool */
protected $skipIt = false;
class FeatureContext implements SnippetAcceptingContext {
protected $buildDir;
protected $serverDir;
protected $updateServerDir;
protected $tmpDownloadDir;
protected $downloadURL = 'https://download.nextcloud.com/server/releases/';
protected $dailyDownloadURL = 'https://download.nextcloud.com/server/daily/latest-';
protected $prereleasesDownloadURL = 'https://download.nextcloud.com/server/prereleases/';
/** @var resource */
protected $updaterServerProcess = null;
/** @var string[] */
protected $CLIOutput;
/** @var integer */
protected $CLIReturnCode;
/** @var string */
protected $autoupdater = '1';
/** @var bool */
protected $skipIt = false;
public function __construct()
{
$baseDir = __DIR__ . '/../../data/';
$this->serverDir = $baseDir . 'server/';
$this->tmpDownloadDir = $baseDir . 'downloads/';
$this->updateServerDir = $baseDir . 'update-server/';
$this->buildDir = $baseDir . '../../';
if(!file_exists($baseDir) && !mkdir($baseDir)) {
throw new RuntimeException('Creating tmp download dir failed');
}
if(!file_exists($this->serverDir) && !mkdir($this->serverDir)) {
throw new RuntimeException('Creating server dir failed');
}
if(!file_exists($this->tmpDownloadDir) && !mkdir($this->tmpDownloadDir)) {
throw new RuntimeException('Creating tmp download dir failed');
}
if(!file_exists($this->updateServerDir) && !mkdir($this->updateServerDir)) {
throw new RuntimeException('Creating update server dir failed');
}
}
public function __construct() {
$baseDir = __DIR__ . '/../../data/';
$this->serverDir = $baseDir . 'server/';
$this->tmpDownloadDir = $baseDir . 'downloads/';
$this->updateServerDir = $baseDir . 'update-server/';
$this->buildDir = $baseDir . '../../';
if (!file_exists($baseDir) && !mkdir($baseDir)) {
throw new RuntimeException('Creating tmp download dir failed');
}
if (!file_exists($this->serverDir) && !mkdir($this->serverDir)) {
throw new RuntimeException('Creating server dir failed');
}
if (!file_exists($this->tmpDownloadDir) && !mkdir($this->tmpDownloadDir)) {
throw new RuntimeException('Creating tmp download dir failed');
}
if (!file_exists($this->updateServerDir) && !mkdir($this->updateServerDir)) {
throw new RuntimeException('Creating update server dir failed');
}
}
/**
* @AfterScenario
*/
public function stopUpdateServer()
{
if(is_resource($this->updaterServerProcess)) {
proc_terminate($this->updaterServerProcess);
proc_close($this->updaterServerProcess);
}
}
/**
* @AfterScenario
*/
public function stopUpdateServer() {
if (is_resource($this->updaterServerProcess)) {
proc_terminate($this->updaterServerProcess);
proc_close($this->updaterServerProcess);
}
}
/**
* @Given /the current (installed )?version is ([0-9.]+((beta|RC)[0-9]?)?|stable[0-9]+|master)/
*/
public function theCurrentInstalledVersionIs($installed, $version)
{
/**
* @Given /the current (installed )?version is ([0-9.]+((beta|RC)[0-9]?)?|stable[0-9]+|master)/
*/
public function theCurrentInstalledVersionIs($installed, $version) {
if ($this->skipIt) {
return;
}
// recursive deletion of server folder
if(file_exists($this->serverDir)) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($this->serverDir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
// recursive deletion of server folder
if (file_exists($this->serverDir)) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($this->serverDir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $fileInfo) {
$action = $fileInfo->isDir() ? 'rmdir' : 'unlink';
$action($fileInfo->getRealPath());
}
$state = rmdir($this->serverDir);
if($state === false) {
throw new \Exception('Could not rmdir ' . $this->serverDir);
}
}
foreach ($iterator as $fileInfo) {
$action = $fileInfo->isDir() ? 'rmdir' : 'unlink';
$action($fileInfo->getRealPath());
}
$state = rmdir($this->serverDir);
if ($state === false) {
throw new \Exception('Could not rmdir ' . $this->serverDir);
}
}
$filename = 'nextcloud-' . $version . '.zip';
$filename = 'nextcloud-' . $version . '.zip';
if (!file_exists($this->tmpDownloadDir . $filename)) {
$fp = fopen($this->tmpDownloadDir . $filename, 'w+');
$url = $this->downloadURL . $filename;
if (strpos($version, 'RC') !== false || strpos($version, 'beta') !== false) {
$url = $this->prereleasesDownloadURL . 'nextcloud-' . $version . '.zip';
} else if(strpos($version, 'stable') !== false || strpos($version, 'master') !== false) {
$url = $this->dailyDownloadURL . $version . '.zip';
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_USERAGENT, 'Nextcloud Updater');
if(curl_exec($ch) === false) {
throw new \Exception('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode !== 200) {
throw new \Exception('Download failed - HTTP code: ' . $httpCode);
}
curl_close($ch);
fclose($fp);
}
if (!file_exists($this->tmpDownloadDir . $filename)) {
$fp = fopen($this->tmpDownloadDir . $filename, 'w+');
$url = $this->downloadURL . $filename;
if (strpos($version, 'RC') !== false || strpos($version, 'beta') !== false) {
$url = $this->prereleasesDownloadURL . 'nextcloud-' . $version . '.zip';
} elseif (strpos($version, 'stable') !== false || strpos($version, 'master') !== false) {
$url = $this->dailyDownloadURL . $version . '.zip';
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_USERAGENT, 'Nextcloud Updater');
if (curl_exec($ch) === false) {
throw new \Exception('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode !== 200) {
throw new \Exception('Download failed - HTTP code: ' . $httpCode);
}
curl_close($ch);
fclose($fp);
}
$zip = new ZipArchive;
$zipState = $zip->open($this->tmpDownloadDir . $filename);
if ($zipState === true) {
$zip->extractTo($this->serverDir);
$zip->close();
} else {
throw new \Exception('Cant handle ZIP file. Error code is: '.$zipState);
}
$zip = new ZipArchive;
$zipState = $zip->open($this->tmpDownloadDir . $filename);
if ($zipState === true) {
$zip->extractTo($this->serverDir);
$zip->close();
} else {
throw new \Exception('Cant handle ZIP file. Error code is: '.$zipState);
}
if($installed === '') {
if ($installed === '') {
// the instance should not be installed
return;
}
chdir($this->serverDir . 'nextcloud');
shell_exec('chmod +x occ');
exec('./occ maintenance:install --admin-user=admin --admin-pass=admin 2>&1', $output, $returnCode);
chdir($this->serverDir . 'nextcloud');
shell_exec('chmod +x occ');
exec('./occ maintenance:install --admin-user=admin --admin-pass=admin 2>&1', $output, $returnCode);
if ($returnCode !== 0) {
throw new Exception('Install failed' . PHP_EOL . join(PHP_EOL, $output));
}
}
if ($returnCode !== 0) {
throw new Exception('Install failed' . PHP_EOL . join(PHP_EOL, $output));
}
}
/**
* @Given there is no update available
*/
public function thereIsNoUpdateAvailable()
{
/**
* @Given there is no update available
*/
public function thereIsNoUpdateAvailable() {
if ($this->skipIt) {
return;
}
@ -156,8 +151,7 @@ class FeatureContext implements SnippetAcceptingContext
/**
* @When the CLI updater is run successfully
*/
public function theCliUpdaterIsRunSuccessfully()
{
public function theCliUpdaterIsRunSuccessfully() {
if ($this->skipIt) {
return;
}
@ -168,34 +162,33 @@ class FeatureContext implements SnippetAcceptingContext
}
}
/**
* @When the CLI updater is run
*/
public function theCliUpdaterIsRun()
{
/**
* @When the CLI updater is run
*/
public function theCliUpdaterIsRun() {
if ($this->skipIt) {
return;
}
if(!file_exists($this->buildDir . 'updater.phar')) {
throw new Exception('updater.phar not available - please build it in advance via "box build -c box.json"');
}
copy($this->buildDir . 'updater.phar', $this->serverDir . 'nextcloud/updater/updater');
chdir($this->serverDir . 'nextcloud/updater');
chmod($this->serverDir . 'nextcloud/updater/updater', 0755);
exec('./updater -n', $output, $returnCode);
if (!file_exists($this->buildDir . 'updater.phar')) {
throw new Exception('updater.phar not available - please build it in advance via "box build -c box.json"');
}
copy($this->buildDir . 'updater.phar', $this->serverDir . 'nextcloud/updater/updater');
chdir($this->serverDir . 'nextcloud/updater');
chmod($this->serverDir . 'nextcloud/updater/updater', 0755);
exec('./updater -n', $output, $returnCode);
// sleep to let the opcache do it's work and invalidate the status.php
sleep(5);
// sleep to let the opcache do it's work and invalidate the status.php
sleep(5);
$this->CLIOutput = $output;
$this->CLIReturnCode = $returnCode;
}
}
/**
* @param $version
* @return string
*/
public function getSignatureForVersion($version) {
$signatures = [
public function getSignatureForVersion($version) {
$signatures = [
'19.0.0beta4' => 'Cum4wIKpCRHNZuOQ/SfDYsIp39/4/Z3EIiMLTV7vFLf1pjsn+q1FRwk7HbT0ileU
9eGbmpJHrmbNFk73g6k2YLOeosznMD89+AtRrRRn7C+sJmXx90+Eejs1aWWBRi8j
wnC4PNYGZCqV10z+bMWNFWuZlkO2o2c+o8I/mIM93trRgnciFzA2YYAILnz4vZ5L
@ -247,24 +240,23 @@ V367c1FDks7iKs/V96u21NuF14IQzI0mEzMzysPINrKbHC+OU1BKHKOHqRJjkHwQ
fNJsXi16UkYMGUXyQWQXHg==',
];
if(isset($signatures[$version])) {
if (isset($signatures[$version])) {
return $signatures[$version];
}
return '';
}
}
/**
* @Given /there is an update to version ([0-9.]+) available/
*/
public function thereIsAnUpdateToVersionAvailable($version)
{
/**
* @Given /there is an update to version ([0-9.]+) available/
*/
public function thereIsAnUpdateToVersionAvailable($version) {
if ($this->skipIt) {
return;
}
$this->runUpdateServer();
$content = '<?php
$content = '<?php
header("Content-Type: application/xml");
?>
<?xml version="1.0" encoding="UTF-8"?>
@ -277,15 +269,13 @@ fNJsXi16UkYMGUXyQWQXHg==',
<signature>'.$this->getSignatureForVersion($version).'</signature>
</nextcloud>
';
file_put_contents($this->updateServerDir . 'index.php', $content);
}
file_put_contents($this->updateServerDir . 'index.php', $content);
}
/**
* @Given there is an update to prerelease version :version available
*/
public function thereIsAnUpdateToPrereleaseVersionAvailable($version)
{
public function thereIsAnUpdateToPrereleaseVersionAvailable($version) {
if ($this->skipIt) {
return;
}
@ -305,14 +295,12 @@ fNJsXi16UkYMGUXyQWQXHg==',
</nextcloud>
';
file_put_contents($this->updateServerDir . 'index.php', $content);
}
/**
* @Given /there is an update to daily version of (.*) available/
*/
public function thereIsAnUpdateToDailyVersionAvailable($version)
{
public function thereIsAnUpdateToDailyVersionAvailable($version) {
if ($this->skipIt) {
return;
}
@ -331,18 +319,16 @@ fNJsXi16UkYMGUXyQWQXHg==',
</nextcloud>
';
file_put_contents($this->updateServerDir . 'index.php', $content);
}
/**
* runs the updater server
* @throws Exception
*/
protected function runUpdateServer()
{
protected function runUpdateServer() {
$configFile = $this->serverDir . 'nextcloud/config/config.php';
$content = file_get_contents($configFile);
$content = preg_replace('!\$CONFIG\s*=\s*array\s*\(!', "\$CONFIG = array(\n 'updater.server.url' => 'http://localhost:8870/',", $content );
$content = preg_replace('!\$CONFIG\s*=\s*array\s*\(!', "\$CONFIG = array(\n 'updater.server.url' => 'http://localhost:8870/',", $content);
file_put_contents($configFile, $content);
if (!is_null($this->updaterServerProcess)) {
@ -352,7 +338,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
$cmd = "php -S localhost:8870 -t " . $this->updateServerDir . " 2>/dev/null 1>/dev/null";
$this->updaterServerProcess = proc_open($cmd, [], $pipes, $this->updateServerDir);
if(!is_resource($this->updaterServerProcess)) {
if (!is_resource($this->updaterServerProcess)) {
throw new Exception('Update server could not be started');
}
@ -360,29 +346,27 @@ fNJsXi16UkYMGUXyQWQXHg==',
sleep(1);
}
/**
* @Then /the installed version should be ([0-9.]+)/
*/
public function theInstalledVersionShouldBe2($version)
{
/**
* @Then /the installed version should be ([0-9.]+)/
*/
public function theInstalledVersionShouldBe2($version) {
if ($this->skipIt) {
return;
}
/** @var $OC_Version */
require $this->serverDir . 'nextcloud/version.php';
/** @var $OC_Version */
require $this->serverDir . 'nextcloud/version.php';
$installedVersion = join('.', $OC_Version);
$installedVersion = join('.', $OC_Version);
if (strpos($installedVersion, $version) !== 0) {
throw new Exception('Version mismatch - Installed: ' . $installedVersion . ' Wanted: ' . $version);
}
}
if (strpos($installedVersion, $version) !== 0) {
throw new Exception('Version mismatch - Installed: ' . $installedVersion . ' Wanted: ' . $version);
}
}
/**
* @Then /maintenance mode should be (on|off)/
*/
public function maintenanceModeShouldBe($state)
{
public function maintenanceModeShouldBe($state) {
if ($this->skipIt) {
return;
}
@ -403,8 +387,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
* @Given the current channel is :channel
* @param string $channel
*/
public function theCurrentChannelIs($channel)
{
public function theCurrentChannelIs($channel) {
if ($this->skipIt) {
return;
}
@ -417,8 +400,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
/**
* @Then /upgrade is (not required|required)/
*/
public function upgradeIs($state)
{
public function upgradeIs($state) {
if ($this->skipIt) {
return;
}
@ -448,8 +430,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
/**
* @Then /the return code should not be (\S*)/
*/
public function theReturnCodeShouldNotBe($expectedReturnCode)
{
public function theReturnCodeShouldNotBe($expectedReturnCode) {
if ($this->skipIt) {
return;
}
@ -461,8 +442,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
/**
* @Then /the output should contain "(.*)"/
*/
public function theOutputShouldBe($expectedOutput)
{
public function theOutputShouldBe($expectedOutput) {
if ($this->skipIt) {
return;
}
@ -474,8 +454,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
/**
* @Given /the version number is decreased in the config.php to enforce upgrade/
*/
public function theVersionNumberIsDecreasedInTheConfigPHPToEnforceUpgrade()
{
public function theVersionNumberIsDecreasedInTheConfigPHPToEnforceUpgrade() {
if ($this->skipIt) {
return;
}
@ -488,8 +467,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
/**
* @Given there is a folder called :name
*/
public function thereIsAFolderCalled($name)
{
public function thereIsAFolderCalled($name) {
if ($this->skipIt) {
return;
}
@ -499,8 +477,7 @@ fNJsXi16UkYMGUXyQWQXHg==',
/**
* @Given there is a config for a secondary apps directory called :name
*/
public function thereIsAConfigForASecondaryAppsDirectoryCalled($name)
{
public function thereIsAConfigForASecondaryAppsDirectoryCalled($name) {
if ($this->skipIt) {
return;
}
@ -528,8 +505,7 @@ EOF;
/**
* @Given /PHP is at least in version ([0-9.]+)/
*/
public function phpIsAtLeastInVersion($version)
{
public function phpIsAtLeastInVersion($version) {
$this->skipIt = !version_compare($version, PHP_VERSION, '<');
}
}

View File

@ -8,4 +8,4 @@ ini_set('log_errors', '1');
date_default_timezone_set('UTC');
$application = new NC\Updater\CommandApplication();
$application->run();
$application->run();