Skip to content

Instantly share code, notes, and snippets.

@VicDeo
Last active October 25, 2016 22:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VicDeo/937a0172a06d693258b97b7132c4ba5b to your computer and use it in GitHub Desktop.
Save VicDeo/937a0172a06d693258b97b7132c4ba5b to your computer and use it in GitHub Desktop.
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