From 6c1a1234f8c5a064a72cb23cd397edcb9c6f0577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 10 Mar 2015 23:44:29 +0100 Subject: [PATCH] Properly handle available databases at runtime and respect setup checks in command line as well --- core/command/maintenance/install.php | 59 ++++++++----- core/setup/controller.php | 121 ++------------------------- lib/base.php | 3 +- lib/private/setup.php | 117 ++++++++++++++++++++++---- lib/private/util.php | 2 +- tests/lib/setup.php | 17 +++- 6 files changed, 164 insertions(+), 155 deletions(-) diff --git a/core/command/maintenance/install.php b/core/command/maintenance/install.php index 0b01afc20e..e92a546daa 100644 --- a/core/command/maintenance/install.php +++ b/core/command/maintenance/install.php @@ -3,6 +3,7 @@ namespace OC\Core\Command\Maintenance; use InvalidArgumentException; +use OC\Setup; use OCP\IConfig; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -38,39 +39,36 @@ class Install extends Command { protected function execute(InputInterface $input, OutputInterface $output) { - $options = $this->validateInput($input, $output); - - $errors = \OC\Setup::install($options); - if (count($errors) === 0) { - $output->writeln("ownCloud was successfully installed"); - return 0; - } - foreach($errors as $error) { - if (is_array($error)) { - $output->writeln('' . (string)$error['error'] . ''); - $output->writeln(' -> ' . (string)$error['hint'] . ''); - } else { - $output->writeln('' . (string)$error . ''); - } + // validate the environment + $setupHelper = new Setup($this->config, \OC::$server->getIniWrapper(), \OC::$server->getL10N('lib'), new \OC_Defaults()); + $sysInfo = $setupHelper->getSystemInfo(); + $errors = $sysInfo['errors']; + if (count($errors) > 0) { + $this->printErrors($output, $errors); + return 1; } - return 1; + // validate user input + $options = $this->validateInput($input, $output, array_keys($sysInfo['databases'])); + + // perform installation + $errors = $setupHelper->install($options); + if (count($errors) > 0) { + $this->printErrors($output, $errors); + return 1; + } + $output->writeln("ownCloud was successfully installed"); + return 0; } /** * @param InputInterface $input * @param OutputInterface $output + * @param string[] $supportedDatabases * @return array */ - protected function validateInput(InputInterface $input, OutputInterface $output) { + protected function validateInput(InputInterface $input, OutputInterface $output, $supportedDatabases) { $db = strtolower($input->getOption('database')); - $supportedDatabases = $this->config->getSystemValue('supportedDatabases', [ - 'sqlite', - 'mysql', - 'pgsql', - 'oci', - 'mssql' - ]); if (!in_array($db, $supportedDatabases)) { throw new InvalidArgumentException("Database <$db> is not supported."); @@ -126,4 +124,19 @@ class Install extends Command { ]; return $options; } + + /** + * @param OutputInterface $output + * @param $errors + */ + protected function printErrors(OutputInterface $output, $errors) { + foreach ($errors as $error) { + if (is_array($error)) { + $output->writeln('' . (string)$error['error'] . ''); + $output->writeln(' -> ' . (string)$error['hint'] . ''); + } else { + $output->writeln('' . (string)$error . ''); + } + } + } } diff --git a/core/setup/controller.php b/core/setup/controller.php index cc7f4a3a98..fa3637dd8f 100644 --- a/core/setup/controller.php +++ b/core/setup/controller.php @@ -9,42 +9,20 @@ namespace OC\Core\Setup; -use bantu\IniGetWrapper\IniGetWrapper; -use OCP\IConfig; -use OCP\IL10N; +use OC\Setup; class Controller { - /** - * @var \OCP\IConfig - */ - protected $config; - /** @var IniGetWrapper */ - protected $iniWrapper; - /** @var IL10N */ - protected $l10n; - /** @var \OC_Defaults */ - protected $defaults; - - /** - * @var string - */ + /** @var Setup */ + protected $setupHelper; + /** @var string */ private $autoConfigFile; /** - * @param IConfig $config - * @param IniGetWrapper $iniWrapper - * @param IL10N $l10n - * @param \OC_Defaults $defaults + * @param Setup $setupHelper */ - function __construct(IConfig $config, - IniGetWrapper $iniWrapper, - IL10N $l10n, - \OC_Defaults $defaults) { + function __construct(Setup $setupHelper) { $this->autoConfigFile = \OC::$SERVERROOT.'/config/autoconfig.php'; - $this->config = $config; - $this->iniWrapper = $iniWrapper; - $this->l10n = $l10n; - $this->defaults = $defaults; + $this->setupHelper = $setupHelper; } /** @@ -53,7 +31,7 @@ class Controller { public function run($post) { // Check for autosetup: $post = $this->loadAutoConfig($post); - $opts = $this->getSystemInfo(); + $opts = $this->setupHelper->getSystemInfo(); // convert 'abcpassword' to 'abcpass' if (isset($post['adminpassword'])) { @@ -65,7 +43,7 @@ class Controller { if(isset($post['install']) AND $post['install']=='true') { // We have to launch the installation process : - $e = \OC\Setup::install($post); + $e = $this->setupHelper->install($post); $errors = array('errors' => $e); if(count($e) > 0) { @@ -126,85 +104,4 @@ class Controller { return $post; } - - /** - * Gathers system information like database type and does - * a few system checks. - * - * @return array of system info, including an "errors" value - * in case of errors/warnings - */ - public function getSystemInfo() { - $setup = new \OC\Setup($this->config); - $databases = $setup->getSupportedDatabases(); - - $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data'); - - $errors = array(); - - // Create data directory to test whether the .htaccess works - // Notice that this is not necessarily the same data directory as the one - // that will effectively be used. - @mkdir($dataDir); - $htAccessWorking = true; - if (is_dir($dataDir) && is_writable($dataDir)) { - // Protect data directory here, so we can test if the protection is working - \OC\Setup::protectDataDirectory(); - - try { - $htAccessWorking = \OC_Util::isHtaccessWorking(); - } catch (\OC\HintException $e) { - $errors[] = array( - 'error' => $e->getMessage(), - 'hint' => $e->getHint() - ); - $htAccessWorking = false; - } - } - - - if (\OC_Util::runningOnMac()) { - $errors[] = array( - 'error' => $this->l10n->t( - 'Mac OS X is not supported and %s will not work properly on this platform. ' . - 'Use it at your own risk! ', - $this->defaults->getName() - ), - 'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.') - ); - } - - if($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) { - $errors[] = array( - 'error' => $this->l10n->t( - 'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' . - 'This will lead to problems with files over 4 GB and is highly discouraged.', - $this->defaults->getName() - ), - 'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.') - ); - } - if(!function_exists('curl_init') && PHP_INT_SIZE === 4) { - $errors[] = array( - 'error' => $this->l10n->t( - 'It seems that this %s instance is running on a 32-bit PHP environment and cURL is not installed. ' . - 'This will lead to problems with files over 4 GB and is highly discouraged.', - $this->defaults->getName() - ), - 'hint' => $this->l10n->t('Please install the cURL extension and restart your webserver.') - ); - } - - return array( - 'hasSQLite' => isset($databases['sqlite']), - 'hasMySQL' => isset($databases['mysql']), - 'hasPostgreSQL' => isset($databases['pgsql']), - 'hasOracle' => isset($databases['oci']), - 'hasMSSQL' => isset($databases['mssql']), - 'databases' => $databases, - 'directory' => $dataDir, - 'htaccessWorking' => $htAccessWorking, - 'errors' => $errors, - ); - } } diff --git a/lib/base.php b/lib/base.php index ea379e429b..107ae059bb 100644 --- a/lib/base.php +++ b/lib/base.php @@ -747,7 +747,8 @@ class OC { // Check if ownCloud is installed or in maintenance (update) mode if (!$systemConfig->getValue('installed', false)) { \OC::$server->getSession()->clear(); - $controller = new OC\Core\Setup\Controller(\OC::$server->getConfig(), \OC::$server->getIniWrapper(), \OC::$server->getL10N('core'), new \OC_Defaults()); + $setupHelper = new OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(), \OC::$server->getL10N('lib'), new \OC_Defaults()); + $controller = new OC\Core\Setup\Controller($setupHelper); $controller->run($_POST); exit(); } diff --git a/lib/private/setup.php b/lib/private/setup.php index 064afecbfe..1da42f0f8a 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -8,19 +8,34 @@ namespace OC; +use bantu\IniGetWrapper\IniGetWrapper; use Exception; -use OC_L10N; use OCP\IConfig; +use OCP\IL10N; class Setup { - /** @var IConfig */ + /** @var \OCP\IConfig */ protected $config; + /** @var IniGetWrapper */ + protected $iniWrapper; + /** @var IL10N */ + protected $l10n; + /** @var \OC_Defaults */ + protected $defaults; /** * @param IConfig $config + * @param IniGetWrapper $iniWrapper + * @param \OC_Defaults $defaults */ - function __construct(IConfig $config) { + function __construct(IConfig $config, + IniGetWrapper $iniWrapper, + IL10N $l10n, + \OC_Defaults $defaults) { $this->config = $config; + $this->iniWrapper = $iniWrapper; + $this->l10n = $l10n; + $this->defaults = $defaults; } static $dbSetupClasses = array( @@ -32,13 +47,6 @@ class Setup { 'sqlite3' => '\OC\Setup\Sqlite', ); - /** - * @return OC_L10N - */ - public static function getTrans(){ - return \OC::$server->getL10N('lib'); - } - /** * Wrapper around the "class_exists" PHP function to be able to mock it * @param string $name @@ -116,12 +124,91 @@ class Setup { return $supportedDatabases; } + /** + * Gathers system information like database type and does + * a few system checks. + * + * @return array of system info, including an "errors" value + * in case of errors/warnings + */ + public function getSystemInfo() { + $databases = $this->getSupportedDatabases(); + + $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data'); + + $errors = array(); + + // Create data directory to test whether the .htaccess works + // Notice that this is not necessarily the same data directory as the one + // that will effectively be used. + @mkdir($dataDir); + $htAccessWorking = true; + if (is_dir($dataDir) && is_writable($dataDir)) { + // Protect data directory here, so we can test if the protection is working + \OC\Setup::protectDataDirectory(); + + try { + $htAccessWorking = \OC_Util::isHtaccessWorking(); + } catch (\OC\HintException $e) { + $errors[] = array( + 'error' => $e->getMessage(), + 'hint' => $e->getHint() + ); + $htAccessWorking = false; + } + } + + if (\OC_Util::runningOnMac()) { + $errors[] = array( + 'error' => $this->l10n->t( + 'Mac OS X is not supported and %s will not work properly on this platform. ' . + 'Use it at your own risk! ', + $this->defaults->getName() + ), + 'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.') + ); + } + + if($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) { + $errors[] = array( + 'error' => $this->l10n->t( + 'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' . + 'This will lead to problems with files over 4 GB and is highly discouraged.', + $this->defaults->getName() + ), + 'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.') + ); + } + if(!function_exists('curl_init') && PHP_INT_SIZE === 4) { + $errors[] = array( + 'error' => $this->l10n->t( + 'It seems that this %s instance is running on a 32-bit PHP environment and cURL is not installed. ' . + 'This will lead to problems with files over 4 GB and is highly discouraged.', + $this->defaults->getName() + ), + 'hint' => $this->l10n->t('Please install the cURL extension and restart your webserver.') + ); + } + + return array( + 'hasSQLite' => isset($databases['sqlite']), + 'hasMySQL' => isset($databases['mysql']), + 'hasPostgreSQL' => isset($databases['pgsql']), + 'hasOracle' => isset($databases['oci']), + 'hasMSSQL' => isset($databases['mssql']), + 'databases' => $databases, + 'directory' => $dataDir, + 'htaccessWorking' => $htAccessWorking, + 'errors' => $errors, + ); + } + /** * @param $options * @return array */ - public static function install($options) { - $l = self::getTrans(); + public function install($options) { + $l = $this->l10n; $error = array(); $dbType = $options['dbtype']; @@ -146,7 +233,7 @@ class Setup { $class = self::$dbSetupClasses[$dbType]; /** @var \OC\Setup\AbstractDatabase $dbSetup */ - $dbSetup = new $class(self::getTrans(), 'db_structure.xml'); + $dbSetup = new $class($l, 'db_structure.xml'); $error = array_merge($error, $dbSetup->validate($options)); // validate the data directory @@ -186,7 +273,7 @@ class Setup { $secret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(48); //write the config file - \OC::$server->getConfig()->setSystemValues([ + $this->config->setSystemValues([ 'passwordsalt' => $salt, 'secret' => $secret, 'trusted_domains' => $trustedDomains, @@ -281,7 +368,7 @@ class Setup { * @throws \OC\HintException If .htaccess does not include the current version */ public static function updateHtaccess() { - $setupHelper = new \OC\Setup(\OC::$server->getConfig()); + $setupHelper = new \OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(), \OC::$server->getL10N('lib'), new \OC_Defaults()); if(!$setupHelper->isCurrentHtaccess()) { throw new \OC\HintException('.htaccess file has the wrong version. Please upload the correct version. Maybe you forgot to replace it after updating?'); } diff --git a/lib/private/util.php b/lib/private/util.php index 49c422c287..72802409da 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -497,7 +497,7 @@ class OC_Util { } $webServerRestart = false; - $setup = new OC\Setup($config); + $setup = new \OC\Setup($config, \OC::$server->getIniWrapper(), \OC::$server->getL10N('lib'), new \OC_Defaults()); $availableDatabases = $setup->getSupportedDatabases(); if (empty($availableDatabases)) { $errors[] = array( diff --git a/tests/lib/setup.php b/tests/lib/setup.php index db6f0e7a05..caaeec08fb 100644 --- a/tests/lib/setup.php +++ b/tests/lib/setup.php @@ -10,16 +10,27 @@ use OCP\IConfig; class Test_OC_Setup extends \Test\TestCase { - /** @var IConfig */ + /** @var IConfig | PHPUnit_Framework_MockObject_MockObject */ protected $config; - /** @var \OC\Setup */ + /** @var \bantu\IniGetWrapper\IniGetWrapper | PHPUnit_Framework_MockObject_MockObject */ + private $iniWrapper; + /** @var \OCP\IL10N | PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + /** @var \OC_Defaults | PHPUnit_Framework_MockObject_MockObject */ + private $defaults; + /** @var \OC\Setup | PHPUnit_Framework_MockObject_MockObject */ protected $setupClass; protected function setUp() { parent::setUp(); $this->config = $this->getMock('\OCP\IConfig'); - $this->setupClass = $this->getMock('\OC\Setup', ['class_exists', 'is_callable'], [$this->config]); + $this->iniWrapper = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper'); + $this->l10n = $this->getMock('\OCP\IL10N'); + $this->defaults = $this->getMock('\OC_Defaults'); + $this->setupClass = $this->getMock('\OC\Setup', + ['class_exists', 'is_callable'], + [$this->config, $this->iniWrapper, $this->l10n, $this->defaults]); } public function testGetSupportedDatabasesWithOneWorking() {