1<?php 2/** 3 * @author Bernhard Posselt <dev@bernhard-posselt.com> 4 * @author Christian Kampka <christian@kampka.net> 5 * @author Jörn Friedrich Dreyer <jfd@butonic.de> 6 * @author Morris Jobke <hey@morrisjobke.de> 7 * @author Thomas Müller <thomas.mueller@tmit.eu> 8 * 9 * @copyright Copyright (c) 2018, ownCloud GmbH 10 * @license AGPL-3.0 11 * 12 * This code is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU Affero General Public License, version 3, 14 * as published by the Free Software Foundation. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Affero General Public License for more details. 20 * 21 * You should have received a copy of the GNU Affero General Public License, version 3, 22 * along with this program. If not, see <http://www.gnu.org/licenses/> 23 * 24 */ 25namespace OC\Core\Command\Maintenance; 26 27use InvalidArgumentException; 28use OC\Setup; 29use OCP\IConfig; 30use Symfony\Component\Console\Command\Command; 31use Symfony\Component\Console\Input\InputInterface; 32use Symfony\Component\Console\Input\InputOption; 33use Symfony\Component\Console\Output\OutputInterface; 34use Symfony\Component\Console\Question\Question; 35 36class Install extends Command { 37 38 /** 39 * @var IConfig 40 */ 41 private $config; 42 43 public function __construct(IConfig $config) { 44 parent::__construct(); 45 $this->config = $config; 46 } 47 48 protected function configure() { 49 $this 50 ->setName('maintenance:install') 51 ->setDescription('Install ownCloud.') 52 ->addOption('database', null, InputOption::VALUE_REQUIRED, 'Supported database type.', 'sqlite') 53 ->addOption('database-connection-string', null, InputOption::VALUE_REQUIRED, 'Oracle specific connection string. As soon as this parameter is provided other parameters like database-host and database-name are not used and do not need to be provided') 54 ->addOption('database-name', null, InputOption::VALUE_REQUIRED, 'Name of the database.') 55 ->addOption('database-host', null, InputOption::VALUE_REQUIRED, 'Hostname of the database.', 'localhost') 56 ->addOption('database-user', null, InputOption::VALUE_REQUIRED, 'User name to connect to the database.') 57 ->addOption('database-pass', null, InputOption::VALUE_OPTIONAL, 'Password of the database user.', null) 58 ->addOption('database-table-prefix', null, InputOption::VALUE_OPTIONAL, 'Prefix for all tables (default: oc_).', null) 59 ->addOption('admin-user', null, InputOption::VALUE_REQUIRED, 'User name of the admin account.', 'admin') 60 ->addOption('admin-pass', null, InputOption::VALUE_REQUIRED, 'Password of the admin account.') 61 ->addOption('data-dir', null, InputOption::VALUE_REQUIRED, 'Path to the data directory.', \OC::$SERVERROOT."/data"); 62 } 63 64 protected function execute(InputInterface $input, OutputInterface $output) { 65 66 // validate the environment 67 $server = \OC::$server; 68 $setupHelper = new Setup( 69 $this->config, 70 $server->getIniWrapper(), 71 $server->getL10N('lib'), 72 new \OC_Defaults(), 73 $server->getLogger(), 74 $server->getSecureRandom() 75 ); 76 $sysInfo = $setupHelper->getSystemInfo(true); 77 $errors = $sysInfo['errors']; 78 if (\count($errors) > 0) { 79 $this->printErrors($output, $errors); 80 81 // ignore the OS X setup warning 82 if (\count($errors) !== 1 || 83 (string)($errors[0]['error']) !== 'Mac OS X is not supported and ownCloud will not work properly on this platform. Use it at your own risk! ') { 84 return 1; 85 } 86 } 87 88 // validate user input 89 $options = $this->validateInput($input, $output, \array_keys($sysInfo['databases'])); 90 91 // perform installation 92 $errors = $setupHelper->install($options); 93 if (\count($errors) > 0) { 94 $this->printErrors($output, $errors); 95 return 1; 96 } 97 $output->writeln("ownCloud was successfully installed"); 98 return 0; 99 } 100 101 /** 102 * @param InputInterface $input 103 * @param OutputInterface $output 104 * @param string[] $supportedDatabases 105 * @return array 106 */ 107 protected function validateInput(InputInterface $input, OutputInterface $output, $supportedDatabases) { 108 $db = \strtolower($input->getOption('database')); 109 110 if (!\in_array($db, $supportedDatabases)) { 111 throw new InvalidArgumentException("Database <$db> is not supported."); 112 } 113 114 $dbUser = $input->getOption('database-user'); 115 $dbPass = $input->getOption('database-pass'); 116 $dbName = $input->getOption('database-name'); 117 $dbConnectionString = $input->getOption('database-connection-string'); 118 if ($db === 'oci') { 119 // an empty hostname needs to be read from the raw parameters 120 $dbHost = $input->getParameterOption('--database-host', ''); 121 } else { 122 $dbHost = $input->getOption('database-host'); 123 } 124 $dbTablePrefix = 'oc_'; 125 if ($input->hasParameterOption('--database-table-prefix')) { 126 $dbTablePrefix = (string) $input->getOption('database-table-prefix'); 127 $dbTablePrefix = \trim($dbTablePrefix); 128 } 129 if ($input->hasParameterOption('--database-pass')) { 130 $dbPass = (string) $input->getOption('database-pass'); 131 } 132 $adminLogin = $input->getOption('admin-user'); 133 $adminPassword = $input->getOption('admin-pass'); 134 $dataDir = $input->getOption('data-dir'); 135 136 if ($db !== 'sqlite') { 137 if ($dbUser === null) { 138 throw new InvalidArgumentException("Database user not provided."); 139 } 140 if ($dbName === null && $dbConnectionString === null) { 141 throw new InvalidArgumentException('Database name and connection string not provided.'); 142 } 143 if ($dbPass === null) { 144 /** @var $dialog \Symfony\Component\Console\Helper\QuestionHelper */ 145 $dialog = $this->getHelperSet()->get('question'); 146 '@phan-var \Symfony\Component\Console\Helper\QuestionHelper $dialog'; 147 $q = new Question("<question>What is the password to access the database with user <$dbUser>?</question>", false); 148 $q->setHidden(true); 149 $dbPass = $dialog->ask($input, $output, $q); 150 } 151 } 152 153 if ($adminPassword === null) { 154 /** @var $dialog \Symfony\Component\Console\Helper\QuestionHelper */ 155 $dialog = $this->getHelperSet()->get('question'); 156 '@phan-var \Symfony\Component\Console\Helper\QuestionHelper $dialog'; 157 $q = new Question("<question>What is the password you like to use for the admin account <$adminLogin>?</question>", false); 158 $q->setHidden(true); 159 $adminPassword = $dialog->ask($input, $output, $q); 160 } 161 162 $options = [ 163 'dbtype' => $db, 164 'dbuser' => $dbUser, 165 'dbpass' => $dbPass, 166 'dbname' => $dbName, 167 'dbhost' => $dbHost, 168 'dbconnectionstring' => $dbConnectionString, 169 'dbtableprefix' => $dbTablePrefix, 170 'adminlogin' => $adminLogin, 171 'adminpass' => $adminPassword, 172 'directory' => $dataDir 173 ]; 174 return $options; 175 } 176 177 /** 178 * @param OutputInterface $output 179 * @param $errors 180 */ 181 protected function printErrors(OutputInterface $output, $errors) { 182 foreach ($errors as $error) { 183 if (\is_array($error)) { 184 $output->writeln('<error>' . (string)$error['error'] . '</error>'); 185 $output->writeln('<info> -> ' . (string)$error['hint'] . '</info>'); 186 } else { 187 $output->writeln('<error>' . (string)$error . '</error>'); 188 } 189 } 190 } 191} 192