Last active
October 25, 2016 22:18
-
-
Save VicDeo/937a0172a06d693258b97b7132c4ba5b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -Naur updater/src/Command/PostUpgradeCleanupCommand.php updater/src/Command/PostUpgradeCleanupCommand.php | |
--- updater/src/Command/PostUpgradeCleanupCommand.php 2016-07-20 12:15:17.000000000 +0300 | |
+++ updater/src/Command/PostUpgradeCleanupCommand.php 2016-10-25 14:54:44.000000000 +0300 | |
@@ -57,6 +57,14 @@ | |
//Cleanup Filesystem | |
$fsHelper->removeIfExists($locator->getExtractionBaseDir()); | |
+ //Retrigger integrity check | |
+ try { | |
+ $this->container['utils.occrunner']->run('integrity:check-core'); | |
+ } catch (\Exception $e){ | |
+ $this->getApplication()->getLogger()->error('Integrity check failed'); | |
+ $this->getApplication()->logException($e); | |
+ } | |
+ | |
//Cleanup updater cache | |
$registry->clearAll(); | |
diff -Naur updater/src/Console/Application.php updater/src/Console/Application.php | |
--- updater/src/Console/Application.php 2016-07-20 12:15:17.000000000 +0300 | |
+++ updater/src/Console/Application.php 2016-10-25 14:54:44.000000000 +0300 | |
@@ -24,6 +24,7 @@ | |
use Owncloud\Updater\Utils\DocLink; | |
use Owncloud\Updater\Utils\Locator; | |
+use Owncloud\Updater\Utils\OccRunner; | |
use Pimple\Container; | |
use Symfony\Component\Console\Logger\ConsoleLogger; | |
use Symfony\Component\Console\Output\ConsoleOutput; | |
@@ -32,7 +33,7 @@ | |
use Symfony\Component\Console\Output\BufferedOutput; | |
use Symfony\Component\Console\Output\OutputInterface; | |
use Symfony\Component\Console\Command\Command; | |
-use \Symfony\Component\Process\Exception\ProcessFailedException; | |
+use Symfony\Component\Process\Exception\ProcessFailedException; | |
/** | |
* Class Application | |
@@ -128,6 +129,27 @@ | |
return $this->fallbackLogger; | |
} | |
+ public function initConfig(){ | |
+ $configReader = $this->diContainer['utils.configReader']; | |
+ try { | |
+ $configReader->init(); | |
+ } catch (\UnexpectedValueException $e){ | |
+ // try fallback to localhost | |
+ preg_match_all('/https?:\/\/([^\/]*).*$/', $this->getEndpoint(), $matches); | |
+ if (isset($matches[1][0])){ | |
+ $newEndPoint = str_replace($matches[1][0], 'localhost', $this->getEndpoint()); | |
+ $this->setEndpoint($newEndPoint); | |
+ try { | |
+ $configReader->init(); | |
+ } catch (\UnexpectedValueException $e){ | |
+ // fallback to CLI | |
+ $this->diContainer['utils.occrunner']->setCanUseProcess(true); | |
+ $configReader->init(); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
/** | |
* Log exception with trace | |
* @param \Exception $e | |
@@ -147,16 +169,18 @@ | |
* @throws \Exception | |
*/ | |
public function doRun(InputInterface $input, OutputInterface $output){ | |
+ $commandName = $this->getCommandName($input); | |
try{ | |
- $configReader = $this->diContainer['utils.configReader']; | |
- $commandName = $this->getCommandName($input); | |
+ $this->assertOwnCloudFound(); | |
try{ | |
- $configReader->init(); | |
- $this->diContainer['utils.docLink'] = function($c){ | |
- $locator = $c['utils.locator']; | |
- $installedVersion = implode('.', $locator->getInstalledVersion()); | |
- return new DocLink($installedVersion); | |
- }; | |
+ $this->initConfig(); | |
+ if (!isset($this->diContainer['utils.docLink'])) { | |
+ $this->diContainer['utils.docLink'] = function ($c) { | |
+ $locator = $c['utils.locator']; | |
+ $installedVersion = implode('.', $locator->getInstalledVersion()); | |
+ return new DocLink($installedVersion); | |
+ }; | |
+ } | |
} catch (ProcessFailedException $e){ | |
if (!in_array($commandName, $this->allowFailure)){ | |
$this->logException($e); | |
@@ -169,13 +193,17 @@ | |
} | |
} | |
// TODO: check if the current command needs a valid OC instance | |
- $this->assertOwnCloudFound(); | |
- | |
- return parent::doRun($input, $output); | |
+ if (!isset($this->diContainer['logger'])) { | |
+ $locator = $this->diContainer['utils.locator']; | |
+ $this->initLogger($locator->getDataDir()); | |
+ } | |
} catch (\Exception $e){ | |
- $this->logException($e); | |
- throw $e; | |
+ if (!in_array($commandName, $this->allowFailure)){ | |
+ $this->logException($e); | |
+ throw $e; | |
+ } | |
} | |
+ return parent::doRun($input, $output); | |
} | |
/** | |
@@ -190,7 +218,7 @@ | |
$command->setContainer($this->getContainer()); | |
$commandName = $this->getCommandName($input); | |
$this->getLogger()->info('Execution of ' . $commandName . ' command started'); | |
- if (!empty($command->getMessage())){ | |
+ if ($command->getMessage()!==''){ | |
$message = sprintf('<info>%s</info>', $command->getMessage()); | |
$output->writeln($message); | |
} | |
@@ -225,28 +253,25 @@ | |
* Check for ownCloud instance | |
* @throws \RuntimeException | |
*/ | |
- protected function assertOwnCloudFound(){ | |
+ public function assertOwnCloudFound(){ | |
$container = $this->getContainer(); | |
/** @var Locator $locator */ | |
$locator = $container['utils.locator']; | |
$fsHelper = $container['utils.filesystemhelper']; | |
- | |
- // assert minimum version | |
- $installedVersion = implode('.', $locator->getInstalledVersion()); | |
- if (version_compare($installedVersion, '9.0.0', '<')){ | |
- throw new \RuntimeException("Minimum ownCloud version 9.0.0 is required for the updater - $installedVersion was found in " . $locator->getOwnCloudRootPath()); | |
- } | |
+ /** @var OccRunner $occRunner */ | |
+ $occRunner = $container['utils.occrunner']; | |
// has to be installed | |
$file = $locator->getPathToConfigFile(); | |
- if (!file_exists($file) || !is_file($file)){ | |
- throw new \RuntimeException('ownCloud in ' . dirname(dirname($file)) . ' is not installed.'); | |
- } | |
+ $this->assertFileExists($file, 'ownCloud in ' . dirname(dirname($file)) . ' is not installed.'); | |
// version.php should exist | |
$file = $locator->getPathToVersionFile(); | |
- if (!file_exists($file) || !is_file($file)){ | |
- throw new \RuntimeException('ownCloud is not found in ' . dirname($file)); | |
+ $this->assertFileExists($file, 'ownCloud is not found in ' . dirname($file)); | |
+ | |
+ $status = $occRunner->runJson('status'); | |
+ if (!isset($status['installed']) || $status['installed'] != 'true'){ | |
+ throw new \RuntimeException('ownCloud in ' . dirname($file) . ' is not installed.'); | |
} | |
// datadir should exist | |
@@ -260,8 +285,10 @@ | |
throw new \RuntimeException('Datadirectory ' . $dataDir . ' is not writable.'); | |
} | |
- if (!isset($this->diContainer['logger'])) { | |
- $this->initLogger($dataDir); | |
+ // assert minimum version | |
+ $installedVersion = implode('.', $locator->getInstalledVersion()); | |
+ if (version_compare($installedVersion, '9.0.0', '<')){ | |
+ throw new \RuntimeException("Minimum ownCloud version 9.0.0 is required for the updater - $installedVersion was found in " . $locator->getOwnCloudRootPath()); | |
} | |
if (!$fsHelper->fileExists($locator->getUpdaterBaseDir())){ | |
@@ -275,4 +302,14 @@ | |
$fsHelper->mkdir($locator->getCheckpointDir()); | |
} | |
} | |
+ | |
+ /** | |
+ * @param string $path | |
+ * @param string $message | |
+ */ | |
+ protected function assertFileExists($path, $message){ | |
+ if (!file_exists($path) || !is_file($path)){ | |
+ throw new \RuntimeException($message); | |
+ } | |
+ } | |
} | |
diff -Naur updater/src/Controller/IndexController.php updater/src/Controller/IndexController.php | |
--- updater/src/Controller/IndexController.php 2016-07-20 12:15:17.000000000 +0300 | |
+++ updater/src/Controller/IndexController.php 2016-10-25 14:54:44.000000000 +0300 | |
@@ -22,15 +22,16 @@ | |
namespace Owncloud\Updater\Controller; | |
-use League\Plates\Extension\URI; | |
use Owncloud\Updater\Utils\Checkpoint; | |
use Owncloud\Updater\Utils\ConfigReader; | |
-use Symfony\Component\Console\Input\StringInput; | |
-use Symfony\Component\Console\Output\BufferedOutput; | |
use Owncloud\Updater\Formatter\HtmlOutputFormatter; | |
use Owncloud\Updater\Http\Request; | |
use League\Plates\Engine; | |
use League\Plates\Extension\Asset; | |
+use League\Plates\Extension\URI; | |
+use Symfony\Component\Console\Output\BufferedOutput; | |
+use Symfony\Component\Console\Input\StringInput; | |
+use Symfony\Component\Process\Exception\ProcessFailedException; | |
class IndexController { | |
@@ -60,17 +61,38 @@ | |
} | |
public function dispatch() { | |
+ /** @var ConfigReader $configReader */ | |
+ $configReader = $this->container['utils.configReader']; | |
+ | |
// strip index.php and query string (if any) to get a real base url | |
$baseUrl = preg_replace('/(index\.php.*|\?.*)$/', '', $_SERVER['REQUEST_URI']); | |
$templates = new Engine(CURRENT_DIR . '/src/Resources/views/'); | |
$templates->loadExtension(new Asset(CURRENT_DIR . '/pub/', false)); | |
$templates->loadExtension(new URI($baseUrl)); | |
- | |
+ | |
// Check if the user is logged-in | |
if(!$this->isLoggedIn()) { | |
return $this->showLogin($templates); | |
} | |
- | |
+ | |
+ try { | |
+ $fullEndpoint = $this->getEndpoint(); | |
+ $this->container['application']->setEndpoint($fullEndpoint); | |
+ $this->container['application']->setAuthToken($this->request->header('X_Updater_Auth')); | |
+ $this->container['application']->initConfig(); | |
+ $this->container['application']->assertOwnCloudFound(); | |
+ } catch (\Exception $e){ | |
+ $content = $templates->render( | |
+ 'partials/error', | |
+ [ | |
+ 'title' => 'Updater', | |
+ 'version' => $this->container['application']->getVersion(), | |
+ 'error' => $e->getMessage() | |
+ ] | |
+ ); | |
+ return $content; | |
+ } | |
+ | |
if (is_null($this->command)){ | |
/** @var Checkpoint $checkpoint */ | |
$checkpoint = $this->container['utils.checkpoint']; | |
@@ -90,11 +112,14 @@ | |
return $content; | |
} | |
+ /** | |
+ * @return bool | |
+ */ | |
protected function isLoggedIn() { | |
/** @var ConfigReader $configReader */ | |
$locator = $this->container['utils.locator']; | |
$storedSecret = $locator->getSecretFromConfig(); | |
- if($storedSecret === '') { | |
+ if ($storedSecret === '') { | |
die('updater.secret is undefined in config/config.php. Either browse the admin settings in your ownCloud and click "Open updater" or define a strong secret using <pre>php -r \'echo password_hash("MyStrongSecretDoUseYourOwn!", PASSWORD_DEFAULT)."\n";\'</pre> and set this in the config.php.'); | |
} | |
$sentAuthHeader = ($this->request->header('X_Updater_Auth') !== null) ? $this->request->header('X_Updater_Auth') : ''; | |
@@ -135,16 +160,6 @@ | |
$application->setAutoExit(false); | |
- $endpoint = preg_replace('/(updater\/|updater\/index.php)$/', '', $this->request->getRequestUri()); | |
- $fullEndpoint = sprintf( | |
- '%s://%s%sindex.php/occ/', | |
- $this->request->getServerProtocol(), | |
- $this->request->getHost(), | |
- $endpoint !== '' ? $endpoint : '/' | |
- ); | |
- | |
- $application->setEndpoint($fullEndpoint); | |
- $application->setAuthToken($this->request->header('X_Updater_Auth')); | |
// Some commands dump things out instead of returning a value | |
ob_start(); | |
$errorCode = $application->run($input, $output); | |
@@ -162,5 +177,17 @@ | |
'error_code' => $errorCode | |
]; | |
} | |
+ | |
+ protected function getEndpoint(){ | |
+ $endpoint = preg_replace('/(updater\/|updater\/index.php)$/', '', $this->request->getRequestUri()); | |
+ $fullEndpoint = sprintf( | |
+ '%s://%s%sindex.php/occ/', | |
+ $this->request->getServerProtocol(), | |
+ $this->request->getHost(), | |
+ $endpoint !== '' ? $endpoint : '/' | |
+ ); | |
+ | |
+ return $fullEndpoint; | |
+ } | |
} | |
diff -Naur updater/src/Resources/views/partials/error.php updater/src/Resources/views/partials/error.php | |
--- updater/src/Resources/views/partials/error.php 1970-01-01 03:00:00.000000000 +0300 | |
+++ updater/src/Resources/views/partials/error.php 2016-10-25 14:54:44.000000000 +0300 | |
@@ -0,0 +1,2 @@ | |
+<?=$this->e($error) ?> | |
+ | |
diff -Naur updater/src/Utils/Locator.php updater/src/Utils/Locator.php | |
--- updater/src/Utils/Locator.php 2016-07-20 12:15:17.000000000 +0300 | |
+++ updater/src/Utils/Locator.php 2016-10-25 14:54:44.000000000 +0300 | |
@@ -72,6 +72,7 @@ | |
"AUTHORS", | |
"console.php", | |
"COPYING-AGPL", | |
+ "COPYING", | |
"cron.php", | |
"db_structure.xml", | |
"index.html", | |
diff -Naur updater/src/Utils/OccRunner.php updater/src/Utils/OccRunner.php | |
--- updater/src/Utils/OccRunner.php 2016-07-20 12:15:17.000000000 +0300 | |
+++ updater/src/Utils/OccRunner.php 2016-10-25 14:54:44.000000000 +0300 | |
@@ -49,13 +49,17 @@ | |
$this->canUseProcess = $canUseProcess; | |
} | |
+ public function setCanUseProcess($canUseProcess){ | |
+ $this->canUseProcess = $canUseProcess; | |
+ } | |
+ | |
public function run($command, $args = [], $asJson = false){ | |
if ($this->canUseProcess){ | |
$extra = $asJson ? '--output=json' : ''; | |
$cmdLine = trim($command . ' ' . $extra); | |
foreach ($args as $optionTitle => $optionValue){ | |
if (strpos($optionTitle, '--') === 0){ | |
- $line = trim("$optionTitle $optionValue"); | |
+ $line = trim("$optionTitle=$optionValue"); | |
} else { | |
$line = $optionValue; | |
} | |
--- core/Controller/OccController.php 2016-07-20 12:15:02.000000000 +0300 | |
+++ core/Controller/OccController.php 2016-10-25 14:54:36.000000000 +0300 | |
@@ -26,6 +26,7 @@ | |
use OC\Console\Application; | |
use OCP\IConfig; | |
use OCP\IRequest; | |
+use OCP\ILogger; | |
use Symfony\Component\Console\Input\ArrayInput; | |
use Symfony\Component\Console\Output\BufferedOutput; | |
@@ -40,6 +41,7 @@ | |
'check', | |
'config:list', | |
'maintenance:mode', | |
+ 'integrity:check-core', | |
'status', | |
'upgrade' | |
]; | |
@@ -48,6 +50,8 @@ | |
private $config; | |
/** @var Application */ | |
private $console; | |
+ /** @var ILogger */ | |
+ private $logger; | |
/** | |
* OccController constructor. | |
@@ -56,12 +60,14 @@ | |
* @param IRequest $request | |
* @param IConfig $config | |
* @param Application $console | |
+ * @param ILogger $logger | |
*/ | |
public function __construct($appName, IRequest $request, | |
- IConfig $config, Application $console) { | |
+ IConfig $config, Application $console, ILogger $logger) { | |
parent::__construct($appName, $request); | |
$this->config = $config; | |
$this->console = $console; | |
+ $this->logger = $logger; | |
} | |
/** | |
@@ -108,6 +114,13 @@ | |
]; | |
} catch (\UnexpectedValueException $e){ | |
+ $this->logger->warning( | |
+ 'Invalid request to occ controller. Details: "{details}"', | |
+ [ | |
+ 'app' => 'core', | |
+ 'details' => $e->getMessage() | |
+ ] | |
+ ); | |
$json = [ | |
'exitCode' => 126, | |
'response' => 'Not allowed', | |
@@ -123,8 +136,13 @@ | |
* @param $token | |
*/ | |
protected function validateRequest($command, $token){ | |
- if (!in_array($this->request->getRemoteAddress(), ['::1', '127.0.0.1', 'localhost'])) { | |
- throw new \UnexpectedValueException('Web executor is not allowed to run from a different host'); | |
+ $allowedHosts = ['::1', '127.0.0.1', 'localhost']; | |
+ if (isset($this->request->server['SERVER_ADDR'])){ | |
+ array_push($allowedHosts, $this->request->server['SERVER_ADDR']); | |
+ } | |
+ | |
+ if (!in_array($this->request->getRemoteAddress(), $allowedHosts)) { | |
+ throw new \UnexpectedValueException('Web executor is not allowed to run from a host ' . $this->request->getRemoteAddress()); | |
} | |
if (!in_array($command, $this->allowedCommands)) { | |
--- core/Application.php 2016-07-20 12:15:02.000000000 +0300 | |
+++ core/Application.php 2016-10-25 14:54:36.000000000 +0300 | |
@@ -126,18 +126,6 @@ | |
$c->query('SecureRandom') | |
); | |
}); | |
- $container->registerService('OccController', function(SimpleContainer $c) { | |
- return new OccController( | |
- $c->query('AppName'), | |
- $c->query('Request'), | |
- $c->query('Config'), | |
- new \OC\Console\Application( | |
- $c->query('Config'), | |
- $c->query('ServerContainer')->getEventDispatcher(), | |
- $c->query('Request') | |
- ) | |
- ); | |
- }); | |
/** | |
* Core class wrappers | |
--- core/routes.php 2016-07-20 12:15:02.000000000 +0300 | |
+++ core/routes.php 2016-10-25 14:54:36.000000000 +0300 | |
@@ -48,7 +48,7 @@ | |
['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'], | |
['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'], | |
['name' => 'token#generateToken', 'url' => '/token/generate', 'verb' => 'POST'], | |
- ['name' => 'occ#execute', 'url' => '/occ/{command}', 'verb' => 'POST'], | |
+ ['name' => 'OC\Core\Controller\Occ#execute', 'url' => '/occ/{command}', 'verb' => 'POST'], | |
['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'], | |
['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'], | |
['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'], |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment