Passed
Push — master ( 5bb75c...645e3e )
by Roeland
31:07 queued 15:37
created
core/Command/Maintenance/Install.php 2 patches
Indentation   +177 added lines, -177 removed lines patch added patch discarded remove patch
@@ -48,181 +48,181 @@
 block discarded – undo
48 48
 
49 49
 class Install extends Command {
50 50
 
51
-	/** @var SystemConfig */
52
-	private $config;
53
-	/** @var IniGetWrapper  */
54
-	private $iniGetWrapper;
55
-
56
-	public function __construct(SystemConfig $config, IniGetWrapper $iniGetWrapper) {
57
-		parent::__construct();
58
-		$this->config = $config;
59
-		$this->iniGetWrapper = $iniGetWrapper;
60
-	}
61
-
62
-	protected function configure() {
63
-		$this
64
-			->setName('maintenance:install')
65
-			->setDescription('install Nextcloud')
66
-			->addOption('database', null, InputOption::VALUE_REQUIRED, 'Supported database type', 'sqlite')
67
-			->addOption('database-name', null, InputOption::VALUE_REQUIRED, 'Name of the database')
68
-			->addOption('database-host', null, InputOption::VALUE_REQUIRED, 'Hostname of the database', 'localhost')
69
-			->addOption('database-port', null, InputOption::VALUE_REQUIRED, 'Port the database is listening on')
70
-			->addOption('database-user', null, InputOption::VALUE_REQUIRED, 'User name to connect to the database')
71
-			->addOption('database-pass', null, InputOption::VALUE_OPTIONAL, 'Password of the database user', null)
72
-			->addOption('database-table-space', null, InputOption::VALUE_OPTIONAL, 'Table space of the database (oci only)', null)
73
-			->addOption('admin-user', null, InputOption::VALUE_REQUIRED, 'User name of the admin account', 'admin')
74
-			->addOption('admin-pass', null, InputOption::VALUE_REQUIRED, 'Password of the admin account')
75
-			->addOption('admin-email', null, InputOption::VALUE_OPTIONAL, 'E-Mail of the admin account')
76
-			->addOption('data-dir', null, InputOption::VALUE_REQUIRED, 'Path to data directory', \OC::$SERVERROOT."/data");
77
-	}
78
-
79
-	protected function execute(InputInterface $input, OutputInterface $output): int {
80
-
81
-		// validate the environment
82
-		$server = \OC::$server;
83
-		$setupHelper = new Setup(
84
-			$this->config,
85
-			$this->iniGetWrapper,
86
-			$server->getL10N('lib'),
87
-			$server->query(Defaults::class),
88
-			$server->getLogger(),
89
-			$server->getSecureRandom(),
90
-			\OC::$server->query(Installer::class)
91
-		);
92
-		$sysInfo = $setupHelper->getSystemInfo(true);
93
-		$errors = $sysInfo['errors'];
94
-		if (count($errors) > 0) {
95
-			$this->printErrors($output, $errors);
96
-
97
-			// ignore the OS X setup warning
98
-			if (count($errors) !== 1 ||
99
-				(string)$errors[0]['error'] !== 'Mac OS X is not supported and Nextcloud will not work properly on this platform. Use it at your own risk! ') {
100
-				return 1;
101
-			}
102
-		}
103
-
104
-		// validate user input
105
-		$options = $this->validateInput($input, $output, array_keys($sysInfo['databases']));
106
-
107
-		// perform installation
108
-		$errors = $setupHelper->install($options);
109
-		if (count($errors) > 0) {
110
-			$this->printErrors($output, $errors);
111
-			return 1;
112
-		}
113
-		$output->writeln("Nextcloud was successfully installed");
114
-		return 0;
115
-	}
116
-
117
-	/**
118
-	 * @param InputInterface $input
119
-	 * @param OutputInterface $output
120
-	 * @param string[] $supportedDatabases
121
-	 * @return array
122
-	 */
123
-	protected function validateInput(InputInterface $input, OutputInterface $output, $supportedDatabases) {
124
-		$db = strtolower($input->getOption('database'));
125
-
126
-		if (!in_array($db, $supportedDatabases)) {
127
-			throw new InvalidArgumentException("Database <$db> is not supported.");
128
-		}
129
-
130
-		$dbUser = $input->getOption('database-user');
131
-		$dbPass = $input->getOption('database-pass');
132
-		$dbName = $input->getOption('database-name');
133
-		$dbPort = $input->getOption('database-port');
134
-		if ($db === 'oci') {
135
-			// an empty hostname needs to be read from the raw parameters
136
-			$dbHost = $input->getParameterOption('--database-host', '');
137
-		} else {
138
-			$dbHost = $input->getOption('database-host');
139
-		}
140
-		if ($dbPort) {
141
-			// Append the port to the host so it is the same as in the config (there is no dbport config)
142
-			$dbHost .= ':' . $dbPort;
143
-		}
144
-		if ($input->hasParameterOption('--database-pass')) {
145
-			$dbPass = (string) $input->getOption('database-pass');
146
-		}
147
-		$adminLogin = $input->getOption('admin-user');
148
-		$adminPassword = $input->getOption('admin-pass');
149
-		$adminEmail = $input->getOption('admin-email');
150
-		$dataDir = $input->getOption('data-dir');
151
-
152
-		if ($db !== 'sqlite') {
153
-			if (is_null($dbUser)) {
154
-				throw new InvalidArgumentException("Database user not provided.");
155
-			}
156
-			if (is_null($dbName)) {
157
-				throw new InvalidArgumentException("Database name not provided.");
158
-			}
159
-			if (is_null($dbPass)) {
160
-				/** @var QuestionHelper $helper */
161
-				$helper = $this->getHelper('question');
162
-				$question = new Question('What is the password to access the database with user <'.$dbUser.'>?');
163
-				$question->setHidden(true);
164
-				$question->setHiddenFallback(false);
165
-				$dbPass = $helper->ask($input, $output, $question);
166
-			}
167
-		}
168
-
169
-		if (is_null($adminPassword)) {
170
-			/** @var QuestionHelper $helper */
171
-			$helper = $this->getHelper('question');
172
-			$question = new Question('What is the password you like to use for the admin account <'.$adminLogin.'>?');
173
-			$question->setHidden(true);
174
-			$question->setHiddenFallback(false);
175
-			$adminPassword = $helper->ask($input, $output, $question);
176
-		}
177
-
178
-		if ($adminEmail !== null && !filter_var($adminEmail, FILTER_VALIDATE_EMAIL)) {
179
-			throw new InvalidArgumentException('Invalid e-mail-address <' . $adminEmail . '> for <' . $adminLogin . '>.');
180
-		}
181
-
182
-		$options = [
183
-			'dbtype' => $db,
184
-			'dbuser' => $dbUser,
185
-			'dbpass' => $dbPass,
186
-			'dbname' => $dbName,
187
-			'dbhost' => $dbHost,
188
-			'adminlogin' => $adminLogin,
189
-			'adminpass' => $adminPassword,
190
-			'adminemail' => $adminEmail,
191
-			'directory' => $dataDir
192
-		];
193
-		if ($db === 'oci') {
194
-			$options['dbtablespace'] = $input->getParameterOption('--database-table-space', '');
195
-		}
196
-		return $options;
197
-	}
198
-
199
-	/**
200
-	 * @param OutputInterface $output
201
-	 * @param $errors
202
-	 */
203
-	protected function printErrors(OutputInterface $output, $errors) {
204
-		foreach ($errors as $error) {
205
-			if (is_array($error)) {
206
-				$output->writeln('<error>' . $error['error'] . '</error>');
207
-				if (isset($error['hint']) && !empty($error['hint'])) {
208
-					$output->writeln('<info> -> ' . $error['hint'] . '</info>');
209
-				}
210
-				if (isset($error['exception']) && $error['exception'] instanceof Throwable) {
211
-					$this->printThrowable($output, $error['exception']);
212
-				}
213
-			} else {
214
-				$output->writeln('<error>' . $error . '</error>');
215
-			}
216
-		}
217
-	}
218
-
219
-	private function printThrowable(OutputInterface $output, Throwable $t): void {
220
-		$output->write('<info>Trace: ' . $t->getTraceAsString() . '</info>');
221
-		$output->writeln('');
222
-		if ($t->getPrevious() !== null) {
223
-			$output->writeln('');
224
-			$output->writeln('<info>Previous: ' . get_class($t->getPrevious()) . ': ' . $t->getPrevious()->getMessage() . '</info>');
225
-			$this->printThrowable($output, $t->getPrevious());
226
-		}
227
-	}
51
+    /** @var SystemConfig */
52
+    private $config;
53
+    /** @var IniGetWrapper  */
54
+    private $iniGetWrapper;
55
+
56
+    public function __construct(SystemConfig $config, IniGetWrapper $iniGetWrapper) {
57
+        parent::__construct();
58
+        $this->config = $config;
59
+        $this->iniGetWrapper = $iniGetWrapper;
60
+    }
61
+
62
+    protected function configure() {
63
+        $this
64
+            ->setName('maintenance:install')
65
+            ->setDescription('install Nextcloud')
66
+            ->addOption('database', null, InputOption::VALUE_REQUIRED, 'Supported database type', 'sqlite')
67
+            ->addOption('database-name', null, InputOption::VALUE_REQUIRED, 'Name of the database')
68
+            ->addOption('database-host', null, InputOption::VALUE_REQUIRED, 'Hostname of the database', 'localhost')
69
+            ->addOption('database-port', null, InputOption::VALUE_REQUIRED, 'Port the database is listening on')
70
+            ->addOption('database-user', null, InputOption::VALUE_REQUIRED, 'User name to connect to the database')
71
+            ->addOption('database-pass', null, InputOption::VALUE_OPTIONAL, 'Password of the database user', null)
72
+            ->addOption('database-table-space', null, InputOption::VALUE_OPTIONAL, 'Table space of the database (oci only)', null)
73
+            ->addOption('admin-user', null, InputOption::VALUE_REQUIRED, 'User name of the admin account', 'admin')
74
+            ->addOption('admin-pass', null, InputOption::VALUE_REQUIRED, 'Password of the admin account')
75
+            ->addOption('admin-email', null, InputOption::VALUE_OPTIONAL, 'E-Mail of the admin account')
76
+            ->addOption('data-dir', null, InputOption::VALUE_REQUIRED, 'Path to data directory', \OC::$SERVERROOT."/data");
77
+    }
78
+
79
+    protected function execute(InputInterface $input, OutputInterface $output): int {
80
+
81
+        // validate the environment
82
+        $server = \OC::$server;
83
+        $setupHelper = new Setup(
84
+            $this->config,
85
+            $this->iniGetWrapper,
86
+            $server->getL10N('lib'),
87
+            $server->query(Defaults::class),
88
+            $server->getLogger(),
89
+            $server->getSecureRandom(),
90
+            \OC::$server->query(Installer::class)
91
+        );
92
+        $sysInfo = $setupHelper->getSystemInfo(true);
93
+        $errors = $sysInfo['errors'];
94
+        if (count($errors) > 0) {
95
+            $this->printErrors($output, $errors);
96
+
97
+            // ignore the OS X setup warning
98
+            if (count($errors) !== 1 ||
99
+                (string)$errors[0]['error'] !== 'Mac OS X is not supported and Nextcloud will not work properly on this platform. Use it at your own risk! ') {
100
+                return 1;
101
+            }
102
+        }
103
+
104
+        // validate user input
105
+        $options = $this->validateInput($input, $output, array_keys($sysInfo['databases']));
106
+
107
+        // perform installation
108
+        $errors = $setupHelper->install($options);
109
+        if (count($errors) > 0) {
110
+            $this->printErrors($output, $errors);
111
+            return 1;
112
+        }
113
+        $output->writeln("Nextcloud was successfully installed");
114
+        return 0;
115
+    }
116
+
117
+    /**
118
+     * @param InputInterface $input
119
+     * @param OutputInterface $output
120
+     * @param string[] $supportedDatabases
121
+     * @return array
122
+     */
123
+    protected function validateInput(InputInterface $input, OutputInterface $output, $supportedDatabases) {
124
+        $db = strtolower($input->getOption('database'));
125
+
126
+        if (!in_array($db, $supportedDatabases)) {
127
+            throw new InvalidArgumentException("Database <$db> is not supported.");
128
+        }
129
+
130
+        $dbUser = $input->getOption('database-user');
131
+        $dbPass = $input->getOption('database-pass');
132
+        $dbName = $input->getOption('database-name');
133
+        $dbPort = $input->getOption('database-port');
134
+        if ($db === 'oci') {
135
+            // an empty hostname needs to be read from the raw parameters
136
+            $dbHost = $input->getParameterOption('--database-host', '');
137
+        } else {
138
+            $dbHost = $input->getOption('database-host');
139
+        }
140
+        if ($dbPort) {
141
+            // Append the port to the host so it is the same as in the config (there is no dbport config)
142
+            $dbHost .= ':' . $dbPort;
143
+        }
144
+        if ($input->hasParameterOption('--database-pass')) {
145
+            $dbPass = (string) $input->getOption('database-pass');
146
+        }
147
+        $adminLogin = $input->getOption('admin-user');
148
+        $adminPassword = $input->getOption('admin-pass');
149
+        $adminEmail = $input->getOption('admin-email');
150
+        $dataDir = $input->getOption('data-dir');
151
+
152
+        if ($db !== 'sqlite') {
153
+            if (is_null($dbUser)) {
154
+                throw new InvalidArgumentException("Database user not provided.");
155
+            }
156
+            if (is_null($dbName)) {
157
+                throw new InvalidArgumentException("Database name not provided.");
158
+            }
159
+            if (is_null($dbPass)) {
160
+                /** @var QuestionHelper $helper */
161
+                $helper = $this->getHelper('question');
162
+                $question = new Question('What is the password to access the database with user <'.$dbUser.'>?');
163
+                $question->setHidden(true);
164
+                $question->setHiddenFallback(false);
165
+                $dbPass = $helper->ask($input, $output, $question);
166
+            }
167
+        }
168
+
169
+        if (is_null($adminPassword)) {
170
+            /** @var QuestionHelper $helper */
171
+            $helper = $this->getHelper('question');
172
+            $question = new Question('What is the password you like to use for the admin account <'.$adminLogin.'>?');
173
+            $question->setHidden(true);
174
+            $question->setHiddenFallback(false);
175
+            $adminPassword = $helper->ask($input, $output, $question);
176
+        }
177
+
178
+        if ($adminEmail !== null && !filter_var($adminEmail, FILTER_VALIDATE_EMAIL)) {
179
+            throw new InvalidArgumentException('Invalid e-mail-address <' . $adminEmail . '> for <' . $adminLogin . '>.');
180
+        }
181
+
182
+        $options = [
183
+            'dbtype' => $db,
184
+            'dbuser' => $dbUser,
185
+            'dbpass' => $dbPass,
186
+            'dbname' => $dbName,
187
+            'dbhost' => $dbHost,
188
+            'adminlogin' => $adminLogin,
189
+            'adminpass' => $adminPassword,
190
+            'adminemail' => $adminEmail,
191
+            'directory' => $dataDir
192
+        ];
193
+        if ($db === 'oci') {
194
+            $options['dbtablespace'] = $input->getParameterOption('--database-table-space', '');
195
+        }
196
+        return $options;
197
+    }
198
+
199
+    /**
200
+     * @param OutputInterface $output
201
+     * @param $errors
202
+     */
203
+    protected function printErrors(OutputInterface $output, $errors) {
204
+        foreach ($errors as $error) {
205
+            if (is_array($error)) {
206
+                $output->writeln('<error>' . $error['error'] . '</error>');
207
+                if (isset($error['hint']) && !empty($error['hint'])) {
208
+                    $output->writeln('<info> -> ' . $error['hint'] . '</info>');
209
+                }
210
+                if (isset($error['exception']) && $error['exception'] instanceof Throwable) {
211
+                    $this->printThrowable($output, $error['exception']);
212
+                }
213
+            } else {
214
+                $output->writeln('<error>' . $error . '</error>');
215
+            }
216
+        }
217
+    }
218
+
219
+    private function printThrowable(OutputInterface $output, Throwable $t): void {
220
+        $output->write('<info>Trace: ' . $t->getTraceAsString() . '</info>');
221
+        $output->writeln('');
222
+        if ($t->getPrevious() !== null) {
223
+            $output->writeln('');
224
+            $output->writeln('<info>Previous: ' . get_class($t->getPrevious()) . ': ' . $t->getPrevious()->getMessage() . '</info>');
225
+            $this->printThrowable($output, $t->getPrevious());
226
+        }
227
+    }
228 228
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 
97 97
 			// ignore the OS X setup warning
98 98
 			if (count($errors) !== 1 ||
99
-				(string)$errors[0]['error'] !== 'Mac OS X is not supported and Nextcloud will not work properly on this platform. Use it at your own risk! ') {
99
+				(string) $errors[0]['error'] !== 'Mac OS X is not supported and Nextcloud will not work properly on this platform. Use it at your own risk! ') {
100 100
 				return 1;
101 101
 			}
102 102
 		}
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
 		}
140 140
 		if ($dbPort) {
141 141
 			// Append the port to the host so it is the same as in the config (there is no dbport config)
142
-			$dbHost .= ':' . $dbPort;
142
+			$dbHost .= ':'.$dbPort;
143 143
 		}
144 144
 		if ($input->hasParameterOption('--database-pass')) {
145 145
 			$dbPass = (string) $input->getOption('database-pass');
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
 		}
177 177
 
178 178
 		if ($adminEmail !== null && !filter_var($adminEmail, FILTER_VALIDATE_EMAIL)) {
179
-			throw new InvalidArgumentException('Invalid e-mail-address <' . $adminEmail . '> for <' . $adminLogin . '>.');
179
+			throw new InvalidArgumentException('Invalid e-mail-address <'.$adminEmail.'> for <'.$adminLogin.'>.');
180 180
 		}
181 181
 
182 182
 		$options = [
@@ -203,25 +203,25 @@  discard block
 block discarded – undo
203 203
 	protected function printErrors(OutputInterface $output, $errors) {
204 204
 		foreach ($errors as $error) {
205 205
 			if (is_array($error)) {
206
-				$output->writeln('<error>' . $error['error'] . '</error>');
206
+				$output->writeln('<error>'.$error['error'].'</error>');
207 207
 				if (isset($error['hint']) && !empty($error['hint'])) {
208
-					$output->writeln('<info> -> ' . $error['hint'] . '</info>');
208
+					$output->writeln('<info> -> '.$error['hint'].'</info>');
209 209
 				}
210 210
 				if (isset($error['exception']) && $error['exception'] instanceof Throwable) {
211 211
 					$this->printThrowable($output, $error['exception']);
212 212
 				}
213 213
 			} else {
214
-				$output->writeln('<error>' . $error . '</error>');
214
+				$output->writeln('<error>'.$error.'</error>');
215 215
 			}
216 216
 		}
217 217
 	}
218 218
 
219 219
 	private function printThrowable(OutputInterface $output, Throwable $t): void {
220
-		$output->write('<info>Trace: ' . $t->getTraceAsString() . '</info>');
220
+		$output->write('<info>Trace: '.$t->getTraceAsString().'</info>');
221 221
 		$output->writeln('');
222 222
 		if ($t->getPrevious() !== null) {
223 223
 			$output->writeln('');
224
-			$output->writeln('<info>Previous: ' . get_class($t->getPrevious()) . ': ' . $t->getPrevious()->getMessage() . '</info>');
224
+			$output->writeln('<info>Previous: '.get_class($t->getPrevious()).': '.$t->getPrevious()->getMessage().'</info>');
225 225
 			$this->printThrowable($output, $t->getPrevious());
226 226
 		}
227 227
 	}
Please login to merge, or discard this patch.
lib/private/Setup/PostgreSQL.php 1 patch
Indentation   +131 added lines, -131 removed lines patch added patch discarded remove patch
@@ -34,135 +34,135 @@
 block discarded – undo
34 34
 use OCP\IDBConnection;
35 35
 
36 36
 class PostgreSQL extends AbstractDatabase {
37
-	public $dbprettyname = 'PostgreSQL';
38
-
39
-	/**
40
-	 * @param string $username
41
-	 * @throws \OC\DatabaseSetupException
42
-	 */
43
-	public function setupDatabase($username) {
44
-		try {
45
-			$connection = $this->connect([
46
-				'dbname' => 'postgres'
47
-			]);
48
-			//check for roles creation rights in postgresql
49
-			$builder = $connection->getQueryBuilder();
50
-			$builder->automaticTablePrefix(false);
51
-			$query = $builder
52
-				->select('rolname')
53
-				->from('pg_roles')
54
-				->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE')))
55
-				->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser)));
56
-
57
-			try {
58
-				$result = $query->execute();
59
-				$canCreateRoles = $result->rowCount() > 0;
60
-			} catch (DatabaseException $e) {
61
-				$canCreateRoles = false;
62
-			}
63
-
64
-			if ($canCreateRoles) {
65
-				//use the admin login data for the new database user
66
-
67
-				//add prefix to the postgresql user name to prevent collisions
68
-				$this->dbUser = 'oc_' . strtolower($username);
69
-				//create a new password so we don't need to store the admin config in the config file
70
-				$this->dbPassword = \OC::$server->getSecureRandom()->generate(30, \OCP\Security\ISecureRandom::CHAR_LOWER . \OCP\Security\ISecureRandom::CHAR_DIGITS);
71
-
72
-				$this->createDBUser($connection);
73
-			}
74
-
75
-			$this->config->setValues([
76
-				'dbuser' => $this->dbUser,
77
-				'dbpassword' => $this->dbPassword,
78
-			]);
79
-
80
-			//create the database
81
-			$this->createDatabase($connection);
82
-			// the connection to dbname=postgres is not needed anymore
83
-			$connection->close();
84
-		} catch (\Exception $e) {
85
-			$this->logger->logException($e);
86
-			$this->logger->warning('Error trying to connect as "postgres", assuming database is setup and tables need to be created');
87
-			$this->config->setValues([
88
-				'dbuser' => $this->dbUser,
89
-				'dbpassword' => $this->dbPassword,
90
-			]);
91
-		}
92
-
93
-		// connect to the database (dbname=$this->dbname) and check if it needs to be filled
94
-		$this->dbUser = $this->config->getValue('dbuser');
95
-		$this->dbPassword = $this->config->getValue('dbpassword');
96
-		$connection = $this->connect();
97
-		try {
98
-			$connection->connect();
99
-		} catch (\Exception $e) {
100
-			$this->logger->logException($e);
101
-			throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL username and/or password not valid'),
102
-				$this->trans->t('You need to enter details of an existing account.'), 0, $e);
103
-		}
104
-	}
105
-
106
-	private function createDatabase(IDBConnection $connection) {
107
-		if (!$this->databaseExists($connection)) {
108
-			//The database does not exists... let's create it
109
-			$query = $connection->prepare("CREATE DATABASE " . addslashes($this->dbName) . " OWNER " . addslashes($this->dbUser));
110
-			try {
111
-				$query->execute();
112
-			} catch (DatabaseException $e) {
113
-				$this->logger->error('Error while trying to create database');
114
-				$this->logger->logException($e);
115
-			}
116
-		} else {
117
-			$query = $connection->prepare("REVOKE ALL PRIVILEGES ON DATABASE " . addslashes($this->dbName) . " FROM PUBLIC");
118
-			try {
119
-				$query->execute();
120
-			} catch (DatabaseException $e) {
121
-				$this->logger->error('Error while trying to restrict database permissions');
122
-				$this->logger->logException($e);
123
-			}
124
-		}
125
-	}
126
-
127
-	private function userExists(IDBConnection $connection) {
128
-		$builder = $connection->getQueryBuilder();
129
-		$builder->automaticTablePrefix(false);
130
-		$query = $builder->select('*')
131
-			->from('pg_roles')
132
-			->where($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser)));
133
-		$result = $query->execute();
134
-		return $result->rowCount() > 0;
135
-	}
136
-
137
-	private function databaseExists(IDBConnection $connection) {
138
-		$builder = $connection->getQueryBuilder();
139
-		$builder->automaticTablePrefix(false);
140
-		$query = $builder->select('datname')
141
-			->from('pg_database')
142
-			->where($builder->expr()->eq('datname', $builder->createNamedParameter($this->dbName)));
143
-		$result = $query->execute();
144
-		return $result->rowCount() > 0;
145
-	}
146
-
147
-	private function createDBUser(IDBConnection $connection) {
148
-		$dbUser = $this->dbUser;
149
-		try {
150
-			$i = 1;
151
-			while ($this->userExists($connection)) {
152
-				$i++;
153
-				$this->dbUser = $dbUser . $i;
154
-			}
155
-
156
-			// create the user
157
-			$query = $connection->prepare("CREATE USER " . addslashes($this->dbUser) . " CREATEDB PASSWORD '" . addslashes($this->dbPassword) . "'");
158
-			$query->execute();
159
-			if ($this->databaseExists($connection)) {
160
-				$query = $connection->prepare('GRANT CONNECT ON DATABASE ' . addslashes($this->dbName) . ' TO '.addslashes($this->dbUser));
161
-				$query->execute();
162
-			}
163
-		} catch (DatabaseException $e) {
164
-			$this->logger->error('Error while trying to create database user');
165
-			$this->logger->logException($e);
166
-		}
167
-	}
37
+    public $dbprettyname = 'PostgreSQL';
38
+
39
+    /**
40
+     * @param string $username
41
+     * @throws \OC\DatabaseSetupException
42
+     */
43
+    public function setupDatabase($username) {
44
+        try {
45
+            $connection = $this->connect([
46
+                'dbname' => 'postgres'
47
+            ]);
48
+            //check for roles creation rights in postgresql
49
+            $builder = $connection->getQueryBuilder();
50
+            $builder->automaticTablePrefix(false);
51
+            $query = $builder
52
+                ->select('rolname')
53
+                ->from('pg_roles')
54
+                ->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE')))
55
+                ->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser)));
56
+
57
+            try {
58
+                $result = $query->execute();
59
+                $canCreateRoles = $result->rowCount() > 0;
60
+            } catch (DatabaseException $e) {
61
+                $canCreateRoles = false;
62
+            }
63
+
64
+            if ($canCreateRoles) {
65
+                //use the admin login data for the new database user
66
+
67
+                //add prefix to the postgresql user name to prevent collisions
68
+                $this->dbUser = 'oc_' . strtolower($username);
69
+                //create a new password so we don't need to store the admin config in the config file
70
+                $this->dbPassword = \OC::$server->getSecureRandom()->generate(30, \OCP\Security\ISecureRandom::CHAR_LOWER . \OCP\Security\ISecureRandom::CHAR_DIGITS);
71
+
72
+                $this->createDBUser($connection);
73
+            }
74
+
75
+            $this->config->setValues([
76
+                'dbuser' => $this->dbUser,
77
+                'dbpassword' => $this->dbPassword,
78
+            ]);
79
+
80
+            //create the database
81
+            $this->createDatabase($connection);
82
+            // the connection to dbname=postgres is not needed anymore
83
+            $connection->close();
84
+        } catch (\Exception $e) {
85
+            $this->logger->logException($e);
86
+            $this->logger->warning('Error trying to connect as "postgres", assuming database is setup and tables need to be created');
87
+            $this->config->setValues([
88
+                'dbuser' => $this->dbUser,
89
+                'dbpassword' => $this->dbPassword,
90
+            ]);
91
+        }
92
+
93
+        // connect to the database (dbname=$this->dbname) and check if it needs to be filled
94
+        $this->dbUser = $this->config->getValue('dbuser');
95
+        $this->dbPassword = $this->config->getValue('dbpassword');
96
+        $connection = $this->connect();
97
+        try {
98
+            $connection->connect();
99
+        } catch (\Exception $e) {
100
+            $this->logger->logException($e);
101
+            throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL username and/or password not valid'),
102
+                $this->trans->t('You need to enter details of an existing account.'), 0, $e);
103
+        }
104
+    }
105
+
106
+    private function createDatabase(IDBConnection $connection) {
107
+        if (!$this->databaseExists($connection)) {
108
+            //The database does not exists... let's create it
109
+            $query = $connection->prepare("CREATE DATABASE " . addslashes($this->dbName) . " OWNER " . addslashes($this->dbUser));
110
+            try {
111
+                $query->execute();
112
+            } catch (DatabaseException $e) {
113
+                $this->logger->error('Error while trying to create database');
114
+                $this->logger->logException($e);
115
+            }
116
+        } else {
117
+            $query = $connection->prepare("REVOKE ALL PRIVILEGES ON DATABASE " . addslashes($this->dbName) . " FROM PUBLIC");
118
+            try {
119
+                $query->execute();
120
+            } catch (DatabaseException $e) {
121
+                $this->logger->error('Error while trying to restrict database permissions');
122
+                $this->logger->logException($e);
123
+            }
124
+        }
125
+    }
126
+
127
+    private function userExists(IDBConnection $connection) {
128
+        $builder = $connection->getQueryBuilder();
129
+        $builder->automaticTablePrefix(false);
130
+        $query = $builder->select('*')
131
+            ->from('pg_roles')
132
+            ->where($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser)));
133
+        $result = $query->execute();
134
+        return $result->rowCount() > 0;
135
+    }
136
+
137
+    private function databaseExists(IDBConnection $connection) {
138
+        $builder = $connection->getQueryBuilder();
139
+        $builder->automaticTablePrefix(false);
140
+        $query = $builder->select('datname')
141
+            ->from('pg_database')
142
+            ->where($builder->expr()->eq('datname', $builder->createNamedParameter($this->dbName)));
143
+        $result = $query->execute();
144
+        return $result->rowCount() > 0;
145
+    }
146
+
147
+    private function createDBUser(IDBConnection $connection) {
148
+        $dbUser = $this->dbUser;
149
+        try {
150
+            $i = 1;
151
+            while ($this->userExists($connection)) {
152
+                $i++;
153
+                $this->dbUser = $dbUser . $i;
154
+            }
155
+
156
+            // create the user
157
+            $query = $connection->prepare("CREATE USER " . addslashes($this->dbUser) . " CREATEDB PASSWORD '" . addslashes($this->dbPassword) . "'");
158
+            $query->execute();
159
+            if ($this->databaseExists($connection)) {
160
+                $query = $connection->prepare('GRANT CONNECT ON DATABASE ' . addslashes($this->dbName) . ' TO '.addslashes($this->dbUser));
161
+                $query->execute();
162
+            }
163
+        } catch (DatabaseException $e) {
164
+            $this->logger->error('Error while trying to create database user');
165
+            $this->logger->logException($e);
166
+        }
167
+    }
168 168
 }
Please login to merge, or discard this patch.
lib/private/Setup/OCI.php 2 patches
Indentation   +70 added lines, -70 removed lines patch added patch discarded remove patch
@@ -31,81 +31,81 @@
 block discarded – undo
31 31
 namespace OC\Setup;
32 32
 
33 33
 class OCI extends AbstractDatabase {
34
-	public $dbprettyname = 'Oracle';
34
+    public $dbprettyname = 'Oracle';
35 35
 
36
-	protected $dbtablespace;
36
+    protected $dbtablespace;
37 37
 
38
-	public function initialize($config) {
39
-		parent::initialize($config);
40
-		if (array_key_exists('dbtablespace', $config)) {
41
-			$this->dbtablespace = $config['dbtablespace'];
42
-		} else {
43
-			$this->dbtablespace = 'USERS';
44
-		}
45
-		// allow empty hostname for oracle
46
-		$this->dbHost = $config['dbhost'];
38
+    public function initialize($config) {
39
+        parent::initialize($config);
40
+        if (array_key_exists('dbtablespace', $config)) {
41
+            $this->dbtablespace = $config['dbtablespace'];
42
+        } else {
43
+            $this->dbtablespace = 'USERS';
44
+        }
45
+        // allow empty hostname for oracle
46
+        $this->dbHost = $config['dbhost'];
47 47
 
48
-		$this->config->setValues([
49
-			'dbhost' => $this->dbHost,
50
-			'dbtablespace' => $this->dbtablespace,
51
-		]);
52
-	}
48
+        $this->config->setValues([
49
+            'dbhost' => $this->dbHost,
50
+            'dbtablespace' => $this->dbtablespace,
51
+        ]);
52
+    }
53 53
 
54
-	public function validate($config) {
55
-		$errors = [];
56
-		if (empty($config['dbuser']) && empty($config['dbname'])) {
57
-			$errors[] = $this->trans->t("%s enter the database username and name.", [$this->dbprettyname]);
58
-		} elseif (empty($config['dbuser'])) {
59
-			$errors[] = $this->trans->t("%s enter the database username.", [$this->dbprettyname]);
60
-		} elseif (empty($config['dbname'])) {
61
-			$errors[] = $this->trans->t("%s enter the database name.", [$this->dbprettyname]);
62
-		}
63
-		return $errors;
64
-	}
54
+    public function validate($config) {
55
+        $errors = [];
56
+        if (empty($config['dbuser']) && empty($config['dbname'])) {
57
+            $errors[] = $this->trans->t("%s enter the database username and name.", [$this->dbprettyname]);
58
+        } elseif (empty($config['dbuser'])) {
59
+            $errors[] = $this->trans->t("%s enter the database username.", [$this->dbprettyname]);
60
+        } elseif (empty($config['dbname'])) {
61
+            $errors[] = $this->trans->t("%s enter the database name.", [$this->dbprettyname]);
62
+        }
63
+        return $errors;
64
+    }
65 65
 
66
-	public function setupDatabase($username) {
67
-		try {
68
-			$this->connect();
69
-		} catch (\Exception $e) {
70
-			$errorMessage = $this->getLastError();
71
-			if ($errorMessage) {
72
-				throw new \OC\DatabaseSetupException($this->trans->t('Oracle connection could not be established'),
73
-					$errorMessage . ' Check environment: ORACLE_HOME=' . getenv('ORACLE_HOME')
74
-					. ' ORACLE_SID=' . getenv('ORACLE_SID')
75
-					. ' LD_LIBRARY_PATH=' . getenv('LD_LIBRARY_PATH')
76
-					. ' NLS_LANG=' . getenv('NLS_LANG')
77
-					. ' tnsnames.ora is ' . (is_readable(getenv('ORACLE_HOME') . '/network/admin/tnsnames.ora') ? '' : 'not ') . 'readable', 0, $e);
78
-			}
79
-			throw new \OC\DatabaseSetupException($this->trans->t('Oracle username and/or password not valid'),
80
-				'Check environment: ORACLE_HOME=' . getenv('ORACLE_HOME')
81
-				. ' ORACLE_SID=' . getenv('ORACLE_SID')
82
-				. ' LD_LIBRARY_PATH=' . getenv('LD_LIBRARY_PATH')
83
-				. ' NLS_LANG=' . getenv('NLS_LANG')
84
-				. ' tnsnames.ora is ' . (is_readable(getenv('ORACLE_HOME') . '/network/admin/tnsnames.ora') ? '' : 'not ') . 'readable', 0, $e);
85
-		}
66
+    public function setupDatabase($username) {
67
+        try {
68
+            $this->connect();
69
+        } catch (\Exception $e) {
70
+            $errorMessage = $this->getLastError();
71
+            if ($errorMessage) {
72
+                throw new \OC\DatabaseSetupException($this->trans->t('Oracle connection could not be established'),
73
+                    $errorMessage . ' Check environment: ORACLE_HOME=' . getenv('ORACLE_HOME')
74
+                    . ' ORACLE_SID=' . getenv('ORACLE_SID')
75
+                    . ' LD_LIBRARY_PATH=' . getenv('LD_LIBRARY_PATH')
76
+                    . ' NLS_LANG=' . getenv('NLS_LANG')
77
+                    . ' tnsnames.ora is ' . (is_readable(getenv('ORACLE_HOME') . '/network/admin/tnsnames.ora') ? '' : 'not ') . 'readable', 0, $e);
78
+            }
79
+            throw new \OC\DatabaseSetupException($this->trans->t('Oracle username and/or password not valid'),
80
+                'Check environment: ORACLE_HOME=' . getenv('ORACLE_HOME')
81
+                . ' ORACLE_SID=' . getenv('ORACLE_SID')
82
+                . ' LD_LIBRARY_PATH=' . getenv('LD_LIBRARY_PATH')
83
+                . ' NLS_LANG=' . getenv('NLS_LANG')
84
+                . ' tnsnames.ora is ' . (is_readable(getenv('ORACLE_HOME') . '/network/admin/tnsnames.ora') ? '' : 'not ') . 'readable', 0, $e);
85
+        }
86 86
 
87
-		$this->config->setValues([
88
-			'dbuser' => $this->dbUser,
89
-			'dbname' => $this->dbName,
90
-			'dbpassword' => $this->dbPassword,
91
-		]);
92
-	}
87
+        $this->config->setValues([
88
+            'dbuser' => $this->dbUser,
89
+            'dbname' => $this->dbName,
90
+            'dbpassword' => $this->dbPassword,
91
+        ]);
92
+    }
93 93
 
94
-	/**
95
-	 * @param resource $connection
96
-	 * @return string
97
-	 */
98
-	protected function getLastError($connection = null) {
99
-		if ($connection) {
100
-			$error = oci_error($connection);
101
-		} else {
102
-			$error = oci_error();
103
-		}
104
-		foreach (['message', 'code'] as $key) {
105
-			if (isset($error[$key])) {
106
-				return $error[$key];
107
-			}
108
-		}
109
-		return '';
110
-	}
94
+    /**
95
+     * @param resource $connection
96
+     * @return string
97
+     */
98
+    protected function getLastError($connection = null) {
99
+        if ($connection) {
100
+            $error = oci_error($connection);
101
+        } else {
102
+            $error = oci_error();
103
+        }
104
+        foreach (['message', 'code'] as $key) {
105
+            if (isset($error[$key])) {
106
+                return $error[$key];
107
+            }
108
+        }
109
+        return '';
110
+    }
111 111
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -70,18 +70,18 @@
 block discarded – undo
70 70
 			$errorMessage = $this->getLastError();
71 71
 			if ($errorMessage) {
72 72
 				throw new \OC\DatabaseSetupException($this->trans->t('Oracle connection could not be established'),
73
-					$errorMessage . ' Check environment: ORACLE_HOME=' . getenv('ORACLE_HOME')
74
-					. ' ORACLE_SID=' . getenv('ORACLE_SID')
75
-					. ' LD_LIBRARY_PATH=' . getenv('LD_LIBRARY_PATH')
76
-					. ' NLS_LANG=' . getenv('NLS_LANG')
77
-					. ' tnsnames.ora is ' . (is_readable(getenv('ORACLE_HOME') . '/network/admin/tnsnames.ora') ? '' : 'not ') . 'readable', 0, $e);
73
+					$errorMessage.' Check environment: ORACLE_HOME='.getenv('ORACLE_HOME')
74
+					. ' ORACLE_SID='.getenv('ORACLE_SID')
75
+					. ' LD_LIBRARY_PATH='.getenv('LD_LIBRARY_PATH')
76
+					. ' NLS_LANG='.getenv('NLS_LANG')
77
+					. ' tnsnames.ora is '.(is_readable(getenv('ORACLE_HOME').'/network/admin/tnsnames.ora') ? '' : 'not ').'readable', 0, $e);
78 78
 			}
79 79
 			throw new \OC\DatabaseSetupException($this->trans->t('Oracle username and/or password not valid'),
80
-				'Check environment: ORACLE_HOME=' . getenv('ORACLE_HOME')
81
-				. ' ORACLE_SID=' . getenv('ORACLE_SID')
82
-				. ' LD_LIBRARY_PATH=' . getenv('LD_LIBRARY_PATH')
83
-				. ' NLS_LANG=' . getenv('NLS_LANG')
84
-				. ' tnsnames.ora is ' . (is_readable(getenv('ORACLE_HOME') . '/network/admin/tnsnames.ora') ? '' : 'not ') . 'readable', 0, $e);
80
+				'Check environment: ORACLE_HOME='.getenv('ORACLE_HOME')
81
+				. ' ORACLE_SID='.getenv('ORACLE_SID')
82
+				. ' LD_LIBRARY_PATH='.getenv('LD_LIBRARY_PATH')
83
+				. ' NLS_LANG='.getenv('NLS_LANG')
84
+				. ' tnsnames.ora is '.(is_readable(getenv('ORACLE_HOME').'/network/admin/tnsnames.ora') ? '' : 'not ').'readable', 0, $e);
85 85
 		}
86 86
 
87 87
 		$this->config->setValues([
Please login to merge, or discard this patch.
lib/private/Setup/MySQL.php 1 patch
Indentation   +156 added lines, -156 removed lines patch added patch discarded remove patch
@@ -37,160 +37,160 @@
 block discarded – undo
37 37
 use Doctrine\DBAL\Platforms\MySQL80Platform;
38 38
 
39 39
 class MySQL extends AbstractDatabase {
40
-	public $dbprettyname = 'MySQL/MariaDB';
41
-
42
-	public function setupDatabase($username) {
43
-		//check if the database user has admin right
44
-		$connection = $this->connect(['dbname' => null]);
45
-
46
-		// detect mb4
47
-		$tools = new MySqlTools();
48
-		if ($tools->supports4ByteCharset($connection)) {
49
-			$this->config->setValue('mysql.utf8mb4', true);
50
-			$connection = $this->connect(['dbname' => null]);
51
-		}
52
-
53
-		$this->createSpecificUser($username, $connection);
54
-
55
-		//create the database
56
-		$this->createDatabase($connection);
57
-
58
-		//fill the database if needed
59
-		$query = 'select count(*) from information_schema.tables where table_schema=? AND table_name = ?';
60
-		$connection->executeQuery($query, [$this->dbName, $this->tablePrefix.'users']);
61
-
62
-		$connection->close();
63
-		$connection = $this->connect();
64
-		try {
65
-			$connection->connect();
66
-		} catch (\Exception $e) {
67
-			$this->logger->logException($e);
68
-			throw new \OC\DatabaseSetupException($this->trans->t('MySQL username and/or password not valid'),
69
-				$this->trans->t('You need to enter details of an existing account.'), 0, $e);
70
-		}
71
-	}
72
-
73
-	/**
74
-	 * @param \OC\DB\Connection $connection
75
-	 */
76
-	private function createDatabase($connection) {
77
-		try {
78
-			$name = $this->dbName;
79
-			$user = $this->dbUser;
80
-			//we can't use OC_DB functions here because we need to connect as the administrative user.
81
-			$characterSet = $this->config->getValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
82
-			$query = "CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET $characterSet COLLATE ${characterSet}_bin;";
83
-			$connection->executeUpdate($query);
84
-		} catch (\Exception $ex) {
85
-			$this->logger->logException($ex, [
86
-				'message' => 'Database creation failed.',
87
-				'level' => ILogger::ERROR,
88
-				'app' => 'mysql.setup',
89
-			]);
90
-			return;
91
-		}
92
-
93
-		try {
94
-			//this query will fail if there aren't the right permissions, ignore the error
95
-			$query = "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `$name` . * TO '$user'";
96
-			$connection->executeUpdate($query);
97
-		} catch (\Exception $ex) {
98
-			$this->logger->logException($ex, [
99
-				'message' => 'Could not automatically grant privileges, this can be ignored if database user already had privileges.',
100
-				'level' => ILogger::DEBUG,
101
-				'app' => 'mysql.setup',
102
-			]);
103
-		}
104
-	}
105
-
106
-	/**
107
-	 * @param IDBConnection $connection
108
-	 * @throws \OC\DatabaseSetupException
109
-	 */
110
-	private function createDBUser($connection) {
111
-		try {
112
-			$name = $this->dbUser;
113
-			$password = $this->dbPassword;
114
-			// we need to create 2 accounts, one for global use and one for local user. if we don't specify the local one,
115
-			// the anonymous user would take precedence when there is one.
116
-
117
-			if ($connection->getDatabasePlatform() instanceof Mysql80Platform) {
118
-				$query = "CREATE USER '$name'@'localhost' IDENTIFIED WITH mysql_native_password BY '$password'";
119
-				$connection->executeUpdate($query);
120
-				$query = "CREATE USER '$name'@'%' IDENTIFIED WITH mysql_native_password BY '$password'";
121
-				$connection->executeUpdate($query);
122
-			} else {
123
-				$query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'";
124
-				$connection->executeUpdate($query);
125
-				$query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'";
126
-				$connection->executeUpdate($query);
127
-			}
128
-		} catch (\Exception $ex) {
129
-			$this->logger->logException($ex, [
130
-				'message' => 'Database user creation failed.',
131
-				'level' => ILogger::ERROR,
132
-				'app' => 'mysql.setup',
133
-			]);
134
-		}
135
-	}
136
-
137
-	/**
138
-	 * @param $username
139
-	 * @param IDBConnection $connection
140
-	 * @return array
141
-	 */
142
-	private function createSpecificUser($username, $connection) {
143
-		try {
144
-			//user already specified in config
145
-			$oldUser = $this->config->getValue('dbuser', false);
146
-
147
-			//we don't have a dbuser specified in config
148
-			if ($this->dbUser !== $oldUser) {
149
-				//add prefix to the admin username to prevent collisions
150
-				$adminUser = substr('oc_' . $username, 0, 16);
151
-
152
-				$i = 1;
153
-				while (true) {
154
-					//this should be enough to check for admin rights in mysql
155
-					$query = 'SELECT user FROM mysql.user WHERE user=?';
156
-					$result = $connection->executeQuery($query, [$adminUser]);
157
-
158
-					//current dbuser has admin rights
159
-					if ($result) {
160
-						$data = $result->fetchAll();
161
-						//new dbuser does not exist
162
-						if (count($data) === 0) {
163
-							//use the admin login data for the new database user
164
-							$this->dbUser = $adminUser;
165
-
166
-							//create a random password so we don't need to store the admin password in the config file
167
-							$this->dbPassword = $this->random->generate(30);
168
-
169
-							$this->createDBUser($connection);
170
-
171
-							break;
172
-						} else {
173
-							//repeat with different username
174
-							$length = strlen((string)$i);
175
-							$adminUser = substr('oc_' . $username, 0, 16 - $length) . $i;
176
-							$i++;
177
-						}
178
-					} else {
179
-						break;
180
-					}
181
-				}
182
-			}
183
-		} catch (\Exception $ex) {
184
-			$this->logger->logException($ex, [
185
-				'message' => 'Can not create a new MySQL user, will continue with the provided user.',
186
-				'level' => ILogger::INFO,
187
-				'app' => 'mysql.setup',
188
-			]);
189
-		}
190
-
191
-		$this->config->setValues([
192
-			'dbuser' => $this->dbUser,
193
-			'dbpassword' => $this->dbPassword,
194
-		]);
195
-	}
40
+    public $dbprettyname = 'MySQL/MariaDB';
41
+
42
+    public function setupDatabase($username) {
43
+        //check if the database user has admin right
44
+        $connection = $this->connect(['dbname' => null]);
45
+
46
+        // detect mb4
47
+        $tools = new MySqlTools();
48
+        if ($tools->supports4ByteCharset($connection)) {
49
+            $this->config->setValue('mysql.utf8mb4', true);
50
+            $connection = $this->connect(['dbname' => null]);
51
+        }
52
+
53
+        $this->createSpecificUser($username, $connection);
54
+
55
+        //create the database
56
+        $this->createDatabase($connection);
57
+
58
+        //fill the database if needed
59
+        $query = 'select count(*) from information_schema.tables where table_schema=? AND table_name = ?';
60
+        $connection->executeQuery($query, [$this->dbName, $this->tablePrefix.'users']);
61
+
62
+        $connection->close();
63
+        $connection = $this->connect();
64
+        try {
65
+            $connection->connect();
66
+        } catch (\Exception $e) {
67
+            $this->logger->logException($e);
68
+            throw new \OC\DatabaseSetupException($this->trans->t('MySQL username and/or password not valid'),
69
+                $this->trans->t('You need to enter details of an existing account.'), 0, $e);
70
+        }
71
+    }
72
+
73
+    /**
74
+     * @param \OC\DB\Connection $connection
75
+     */
76
+    private function createDatabase($connection) {
77
+        try {
78
+            $name = $this->dbName;
79
+            $user = $this->dbUser;
80
+            //we can't use OC_DB functions here because we need to connect as the administrative user.
81
+            $characterSet = $this->config->getValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
82
+            $query = "CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET $characterSet COLLATE ${characterSet}_bin;";
83
+            $connection->executeUpdate($query);
84
+        } catch (\Exception $ex) {
85
+            $this->logger->logException($ex, [
86
+                'message' => 'Database creation failed.',
87
+                'level' => ILogger::ERROR,
88
+                'app' => 'mysql.setup',
89
+            ]);
90
+            return;
91
+        }
92
+
93
+        try {
94
+            //this query will fail if there aren't the right permissions, ignore the error
95
+            $query = "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `$name` . * TO '$user'";
96
+            $connection->executeUpdate($query);
97
+        } catch (\Exception $ex) {
98
+            $this->logger->logException($ex, [
99
+                'message' => 'Could not automatically grant privileges, this can be ignored if database user already had privileges.',
100
+                'level' => ILogger::DEBUG,
101
+                'app' => 'mysql.setup',
102
+            ]);
103
+        }
104
+    }
105
+
106
+    /**
107
+     * @param IDBConnection $connection
108
+     * @throws \OC\DatabaseSetupException
109
+     */
110
+    private function createDBUser($connection) {
111
+        try {
112
+            $name = $this->dbUser;
113
+            $password = $this->dbPassword;
114
+            // we need to create 2 accounts, one for global use and one for local user. if we don't specify the local one,
115
+            // the anonymous user would take precedence when there is one.
116
+
117
+            if ($connection->getDatabasePlatform() instanceof Mysql80Platform) {
118
+                $query = "CREATE USER '$name'@'localhost' IDENTIFIED WITH mysql_native_password BY '$password'";
119
+                $connection->executeUpdate($query);
120
+                $query = "CREATE USER '$name'@'%' IDENTIFIED WITH mysql_native_password BY '$password'";
121
+                $connection->executeUpdate($query);
122
+            } else {
123
+                $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'";
124
+                $connection->executeUpdate($query);
125
+                $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'";
126
+                $connection->executeUpdate($query);
127
+            }
128
+        } catch (\Exception $ex) {
129
+            $this->logger->logException($ex, [
130
+                'message' => 'Database user creation failed.',
131
+                'level' => ILogger::ERROR,
132
+                'app' => 'mysql.setup',
133
+            ]);
134
+        }
135
+    }
136
+
137
+    /**
138
+     * @param $username
139
+     * @param IDBConnection $connection
140
+     * @return array
141
+     */
142
+    private function createSpecificUser($username, $connection) {
143
+        try {
144
+            //user already specified in config
145
+            $oldUser = $this->config->getValue('dbuser', false);
146
+
147
+            //we don't have a dbuser specified in config
148
+            if ($this->dbUser !== $oldUser) {
149
+                //add prefix to the admin username to prevent collisions
150
+                $adminUser = substr('oc_' . $username, 0, 16);
151
+
152
+                $i = 1;
153
+                while (true) {
154
+                    //this should be enough to check for admin rights in mysql
155
+                    $query = 'SELECT user FROM mysql.user WHERE user=?';
156
+                    $result = $connection->executeQuery($query, [$adminUser]);
157
+
158
+                    //current dbuser has admin rights
159
+                    if ($result) {
160
+                        $data = $result->fetchAll();
161
+                        //new dbuser does not exist
162
+                        if (count($data) === 0) {
163
+                            //use the admin login data for the new database user
164
+                            $this->dbUser = $adminUser;
165
+
166
+                            //create a random password so we don't need to store the admin password in the config file
167
+                            $this->dbPassword = $this->random->generate(30);
168
+
169
+                            $this->createDBUser($connection);
170
+
171
+                            break;
172
+                        } else {
173
+                            //repeat with different username
174
+                            $length = strlen((string)$i);
175
+                            $adminUser = substr('oc_' . $username, 0, 16 - $length) . $i;
176
+                            $i++;
177
+                        }
178
+                    } else {
179
+                        break;
180
+                    }
181
+                }
182
+            }
183
+        } catch (\Exception $ex) {
184
+            $this->logger->logException($ex, [
185
+                'message' => 'Can not create a new MySQL user, will continue with the provided user.',
186
+                'level' => ILogger::INFO,
187
+                'app' => 'mysql.setup',
188
+            ]);
189
+        }
190
+
191
+        $this->config->setValues([
192
+            'dbuser' => $this->dbUser,
193
+            'dbpassword' => $this->dbPassword,
194
+        ]);
195
+    }
196 196
 }
Please login to merge, or discard this patch.
lib/private/Setup.php 2 patches
Indentation   +550 added lines, -550 removed lines patch added patch discarded remove patch
@@ -64,554 +64,554 @@
 block discarded – undo
64 64
 use OCP\Security\ISecureRandom;
65 65
 
66 66
 class Setup {
67
-	/** @var SystemConfig */
68
-	protected $config;
69
-	/** @var IniGetWrapper */
70
-	protected $iniWrapper;
71
-	/** @var IL10N */
72
-	protected $l10n;
73
-	/** @var Defaults */
74
-	protected $defaults;
75
-	/** @var ILogger */
76
-	protected $logger;
77
-	/** @var ISecureRandom */
78
-	protected $random;
79
-	/** @var Installer */
80
-	protected $installer;
81
-
82
-	/**
83
-	 * @param SystemConfig $config
84
-	 * @param IniGetWrapper $iniWrapper
85
-	 * @param IL10N $l10n
86
-	 * @param Defaults $defaults
87
-	 * @param ILogger $logger
88
-	 * @param ISecureRandom $random
89
-	 * @param Installer $installer
90
-	 */
91
-	public function __construct(
92
-		SystemConfig $config,
93
-		IniGetWrapper $iniWrapper,
94
-		IL10N $l10n,
95
-		Defaults $defaults,
96
-		ILogger $logger,
97
-		ISecureRandom $random,
98
-		Installer $installer
99
-	) {
100
-		$this->config = $config;
101
-		$this->iniWrapper = $iniWrapper;
102
-		$this->l10n = $l10n;
103
-		$this->defaults = $defaults;
104
-		$this->logger = $logger;
105
-		$this->random = $random;
106
-		$this->installer = $installer;
107
-	}
108
-
109
-	protected static $dbSetupClasses = [
110
-		'mysql' => \OC\Setup\MySQL::class,
111
-		'pgsql' => \OC\Setup\PostgreSQL::class,
112
-		'oci' => \OC\Setup\OCI::class,
113
-		'sqlite' => \OC\Setup\Sqlite::class,
114
-		'sqlite3' => \OC\Setup\Sqlite::class,
115
-	];
116
-
117
-	/**
118
-	 * Wrapper around the "class_exists" PHP function to be able to mock it
119
-	 *
120
-	 * @param string $name
121
-	 * @return bool
122
-	 */
123
-	protected function class_exists($name) {
124
-		return class_exists($name);
125
-	}
126
-
127
-	/**
128
-	 * Wrapper around the "is_callable" PHP function to be able to mock it
129
-	 *
130
-	 * @param string $name
131
-	 * @return bool
132
-	 */
133
-	protected function is_callable($name) {
134
-		return is_callable($name);
135
-	}
136
-
137
-	/**
138
-	 * Wrapper around \PDO::getAvailableDrivers
139
-	 *
140
-	 * @return array
141
-	 */
142
-	protected function getAvailableDbDriversForPdo() {
143
-		return \PDO::getAvailableDrivers();
144
-	}
145
-
146
-	/**
147
-	 * Get the available and supported databases of this instance
148
-	 *
149
-	 * @param bool $allowAllDatabases
150
-	 * @return array
151
-	 * @throws Exception
152
-	 */
153
-	public function getSupportedDatabases($allowAllDatabases = false) {
154
-		$availableDatabases = [
155
-			'sqlite' => [
156
-				'type' => 'pdo',
157
-				'call' => 'sqlite',
158
-				'name' => 'SQLite',
159
-			],
160
-			'mysql' => [
161
-				'type' => 'pdo',
162
-				'call' => 'mysql',
163
-				'name' => 'MySQL/MariaDB',
164
-			],
165
-			'pgsql' => [
166
-				'type' => 'pdo',
167
-				'call' => 'pgsql',
168
-				'name' => 'PostgreSQL',
169
-			],
170
-			'oci' => [
171
-				'type' => 'function',
172
-				'call' => 'oci_connect',
173
-				'name' => 'Oracle',
174
-			],
175
-		];
176
-		if ($allowAllDatabases) {
177
-			$configuredDatabases = array_keys($availableDatabases);
178
-		} else {
179
-			$configuredDatabases = $this->config->getValue('supportedDatabases',
180
-				['sqlite', 'mysql', 'pgsql']);
181
-		}
182
-		if (!is_array($configuredDatabases)) {
183
-			throw new Exception('Supported databases are not properly configured.');
184
-		}
185
-
186
-		$supportedDatabases = [];
187
-
188
-		foreach ($configuredDatabases as $database) {
189
-			if (array_key_exists($database, $availableDatabases)) {
190
-				$working = false;
191
-				$type = $availableDatabases[$database]['type'];
192
-				$call = $availableDatabases[$database]['call'];
193
-
194
-				if ($type === 'function') {
195
-					$working = $this->is_callable($call);
196
-				} elseif ($type === 'pdo') {
197
-					$working = in_array($call, $this->getAvailableDbDriversForPdo(), true);
198
-				}
199
-				if ($working) {
200
-					$supportedDatabases[$database] = $availableDatabases[$database]['name'];
201
-				}
202
-			}
203
-		}
204
-
205
-		return $supportedDatabases;
206
-	}
207
-
208
-	/**
209
-	 * Gathers system information like database type and does
210
-	 * a few system checks.
211
-	 *
212
-	 * @return array of system info, including an "errors" value
213
-	 * in case of errors/warnings
214
-	 */
215
-	public function getSystemInfo($allowAllDatabases = false) {
216
-		$databases = $this->getSupportedDatabases($allowAllDatabases);
217
-
218
-		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
219
-
220
-		$errors = [];
221
-
222
-		// Create data directory to test whether the .htaccess works
223
-		// Notice that this is not necessarily the same data directory as the one
224
-		// that will effectively be used.
225
-		if (!file_exists($dataDir)) {
226
-			@mkdir($dataDir);
227
-		}
228
-		$htAccessWorking = true;
229
-		if (is_dir($dataDir) && is_writable($dataDir)) {
230
-			// Protect data directory here, so we can test if the protection is working
231
-			self::protectDataDirectory();
232
-
233
-			try {
234
-				$util = new \OC_Util();
235
-				$htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
236
-			} catch (\OC\HintException $e) {
237
-				$errors[] = [
238
-					'error' => $e->getMessage(),
239
-					'exception' => $e,
240
-					'hint' => $e->getHint(),
241
-				];
242
-				$htAccessWorking = false;
243
-			}
244
-		}
245
-
246
-		if (\OC_Util::runningOnMac()) {
247
-			$errors[] = [
248
-				'error' => $this->l10n->t(
249
-					'Mac OS X is not supported and %s will not work properly on this platform. ' .
250
-					'Use it at your own risk! ',
251
-					[$this->defaults->getName()]
252
-				),
253
-				'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.'),
254
-			];
255
-		}
256
-
257
-		if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
258
-			$errors[] = [
259
-				'error' => $this->l10n->t(
260
-					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
261
-					'This will lead to problems with files over 4 GB and is highly discouraged.',
262
-					[$this->defaults->getName()]
263
-				),
264
-				'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.'),
265
-			];
266
-		}
267
-
268
-		return [
269
-			'hasSQLite' => isset($databases['sqlite']),
270
-			'hasMySQL' => isset($databases['mysql']),
271
-			'hasPostgreSQL' => isset($databases['pgsql']),
272
-			'hasOracle' => isset($databases['oci']),
273
-			'databases' => $databases,
274
-			'directory' => $dataDir,
275
-			'htaccessWorking' => $htAccessWorking,
276
-			'errors' => $errors,
277
-		];
278
-	}
279
-
280
-	/**
281
-	 * @param $options
282
-	 * @return array
283
-	 */
284
-	public function install($options) {
285
-		$l = $this->l10n;
286
-
287
-		$error = [];
288
-		$dbType = $options['dbtype'];
289
-
290
-		if (empty($options['adminlogin'])) {
291
-			$error[] = $l->t('Set an admin username.');
292
-		}
293
-		if (empty($options['adminpass'])) {
294
-			$error[] = $l->t('Set an admin password.');
295
-		}
296
-		if (empty($options['directory'])) {
297
-			$options['directory'] = \OC::$SERVERROOT . "/data";
298
-		}
299
-
300
-		if (!isset(self::$dbSetupClasses[$dbType])) {
301
-			$dbType = 'sqlite';
302
-		}
303
-
304
-		$username = htmlspecialchars_decode($options['adminlogin']);
305
-		$password = htmlspecialchars_decode($options['adminpass']);
306
-		$dataDir = htmlspecialchars_decode($options['directory']);
307
-
308
-		$class = self::$dbSetupClasses[$dbType];
309
-		/** @var \OC\Setup\AbstractDatabase $dbSetup */
310
-		$dbSetup = new $class($l, $this->config, $this->logger, $this->random);
311
-		$error = array_merge($error, $dbSetup->validate($options));
312
-
313
-		// validate the data directory
314
-		if ((!is_dir($dataDir) && !mkdir($dataDir)) || !is_writable($dataDir)) {
315
-			$error[] = $l->t("Can't create or write into the data directory %s", [$dataDir]);
316
-		}
317
-
318
-		if (!empty($error)) {
319
-			return $error;
320
-		}
321
-
322
-		$request = \OC::$server->getRequest();
323
-
324
-		//no errors, good
325
-		if (isset($options['trusted_domains'])
326
-			&& is_array($options['trusted_domains'])) {
327
-			$trustedDomains = $options['trusted_domains'];
328
-		} else {
329
-			$trustedDomains = [$request->getInsecureServerHost()];
330
-		}
331
-
332
-		//use sqlite3 when available, otherwise sqlite2 will be used.
333
-		if ($dbType === 'sqlite' && class_exists('SQLite3')) {
334
-			$dbType = 'sqlite3';
335
-		}
336
-
337
-		//generate a random salt that is used to salt the local user passwords
338
-		$salt = $this->random->generate(30);
339
-		// generate a secret
340
-		$secret = $this->random->generate(48);
341
-
342
-		//write the config file
343
-		$newConfigValues = [
344
-			'passwordsalt' => $salt,
345
-			'secret' => $secret,
346
-			'trusted_domains' => $trustedDomains,
347
-			'datadirectory' => $dataDir,
348
-			'dbtype' => $dbType,
349
-			'version' => implode('.', \OCP\Util::getVersion()),
350
-		];
351
-
352
-		if ($this->config->getValue('overwrite.cli.url', null) === null) {
353
-			$newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
354
-		}
355
-
356
-		$this->config->setValues($newConfigValues);
357
-
358
-		$dbSetup->initialize($options);
359
-		try {
360
-			$dbSetup->setupDatabase($username);
361
-		} catch (\OC\DatabaseSetupException $e) {
362
-			$error[] = [
363
-				'error' => $e->getMessage(),
364
-				'exception' => $e,
365
-				'hint' => $e->getHint(),
366
-			];
367
-			return $error;
368
-		} catch (Exception $e) {
369
-			$error[] = [
370
-				'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
371
-				'exception' => $e,
372
-				'hint' => '',
373
-			];
374
-			return $error;
375
-		}
376
-		try {
377
-			// apply necessary migrations
378
-			$dbSetup->runMigrations();
379
-		} catch (Exception $e) {
380
-			$error[] = [
381
-				'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
382
-				'exception' => $e,
383
-				'hint' => '',
384
-			];
385
-			return $error;
386
-		}
387
-
388
-		//create the user and group
389
-		$user = null;
390
-		try {
391
-			$user = \OC::$server->getUserManager()->createUser($username, $password);
392
-			if (!$user) {
393
-				$error[] = "User <$username> could not be created.";
394
-			}
395
-		} catch (Exception $exception) {
396
-			$error[] = $exception->getMessage();
397
-		}
398
-
399
-		if (empty($error)) {
400
-			$config = \OC::$server->getConfig();
401
-			$config->setAppValue('core', 'installedat', microtime(true));
402
-			$config->setAppValue('core', 'lastupdatedat', microtime(true));
403
-			$config->setAppValue('core', 'vendor', $this->getVendor());
404
-
405
-			$group = \OC::$server->getGroupManager()->createGroup('admin');
406
-			if ($group instanceof IGroup) {
407
-				$group->addUser($user);
408
-			}
409
-
410
-			// Install shipped apps and specified app bundles
411
-			Installer::installShippedApps();
412
-			$bundleFetcher = new BundleFetcher(\OC::$server->getL10N('lib'));
413
-			$defaultInstallationBundles = $bundleFetcher->getDefaultInstallationBundle();
414
-			foreach ($defaultInstallationBundles as $bundle) {
415
-				try {
416
-					$this->installer->installAppBundle($bundle);
417
-				} catch (Exception $e) {
418
-				}
419
-			}
420
-
421
-			// create empty file in data dir, so we can later find
422
-			// out that this is indeed an ownCloud data directory
423
-			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
424
-
425
-			// Update .htaccess files
426
-			self::updateHtaccess();
427
-			self::protectDataDirectory();
428
-
429
-			self::installBackgroundJobs();
430
-
431
-			//and we are done
432
-			$config->setSystemValue('installed', true);
433
-
434
-			// Create a session token for the newly created user
435
-			// The token provider requires a working db, so it's not injected on setup
436
-			/* @var $userSession User\Session */
437
-			$userSession = \OC::$server->getUserSession();
438
-			$defaultTokenProvider = \OC::$server->query(DefaultTokenProvider::class);
439
-			$userSession->setTokenProvider($defaultTokenProvider);
440
-			$userSession->login($username, $password);
441
-			$userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
442
-
443
-			$session = $userSession->getSession();
444
-			$session->set('last-password-confirm', \OC::$server->query(ITimeFactory::class)->getTime());
445
-
446
-			// Set email for admin
447
-			if (!empty($options['adminemail'])) {
448
-				$config->setUserValue($user->getUID(), 'settings', 'email', $options['adminemail']);
449
-			}
450
-		}
451
-
452
-		return $error;
453
-	}
454
-
455
-	public static function installBackgroundJobs() {
456
-		$jobList = \OC::$server->getJobList();
457
-		$jobList->add(DefaultTokenCleanupJob::class);
458
-		$jobList->add(Rotate::class);
459
-		$jobList->add(BackgroundCleanupJob::class);
460
-	}
461
-
462
-	/**
463
-	 * @return string Absolute path to htaccess
464
-	 */
465
-	private function pathToHtaccess() {
466
-		return \OC::$SERVERROOT . '/.htaccess';
467
-	}
468
-
469
-	/**
470
-	 * Find webroot from config
471
-	 *
472
-	 * @param SystemConfig $config
473
-	 * @return string
474
-	 * @throws InvalidArgumentException when invalid value for overwrite.cli.url
475
-	 */
476
-	private static function findWebRoot(SystemConfig $config): string {
477
-		// For CLI read the value from overwrite.cli.url
478
-		if (\OC::$CLI) {
479
-			$webRoot = $config->getValue('overwrite.cli.url', '');
480
-			if ($webRoot === '') {
481
-				throw new InvalidArgumentException('overwrite.cli.url is empty');
482
-			}
483
-			if (!filter_var($webRoot, FILTER_VALIDATE_URL)) {
484
-				throw new InvalidArgumentException('invalid value for overwrite.cli.url');
485
-			}
486
-			$webRoot = rtrim(parse_url($webRoot, PHP_URL_PATH), '/');
487
-		} else {
488
-			$webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
489
-		}
490
-
491
-		return $webRoot;
492
-	}
493
-
494
-	/**
495
-	 * Append the correct ErrorDocument path for Apache hosts
496
-	 *
497
-	 * @return bool True when success, False otherwise
498
-	 * @throws \OCP\AppFramework\QueryException
499
-	 */
500
-	public static function updateHtaccess() {
501
-		$config = \OC::$server->getSystemConfig();
502
-
503
-		try {
504
-			$webRoot = self::findWebRoot($config);
505
-		} catch (InvalidArgumentException $e) {
506
-			return false;
507
-		}
508
-
509
-		$setupHelper = new \OC\Setup(
510
-			$config,
511
-			\OC::$server->get(IniGetWrapper::class),
512
-			\OC::$server->getL10N('lib'),
513
-			\OC::$server->query(Defaults::class),
514
-			\OC::$server->getLogger(),
515
-			\OC::$server->getSecureRandom(),
516
-			\OC::$server->query(Installer::class)
517
-		);
518
-
519
-		$htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
520
-		$content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
521
-		$htaccessContent = explode($content, $htaccessContent, 2)[0];
522
-
523
-		//custom 403 error page
524
-		$content .= "\nErrorDocument 403 " . $webRoot . '/';
525
-
526
-		//custom 404 error page
527
-		$content .= "\nErrorDocument 404 " . $webRoot . '/';
528
-
529
-		// Add rewrite rules if the RewriteBase is configured
530
-		$rewriteBase = $config->getValue('htaccess.RewriteBase', '');
531
-		if ($rewriteBase !== '') {
532
-			$content .= "\n<IfModule mod_rewrite.c>";
533
-			$content .= "\n  Options -MultiViews";
534
-			$content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
535
-			$content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
536
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav)$";
537
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$";
538
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/manifest.json$";
539
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/remote.php";
540
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/public.php";
541
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/cron.php";
542
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php";
543
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/status.php";
544
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php";
545
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php";
546
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots.txt";
547
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/updater/";
548
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
549
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocm-provider/";
550
-			$content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
551
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
552
-			$content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
553
-			$content .= "\n  RewriteBase " . $rewriteBase;
554
-			$content .= "\n  <IfModule mod_env.c>";
555
-			$content .= "\n    SetEnv front_controller_active true";
556
-			$content .= "\n    <IfModule mod_dir.c>";
557
-			$content .= "\n      DirectorySlash off";
558
-			$content .= "\n    </IfModule>";
559
-			$content .= "\n  </IfModule>";
560
-			$content .= "\n</IfModule>";
561
-		}
562
-
563
-		if ($content !== '') {
564
-			//suppress errors in case we don't have permissions for it
565
-			return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
566
-		}
567
-
568
-		return false;
569
-	}
570
-
571
-	public static function protectDataDirectory() {
572
-		//Require all denied
573
-		$now = date('Y-m-d H:i:s');
574
-		$content = "# Generated by Nextcloud on $now\n";
575
-		$content .= "# Section for Apache 2.4 to 2.6\n";
576
-		$content .= "<IfModule mod_authz_core.c>\n";
577
-		$content .= "  Require all denied\n";
578
-		$content .= "</IfModule>\n";
579
-		$content .= "<IfModule mod_access_compat.c>\n";
580
-		$content .= "  Order Allow,Deny\n";
581
-		$content .= "  Deny from all\n";
582
-		$content .= "  Satisfy All\n";
583
-		$content .= "</IfModule>\n\n";
584
-		$content .= "# Section for Apache 2.2\n";
585
-		$content .= "<IfModule !mod_authz_core.c>\n";
586
-		$content .= "  <IfModule !mod_access_compat.c>\n";
587
-		$content .= "    <IfModule mod_authz_host.c>\n";
588
-		$content .= "      Order Allow,Deny\n";
589
-		$content .= "      Deny from all\n";
590
-		$content .= "    </IfModule>\n";
591
-		$content .= "    Satisfy All\n";
592
-		$content .= "  </IfModule>\n";
593
-		$content .= "</IfModule>\n\n";
594
-		$content .= "# Section for Apache 2.2 to 2.6\n";
595
-		$content .= "<IfModule mod_autoindex.c>\n";
596
-		$content .= "  IndexIgnore *\n";
597
-		$content .= "</IfModule>";
598
-
599
-		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
600
-		file_put_contents($baseDir . '/.htaccess', $content);
601
-		file_put_contents($baseDir . '/index.html', '');
602
-	}
603
-
604
-	/**
605
-	 * Return vendor from which this version was published
606
-	 *
607
-	 * @return string Get the vendor
608
-	 *
609
-	 * Copy of \OC\Updater::getVendor()
610
-	 */
611
-	private function getVendor() {
612
-		// this should really be a JSON file
613
-		require \OC::$SERVERROOT . '/version.php';
614
-		/** @var string $vendor */
615
-		return (string)$vendor;
616
-	}
67
+    /** @var SystemConfig */
68
+    protected $config;
69
+    /** @var IniGetWrapper */
70
+    protected $iniWrapper;
71
+    /** @var IL10N */
72
+    protected $l10n;
73
+    /** @var Defaults */
74
+    protected $defaults;
75
+    /** @var ILogger */
76
+    protected $logger;
77
+    /** @var ISecureRandom */
78
+    protected $random;
79
+    /** @var Installer */
80
+    protected $installer;
81
+
82
+    /**
83
+     * @param SystemConfig $config
84
+     * @param IniGetWrapper $iniWrapper
85
+     * @param IL10N $l10n
86
+     * @param Defaults $defaults
87
+     * @param ILogger $logger
88
+     * @param ISecureRandom $random
89
+     * @param Installer $installer
90
+     */
91
+    public function __construct(
92
+        SystemConfig $config,
93
+        IniGetWrapper $iniWrapper,
94
+        IL10N $l10n,
95
+        Defaults $defaults,
96
+        ILogger $logger,
97
+        ISecureRandom $random,
98
+        Installer $installer
99
+    ) {
100
+        $this->config = $config;
101
+        $this->iniWrapper = $iniWrapper;
102
+        $this->l10n = $l10n;
103
+        $this->defaults = $defaults;
104
+        $this->logger = $logger;
105
+        $this->random = $random;
106
+        $this->installer = $installer;
107
+    }
108
+
109
+    protected static $dbSetupClasses = [
110
+        'mysql' => \OC\Setup\MySQL::class,
111
+        'pgsql' => \OC\Setup\PostgreSQL::class,
112
+        'oci' => \OC\Setup\OCI::class,
113
+        'sqlite' => \OC\Setup\Sqlite::class,
114
+        'sqlite3' => \OC\Setup\Sqlite::class,
115
+    ];
116
+
117
+    /**
118
+     * Wrapper around the "class_exists" PHP function to be able to mock it
119
+     *
120
+     * @param string $name
121
+     * @return bool
122
+     */
123
+    protected function class_exists($name) {
124
+        return class_exists($name);
125
+    }
126
+
127
+    /**
128
+     * Wrapper around the "is_callable" PHP function to be able to mock it
129
+     *
130
+     * @param string $name
131
+     * @return bool
132
+     */
133
+    protected function is_callable($name) {
134
+        return is_callable($name);
135
+    }
136
+
137
+    /**
138
+     * Wrapper around \PDO::getAvailableDrivers
139
+     *
140
+     * @return array
141
+     */
142
+    protected function getAvailableDbDriversForPdo() {
143
+        return \PDO::getAvailableDrivers();
144
+    }
145
+
146
+    /**
147
+     * Get the available and supported databases of this instance
148
+     *
149
+     * @param bool $allowAllDatabases
150
+     * @return array
151
+     * @throws Exception
152
+     */
153
+    public function getSupportedDatabases($allowAllDatabases = false) {
154
+        $availableDatabases = [
155
+            'sqlite' => [
156
+                'type' => 'pdo',
157
+                'call' => 'sqlite',
158
+                'name' => 'SQLite',
159
+            ],
160
+            'mysql' => [
161
+                'type' => 'pdo',
162
+                'call' => 'mysql',
163
+                'name' => 'MySQL/MariaDB',
164
+            ],
165
+            'pgsql' => [
166
+                'type' => 'pdo',
167
+                'call' => 'pgsql',
168
+                'name' => 'PostgreSQL',
169
+            ],
170
+            'oci' => [
171
+                'type' => 'function',
172
+                'call' => 'oci_connect',
173
+                'name' => 'Oracle',
174
+            ],
175
+        ];
176
+        if ($allowAllDatabases) {
177
+            $configuredDatabases = array_keys($availableDatabases);
178
+        } else {
179
+            $configuredDatabases = $this->config->getValue('supportedDatabases',
180
+                ['sqlite', 'mysql', 'pgsql']);
181
+        }
182
+        if (!is_array($configuredDatabases)) {
183
+            throw new Exception('Supported databases are not properly configured.');
184
+        }
185
+
186
+        $supportedDatabases = [];
187
+
188
+        foreach ($configuredDatabases as $database) {
189
+            if (array_key_exists($database, $availableDatabases)) {
190
+                $working = false;
191
+                $type = $availableDatabases[$database]['type'];
192
+                $call = $availableDatabases[$database]['call'];
193
+
194
+                if ($type === 'function') {
195
+                    $working = $this->is_callable($call);
196
+                } elseif ($type === 'pdo') {
197
+                    $working = in_array($call, $this->getAvailableDbDriversForPdo(), true);
198
+                }
199
+                if ($working) {
200
+                    $supportedDatabases[$database] = $availableDatabases[$database]['name'];
201
+                }
202
+            }
203
+        }
204
+
205
+        return $supportedDatabases;
206
+    }
207
+
208
+    /**
209
+     * Gathers system information like database type and does
210
+     * a few system checks.
211
+     *
212
+     * @return array of system info, including an "errors" value
213
+     * in case of errors/warnings
214
+     */
215
+    public function getSystemInfo($allowAllDatabases = false) {
216
+        $databases = $this->getSupportedDatabases($allowAllDatabases);
217
+
218
+        $dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
219
+
220
+        $errors = [];
221
+
222
+        // Create data directory to test whether the .htaccess works
223
+        // Notice that this is not necessarily the same data directory as the one
224
+        // that will effectively be used.
225
+        if (!file_exists($dataDir)) {
226
+            @mkdir($dataDir);
227
+        }
228
+        $htAccessWorking = true;
229
+        if (is_dir($dataDir) && is_writable($dataDir)) {
230
+            // Protect data directory here, so we can test if the protection is working
231
+            self::protectDataDirectory();
232
+
233
+            try {
234
+                $util = new \OC_Util();
235
+                $htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
236
+            } catch (\OC\HintException $e) {
237
+                $errors[] = [
238
+                    'error' => $e->getMessage(),
239
+                    'exception' => $e,
240
+                    'hint' => $e->getHint(),
241
+                ];
242
+                $htAccessWorking = false;
243
+            }
244
+        }
245
+
246
+        if (\OC_Util::runningOnMac()) {
247
+            $errors[] = [
248
+                'error' => $this->l10n->t(
249
+                    'Mac OS X is not supported and %s will not work properly on this platform. ' .
250
+                    'Use it at your own risk! ',
251
+                    [$this->defaults->getName()]
252
+                ),
253
+                'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.'),
254
+            ];
255
+        }
256
+
257
+        if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
258
+            $errors[] = [
259
+                'error' => $this->l10n->t(
260
+                    'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
261
+                    'This will lead to problems with files over 4 GB and is highly discouraged.',
262
+                    [$this->defaults->getName()]
263
+                ),
264
+                'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.'),
265
+            ];
266
+        }
267
+
268
+        return [
269
+            'hasSQLite' => isset($databases['sqlite']),
270
+            'hasMySQL' => isset($databases['mysql']),
271
+            'hasPostgreSQL' => isset($databases['pgsql']),
272
+            'hasOracle' => isset($databases['oci']),
273
+            'databases' => $databases,
274
+            'directory' => $dataDir,
275
+            'htaccessWorking' => $htAccessWorking,
276
+            'errors' => $errors,
277
+        ];
278
+    }
279
+
280
+    /**
281
+     * @param $options
282
+     * @return array
283
+     */
284
+    public function install($options) {
285
+        $l = $this->l10n;
286
+
287
+        $error = [];
288
+        $dbType = $options['dbtype'];
289
+
290
+        if (empty($options['adminlogin'])) {
291
+            $error[] = $l->t('Set an admin username.');
292
+        }
293
+        if (empty($options['adminpass'])) {
294
+            $error[] = $l->t('Set an admin password.');
295
+        }
296
+        if (empty($options['directory'])) {
297
+            $options['directory'] = \OC::$SERVERROOT . "/data";
298
+        }
299
+
300
+        if (!isset(self::$dbSetupClasses[$dbType])) {
301
+            $dbType = 'sqlite';
302
+        }
303
+
304
+        $username = htmlspecialchars_decode($options['adminlogin']);
305
+        $password = htmlspecialchars_decode($options['adminpass']);
306
+        $dataDir = htmlspecialchars_decode($options['directory']);
307
+
308
+        $class = self::$dbSetupClasses[$dbType];
309
+        /** @var \OC\Setup\AbstractDatabase $dbSetup */
310
+        $dbSetup = new $class($l, $this->config, $this->logger, $this->random);
311
+        $error = array_merge($error, $dbSetup->validate($options));
312
+
313
+        // validate the data directory
314
+        if ((!is_dir($dataDir) && !mkdir($dataDir)) || !is_writable($dataDir)) {
315
+            $error[] = $l->t("Can't create or write into the data directory %s", [$dataDir]);
316
+        }
317
+
318
+        if (!empty($error)) {
319
+            return $error;
320
+        }
321
+
322
+        $request = \OC::$server->getRequest();
323
+
324
+        //no errors, good
325
+        if (isset($options['trusted_domains'])
326
+            && is_array($options['trusted_domains'])) {
327
+            $trustedDomains = $options['trusted_domains'];
328
+        } else {
329
+            $trustedDomains = [$request->getInsecureServerHost()];
330
+        }
331
+
332
+        //use sqlite3 when available, otherwise sqlite2 will be used.
333
+        if ($dbType === 'sqlite' && class_exists('SQLite3')) {
334
+            $dbType = 'sqlite3';
335
+        }
336
+
337
+        //generate a random salt that is used to salt the local user passwords
338
+        $salt = $this->random->generate(30);
339
+        // generate a secret
340
+        $secret = $this->random->generate(48);
341
+
342
+        //write the config file
343
+        $newConfigValues = [
344
+            'passwordsalt' => $salt,
345
+            'secret' => $secret,
346
+            'trusted_domains' => $trustedDomains,
347
+            'datadirectory' => $dataDir,
348
+            'dbtype' => $dbType,
349
+            'version' => implode('.', \OCP\Util::getVersion()),
350
+        ];
351
+
352
+        if ($this->config->getValue('overwrite.cli.url', null) === null) {
353
+            $newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
354
+        }
355
+
356
+        $this->config->setValues($newConfigValues);
357
+
358
+        $dbSetup->initialize($options);
359
+        try {
360
+            $dbSetup->setupDatabase($username);
361
+        } catch (\OC\DatabaseSetupException $e) {
362
+            $error[] = [
363
+                'error' => $e->getMessage(),
364
+                'exception' => $e,
365
+                'hint' => $e->getHint(),
366
+            ];
367
+            return $error;
368
+        } catch (Exception $e) {
369
+            $error[] = [
370
+                'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
371
+                'exception' => $e,
372
+                'hint' => '',
373
+            ];
374
+            return $error;
375
+        }
376
+        try {
377
+            // apply necessary migrations
378
+            $dbSetup->runMigrations();
379
+        } catch (Exception $e) {
380
+            $error[] = [
381
+                'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
382
+                'exception' => $e,
383
+                'hint' => '',
384
+            ];
385
+            return $error;
386
+        }
387
+
388
+        //create the user and group
389
+        $user = null;
390
+        try {
391
+            $user = \OC::$server->getUserManager()->createUser($username, $password);
392
+            if (!$user) {
393
+                $error[] = "User <$username> could not be created.";
394
+            }
395
+        } catch (Exception $exception) {
396
+            $error[] = $exception->getMessage();
397
+        }
398
+
399
+        if (empty($error)) {
400
+            $config = \OC::$server->getConfig();
401
+            $config->setAppValue('core', 'installedat', microtime(true));
402
+            $config->setAppValue('core', 'lastupdatedat', microtime(true));
403
+            $config->setAppValue('core', 'vendor', $this->getVendor());
404
+
405
+            $group = \OC::$server->getGroupManager()->createGroup('admin');
406
+            if ($group instanceof IGroup) {
407
+                $group->addUser($user);
408
+            }
409
+
410
+            // Install shipped apps and specified app bundles
411
+            Installer::installShippedApps();
412
+            $bundleFetcher = new BundleFetcher(\OC::$server->getL10N('lib'));
413
+            $defaultInstallationBundles = $bundleFetcher->getDefaultInstallationBundle();
414
+            foreach ($defaultInstallationBundles as $bundle) {
415
+                try {
416
+                    $this->installer->installAppBundle($bundle);
417
+                } catch (Exception $e) {
418
+                }
419
+            }
420
+
421
+            // create empty file in data dir, so we can later find
422
+            // out that this is indeed an ownCloud data directory
423
+            file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
424
+
425
+            // Update .htaccess files
426
+            self::updateHtaccess();
427
+            self::protectDataDirectory();
428
+
429
+            self::installBackgroundJobs();
430
+
431
+            //and we are done
432
+            $config->setSystemValue('installed', true);
433
+
434
+            // Create a session token for the newly created user
435
+            // The token provider requires a working db, so it's not injected on setup
436
+            /* @var $userSession User\Session */
437
+            $userSession = \OC::$server->getUserSession();
438
+            $defaultTokenProvider = \OC::$server->query(DefaultTokenProvider::class);
439
+            $userSession->setTokenProvider($defaultTokenProvider);
440
+            $userSession->login($username, $password);
441
+            $userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
442
+
443
+            $session = $userSession->getSession();
444
+            $session->set('last-password-confirm', \OC::$server->query(ITimeFactory::class)->getTime());
445
+
446
+            // Set email for admin
447
+            if (!empty($options['adminemail'])) {
448
+                $config->setUserValue($user->getUID(), 'settings', 'email', $options['adminemail']);
449
+            }
450
+        }
451
+
452
+        return $error;
453
+    }
454
+
455
+    public static function installBackgroundJobs() {
456
+        $jobList = \OC::$server->getJobList();
457
+        $jobList->add(DefaultTokenCleanupJob::class);
458
+        $jobList->add(Rotate::class);
459
+        $jobList->add(BackgroundCleanupJob::class);
460
+    }
461
+
462
+    /**
463
+     * @return string Absolute path to htaccess
464
+     */
465
+    private function pathToHtaccess() {
466
+        return \OC::$SERVERROOT . '/.htaccess';
467
+    }
468
+
469
+    /**
470
+     * Find webroot from config
471
+     *
472
+     * @param SystemConfig $config
473
+     * @return string
474
+     * @throws InvalidArgumentException when invalid value for overwrite.cli.url
475
+     */
476
+    private static function findWebRoot(SystemConfig $config): string {
477
+        // For CLI read the value from overwrite.cli.url
478
+        if (\OC::$CLI) {
479
+            $webRoot = $config->getValue('overwrite.cli.url', '');
480
+            if ($webRoot === '') {
481
+                throw new InvalidArgumentException('overwrite.cli.url is empty');
482
+            }
483
+            if (!filter_var($webRoot, FILTER_VALIDATE_URL)) {
484
+                throw new InvalidArgumentException('invalid value for overwrite.cli.url');
485
+            }
486
+            $webRoot = rtrim(parse_url($webRoot, PHP_URL_PATH), '/');
487
+        } else {
488
+            $webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
489
+        }
490
+
491
+        return $webRoot;
492
+    }
493
+
494
+    /**
495
+     * Append the correct ErrorDocument path for Apache hosts
496
+     *
497
+     * @return bool True when success, False otherwise
498
+     * @throws \OCP\AppFramework\QueryException
499
+     */
500
+    public static function updateHtaccess() {
501
+        $config = \OC::$server->getSystemConfig();
502
+
503
+        try {
504
+            $webRoot = self::findWebRoot($config);
505
+        } catch (InvalidArgumentException $e) {
506
+            return false;
507
+        }
508
+
509
+        $setupHelper = new \OC\Setup(
510
+            $config,
511
+            \OC::$server->get(IniGetWrapper::class),
512
+            \OC::$server->getL10N('lib'),
513
+            \OC::$server->query(Defaults::class),
514
+            \OC::$server->getLogger(),
515
+            \OC::$server->getSecureRandom(),
516
+            \OC::$server->query(Installer::class)
517
+        );
518
+
519
+        $htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
520
+        $content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
521
+        $htaccessContent = explode($content, $htaccessContent, 2)[0];
522
+
523
+        //custom 403 error page
524
+        $content .= "\nErrorDocument 403 " . $webRoot . '/';
525
+
526
+        //custom 404 error page
527
+        $content .= "\nErrorDocument 404 " . $webRoot . '/';
528
+
529
+        // Add rewrite rules if the RewriteBase is configured
530
+        $rewriteBase = $config->getValue('htaccess.RewriteBase', '');
531
+        if ($rewriteBase !== '') {
532
+            $content .= "\n<IfModule mod_rewrite.c>";
533
+            $content .= "\n  Options -MultiViews";
534
+            $content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
535
+            $content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
536
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav)$";
537
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$";
538
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/manifest.json$";
539
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/remote.php";
540
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/public.php";
541
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/cron.php";
542
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php";
543
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/status.php";
544
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php";
545
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php";
546
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots.txt";
547
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/updater/";
548
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
549
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocm-provider/";
550
+            $content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
551
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
552
+            $content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
553
+            $content .= "\n  RewriteBase " . $rewriteBase;
554
+            $content .= "\n  <IfModule mod_env.c>";
555
+            $content .= "\n    SetEnv front_controller_active true";
556
+            $content .= "\n    <IfModule mod_dir.c>";
557
+            $content .= "\n      DirectorySlash off";
558
+            $content .= "\n    </IfModule>";
559
+            $content .= "\n  </IfModule>";
560
+            $content .= "\n</IfModule>";
561
+        }
562
+
563
+        if ($content !== '') {
564
+            //suppress errors in case we don't have permissions for it
565
+            return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
566
+        }
567
+
568
+        return false;
569
+    }
570
+
571
+    public static function protectDataDirectory() {
572
+        //Require all denied
573
+        $now = date('Y-m-d H:i:s');
574
+        $content = "# Generated by Nextcloud on $now\n";
575
+        $content .= "# Section for Apache 2.4 to 2.6\n";
576
+        $content .= "<IfModule mod_authz_core.c>\n";
577
+        $content .= "  Require all denied\n";
578
+        $content .= "</IfModule>\n";
579
+        $content .= "<IfModule mod_access_compat.c>\n";
580
+        $content .= "  Order Allow,Deny\n";
581
+        $content .= "  Deny from all\n";
582
+        $content .= "  Satisfy All\n";
583
+        $content .= "</IfModule>\n\n";
584
+        $content .= "# Section for Apache 2.2\n";
585
+        $content .= "<IfModule !mod_authz_core.c>\n";
586
+        $content .= "  <IfModule !mod_access_compat.c>\n";
587
+        $content .= "    <IfModule mod_authz_host.c>\n";
588
+        $content .= "      Order Allow,Deny\n";
589
+        $content .= "      Deny from all\n";
590
+        $content .= "    </IfModule>\n";
591
+        $content .= "    Satisfy All\n";
592
+        $content .= "  </IfModule>\n";
593
+        $content .= "</IfModule>\n\n";
594
+        $content .= "# Section for Apache 2.2 to 2.6\n";
595
+        $content .= "<IfModule mod_autoindex.c>\n";
596
+        $content .= "  IndexIgnore *\n";
597
+        $content .= "</IfModule>";
598
+
599
+        $baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
600
+        file_put_contents($baseDir . '/.htaccess', $content);
601
+        file_put_contents($baseDir . '/index.html', '');
602
+    }
603
+
604
+    /**
605
+     * Return vendor from which this version was published
606
+     *
607
+     * @return string Get the vendor
608
+     *
609
+     * Copy of \OC\Updater::getVendor()
610
+     */
611
+    private function getVendor() {
612
+        // this should really be a JSON file
613
+        require \OC::$SERVERROOT . '/version.php';
614
+        /** @var string $vendor */
615
+        return (string)$vendor;
616
+    }
617 617
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
 	public function getSystemInfo($allowAllDatabases = false) {
216 216
 		$databases = $this->getSupportedDatabases($allowAllDatabases);
217 217
 
218
-		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
218
+		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT.'/data');
219 219
 
220 220
 		$errors = [];
221 221
 
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
 		if (\OC_Util::runningOnMac()) {
247 247
 			$errors[] = [
248 248
 				'error' => $this->l10n->t(
249
-					'Mac OS X is not supported and %s will not work properly on this platform. ' .
249
+					'Mac OS X is not supported and %s will not work properly on this platform. '.
250 250
 					'Use it at your own risk! ',
251 251
 					[$this->defaults->getName()]
252 252
 				),
@@ -257,7 +257,7 @@  discard block
 block discarded – undo
257 257
 		if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
258 258
 			$errors[] = [
259 259
 				'error' => $this->l10n->t(
260
-					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
260
+					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. '.
261 261
 					'This will lead to problems with files over 4 GB and is highly discouraged.',
262 262
 					[$this->defaults->getName()]
263 263
 				),
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
 			$error[] = $l->t('Set an admin password.');
295 295
 		}
296 296
 		if (empty($options['directory'])) {
297
-			$options['directory'] = \OC::$SERVERROOT . "/data";
297
+			$options['directory'] = \OC::$SERVERROOT."/data";
298 298
 		}
299 299
 
300 300
 		if (!isset(self::$dbSetupClasses[$dbType])) {
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
 		];
351 351
 
352 352
 		if ($this->config->getValue('overwrite.cli.url', null) === null) {
353
-			$newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
353
+			$newConfigValues['overwrite.cli.url'] = $request->getServerProtocol().'://'.$request->getInsecureServerHost().\OC::$WEBROOT;
354 354
 		}
355 355
 
356 356
 		$this->config->setValues($newConfigValues);
@@ -367,7 +367,7 @@  discard block
 block discarded – undo
367 367
 			return $error;
368 368
 		} catch (Exception $e) {
369 369
 			$error[] = [
370
-				'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
370
+				'error' => 'Error while trying to create admin user: '.$e->getMessage(),
371 371
 				'exception' => $e,
372 372
 				'hint' => '',
373 373
 			];
@@ -378,7 +378,7 @@  discard block
 block discarded – undo
378 378
 			$dbSetup->runMigrations();
379 379
 		} catch (Exception $e) {
380 380
 			$error[] = [
381
-				'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
381
+				'error' => 'Error while trying to initialise the database: '.$e->getMessage(),
382 382
 				'exception' => $e,
383 383
 				'hint' => '',
384 384
 			];
@@ -420,7 +420,7 @@  discard block
 block discarded – undo
420 420
 
421 421
 			// create empty file in data dir, so we can later find
422 422
 			// out that this is indeed an ownCloud data directory
423
-			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
423
+			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/.ocdata', '');
424 424
 
425 425
 			// Update .htaccess files
426 426
 			self::updateHtaccess();
@@ -463,7 +463,7 @@  discard block
 block discarded – undo
463 463
 	 * @return string Absolute path to htaccess
464 464
 	 */
465 465
 	private function pathToHtaccess() {
466
-		return \OC::$SERVERROOT . '/.htaccess';
466
+		return \OC::$SERVERROOT.'/.htaccess';
467 467
 	}
468 468
 
469 469
 	/**
@@ -521,10 +521,10 @@  discard block
 block discarded – undo
521 521
 		$htaccessContent = explode($content, $htaccessContent, 2)[0];
522 522
 
523 523
 		//custom 403 error page
524
-		$content .= "\nErrorDocument 403 " . $webRoot . '/';
524
+		$content .= "\nErrorDocument 403 ".$webRoot.'/';
525 525
 
526 526
 		//custom 404 error page
527
-		$content .= "\nErrorDocument 404 " . $webRoot . '/';
527
+		$content .= "\nErrorDocument 404 ".$webRoot.'/';
528 528
 
529 529
 		// Add rewrite rules if the RewriteBase is configured
530 530
 		$rewriteBase = $config->getValue('htaccess.RewriteBase', '');
@@ -550,7 +550,7 @@  discard block
 block discarded – undo
550 550
 			$content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
551 551
 			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
552 552
 			$content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
553
-			$content .= "\n  RewriteBase " . $rewriteBase;
553
+			$content .= "\n  RewriteBase ".$rewriteBase;
554 554
 			$content .= "\n  <IfModule mod_env.c>";
555 555
 			$content .= "\n    SetEnv front_controller_active true";
556 556
 			$content .= "\n    <IfModule mod_dir.c>";
@@ -562,7 +562,7 @@  discard block
 block discarded – undo
562 562
 
563 563
 		if ($content !== '') {
564 564
 			//suppress errors in case we don't have permissions for it
565
-			return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
565
+			return (bool) @file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent.$content."\n");
566 566
 		}
567 567
 
568 568
 		return false;
@@ -596,9 +596,9 @@  discard block
 block discarded – undo
596 596
 		$content .= "  IndexIgnore *\n";
597 597
 		$content .= "</IfModule>";
598 598
 
599
-		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
600
-		file_put_contents($baseDir . '/.htaccess', $content);
601
-		file_put_contents($baseDir . '/index.html', '');
599
+		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data');
600
+		file_put_contents($baseDir.'/.htaccess', $content);
601
+		file_put_contents($baseDir.'/index.html', '');
602 602
 	}
603 603
 
604 604
 	/**
@@ -610,8 +610,8 @@  discard block
 block discarded – undo
610 610
 	 */
611 611
 	private function getVendor() {
612 612
 		// this should really be a JSON file
613
-		require \OC::$SERVERROOT . '/version.php';
613
+		require \OC::$SERVERROOT.'/version.php';
614 614
 		/** @var string $vendor */
615
-		return (string)$vendor;
615
+		return (string) $vendor;
616 616
 	}
617 617
 }
Please login to merge, or discard this patch.