Passed
Push — master ( 4aa8e8...294a00 )
by Blizzz
14:43 queued 13s
created

Setup   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 533
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 295
dl 0
loc 533
rs 5.04
c 2
b 0
f 0
wmc 57

13 Methods

Rating   Name   Duplication   Size   Complexity  
A class_exists() 0 2 1
A protectDataDirectory() 0 31 1
A __construct() 0 16 1
A is_callable() 0 2 1
B getSystemInfo() 0 62 8
B getSupportedDatabases() 0 53 8
A getAvailableDbDriversForPdo() 0 5 2
A findWebRoot() 0 16 5
A getVendorData() 0 8 1
A updateHtaccess() 0 62 4
F install() 0 169 23
A pathToHtaccess() 0 2 1
A installBackgroundJobs() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Setup often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Setup, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Administrator "Administrator@WINDOWS-2012"
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Bart Visscher <[email protected]>
8
 * @author Bernhard Posselt <[email protected]>
9
 * @author Bjoern Schiessle <[email protected]>
10
 * @author Brice Maron <[email protected]>
11
 * @author Christoph Wurst <[email protected]>
12
 * @author Dan Callahan <[email protected]>
13
 * @author Daniel Kesselberg <[email protected]>
14
 * @author François Kubler <[email protected]>
15
 * @author Frank Isemann <[email protected]>
16
 * @author Jakob Sack <[email protected]>
17
 * @author Joas Schilling <[email protected]>
18
 * @author Julius Härtl <[email protected]>
19
 * @author KB7777 <[email protected]>
20
 * @author Kevin Lanni <[email protected]>
21
 * @author Lukas Reschke <[email protected]>
22
 * @author MichaIng <[email protected]>
23
 * @author MichaIng <[email protected]>
24
 * @author Morris Jobke <[email protected]>
25
 * @author Robin Appelman <[email protected]>
26
 * @author Roeland Jago Douma <[email protected]>
27
 * @author Sean Comeau <[email protected]>
28
 * @author Serge Martin <[email protected]>
29
 * @author Simounet <[email protected]>
30
 * @author Thomas Müller <[email protected]>
31
 * @author Valdnet <[email protected]>
32
 * @author Vincent Petry <[email protected]>
33
 *
34
 * @license AGPL-3.0
35
 *
36
 * This code is free software: you can redistribute it and/or modify
37
 * it under the terms of the GNU Affero General Public License, version 3,
38
 * as published by the Free Software Foundation.
39
 *
40
 * This program is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43
 * GNU Affero General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Affero General Public License, version 3,
46
 * along with this program. If not, see <http://www.gnu.org/licenses/>
47
 *
48
 */
49
namespace OC;
50
51
use bantu\IniGetWrapper\IniGetWrapper;
52
use Exception;
53
use InvalidArgumentException;
54
use OC\Authentication\Token\PublicKeyTokenProvider;
55
use OC\Authentication\Token\TokenCleanupJob;
56
use OC\Log\Rotate;
57
use OC\Preview\BackgroundCleanupJob;
58
use OCP\AppFramework\Utility\ITimeFactory;
59
use OCP\Defaults;
60
use OCP\IGroup;
61
use OCP\IL10N;
62
use OCP\Security\ISecureRandom;
63
use Psr\Log\LoggerInterface;
64
65
class Setup {
66
	/** @var SystemConfig */
67
	protected $config;
68
	/** @var IniGetWrapper */
69
	protected $iniWrapper;
70
	/** @var IL10N */
71
	protected $l10n;
72
	/** @var Defaults */
73
	protected $defaults;
74
	/** @var LoggerInterface */
75
	protected $logger;
76
	/** @var ISecureRandom */
77
	protected $random;
78
	/** @var Installer */
79
	protected $installer;
80
81
	public function __construct(
82
		SystemConfig $config,
83
		IniGetWrapper $iniWrapper,
84
		IL10N $l10n,
85
		Defaults $defaults,
86
		LoggerInterface $logger,
87
		ISecureRandom $random,
88
		Installer $installer
89
	) {
90
		$this->config = $config;
91
		$this->iniWrapper = $iniWrapper;
92
		$this->l10n = $l10n;
93
		$this->defaults = $defaults;
94
		$this->logger = $logger;
95
		$this->random = $random;
96
		$this->installer = $installer;
97
	}
98
99
	protected static $dbSetupClasses = [
100
		'mysql' => \OC\Setup\MySQL::class,
101
		'pgsql' => \OC\Setup\PostgreSQL::class,
102
		'oci' => \OC\Setup\OCI::class,
103
		'sqlite' => \OC\Setup\Sqlite::class,
104
		'sqlite3' => \OC\Setup\Sqlite::class,
105
	];
106
107
	/**
108
	 * Wrapper around the "class_exists" PHP function to be able to mock it
109
	 *
110
	 * @param string $name
111
	 * @return bool
112
	 */
113
	protected function class_exists($name) {
114
		return class_exists($name);
115
	}
116
117
	/**
118
	 * Wrapper around the "is_callable" PHP function to be able to mock it
119
	 *
120
	 * @param string $name
121
	 * @return bool
122
	 */
123
	protected function is_callable($name) {
124
		return is_callable($name);
125
	}
126
127
	/**
128
	 * Wrapper around \PDO::getAvailableDrivers
129
	 *
130
	 * @return array
131
	 */
132
	protected function getAvailableDbDriversForPdo() {
133
		if (class_exists(\PDO::class)) {
134
			return \PDO::getAvailableDrivers();
135
		}
136
		return [];
137
	}
138
139
	/**
140
	 * Get the available and supported databases of this instance
141
	 *
142
	 * @param bool $allowAllDatabases
143
	 * @return array
144
	 * @throws Exception
145
	 */
146
	public function getSupportedDatabases($allowAllDatabases = false) {
147
		$availableDatabases = [
148
			'sqlite' => [
149
				'type' => 'pdo',
150
				'call' => 'sqlite',
151
				'name' => 'SQLite',
152
			],
153
			'mysql' => [
154
				'type' => 'pdo',
155
				'call' => 'mysql',
156
				'name' => 'MySQL/MariaDB',
157
			],
158
			'pgsql' => [
159
				'type' => 'pdo',
160
				'call' => 'pgsql',
161
				'name' => 'PostgreSQL',
162
			],
163
			'oci' => [
164
				'type' => 'function',
165
				'call' => 'oci_connect',
166
				'name' => 'Oracle',
167
			],
168
		];
169
		if ($allowAllDatabases) {
170
			$configuredDatabases = array_keys($availableDatabases);
171
		} else {
172
			$configuredDatabases = $this->config->getValue('supportedDatabases',
173
				['sqlite', 'mysql', 'pgsql']);
174
		}
175
		if (!is_array($configuredDatabases)) {
176
			throw new Exception('Supported databases are not properly configured.');
177
		}
178
179
		$supportedDatabases = [];
180
181
		foreach ($configuredDatabases as $database) {
182
			if (array_key_exists($database, $availableDatabases)) {
183
				$working = false;
184
				$type = $availableDatabases[$database]['type'];
185
				$call = $availableDatabases[$database]['call'];
186
187
				if ($type === 'function') {
188
					$working = $this->is_callable($call);
189
				} elseif ($type === 'pdo') {
190
					$working = in_array($call, $this->getAvailableDbDriversForPdo(), true);
191
				}
192
				if ($working) {
193
					$supportedDatabases[$database] = $availableDatabases[$database]['name'];
194
				}
195
			}
196
		}
197
198
		return $supportedDatabases;
199
	}
200
201
	/**
202
	 * Gathers system information like database type and does
203
	 * a few system checks.
204
	 *
205
	 * @return array of system info, including an "errors" value
206
	 * in case of errors/warnings
207
	 */
208
	public function getSystemInfo($allowAllDatabases = false) {
209
		$databases = $this->getSupportedDatabases($allowAllDatabases);
210
211
		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
212
213
		$errors = [];
214
215
		// Create data directory to test whether the .htaccess works
216
		// Notice that this is not necessarily the same data directory as the one
217
		// that will effectively be used.
218
		if (!file_exists($dataDir)) {
219
			@mkdir($dataDir);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

219
			/** @scrutinizer ignore-unhandled */ @mkdir($dataDir);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
220
		}
221
		$htAccessWorking = true;
222
		if (is_dir($dataDir) && is_writable($dataDir)) {
223
			// Protect data directory here, so we can test if the protection is working
224
			self::protectDataDirectory();
225
226
			try {
227
				$util = new \OC_Util();
228
				$htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
229
			} catch (\OCP\HintException $e) {
230
				$errors[] = [
231
					'error' => $e->getMessage(),
232
					'exception' => $e,
233
					'hint' => $e->getHint(),
234
				];
235
				$htAccessWorking = false;
236
			}
237
		}
238
239
		if (\OC_Util::runningOnMac()) {
240
			$errors[] = [
241
				'error' => $this->l10n->t(
242
					'Mac OS X is not supported and %s will not work properly on this platform. ' .
243
					'Use it at your own risk! ',
244
					[$this->defaults->getProductName()]
245
				),
246
				'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.'),
247
			];
248
		}
249
250
		if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
251
			$errors[] = [
252
				'error' => $this->l10n->t(
253
					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
254
					'This will lead to problems with files over 4 GB and is highly discouraged.',
255
					[$this->defaults->getProductName()]
256
				),
257
				'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.'),
258
			];
259
		}
260
261
		return [
262
			'hasSQLite' => isset($databases['sqlite']),
263
			'hasMySQL' => isset($databases['mysql']),
264
			'hasPostgreSQL' => isset($databases['pgsql']),
265
			'hasOracle' => isset($databases['oci']),
266
			'databases' => $databases,
267
			'directory' => $dataDir,
268
			'htaccessWorking' => $htAccessWorking,
269
			'errors' => $errors,
270
		];
271
	}
272
273
	/**
274
	 * @param $options
275
	 * @return array
276
	 */
277
	public function install($options) {
278
		$l = $this->l10n;
279
280
		$error = [];
281
		$dbType = $options['dbtype'];
282
283
		if (empty($options['adminlogin'])) {
284
			$error[] = $l->t('Set an admin username.');
285
		}
286
		if (empty($options['adminpass'])) {
287
			$error[] = $l->t('Set an admin password.');
288
		}
289
		if (empty($options['directory'])) {
290
			$options['directory'] = \OC::$SERVERROOT . "/data";
291
		}
292
293
		if (!isset(self::$dbSetupClasses[$dbType])) {
294
			$dbType = 'sqlite';
295
		}
296
297
		$username = htmlspecialchars_decode($options['adminlogin']);
298
		$password = htmlspecialchars_decode($options['adminpass']);
299
		$dataDir = htmlspecialchars_decode($options['directory']);
300
301
		$class = self::$dbSetupClasses[$dbType];
302
		/** @var \OC\Setup\AbstractDatabase $dbSetup */
303
		$dbSetup = new $class($l, $this->config, $this->logger, $this->random);
304
		$error = array_merge($error, $dbSetup->validate($options));
305
306
		// validate the data directory
307
		if ((!is_dir($dataDir) && !mkdir($dataDir)) || !is_writable($dataDir)) {
308
			$error[] = $l->t("Cannot create or write into the data directory %s", [$dataDir]);
309
		}
310
311
		if (!empty($error)) {
312
			return $error;
313
		}
314
315
		$request = \OC::$server->getRequest();
316
317
		//no errors, good
318
		if (isset($options['trusted_domains'])
319
			&& is_array($options['trusted_domains'])) {
320
			$trustedDomains = $options['trusted_domains'];
321
		} else {
322
			$trustedDomains = [$request->getInsecureServerHost()];
323
		}
324
325
		//use sqlite3 when available, otherwise sqlite2 will be used.
326
		if ($dbType === 'sqlite' && class_exists('SQLite3')) {
327
			$dbType = 'sqlite3';
328
		}
329
330
		//generate a random salt that is used to salt the local user passwords
331
		$salt = $this->random->generate(30);
332
		// generate a secret
333
		$secret = $this->random->generate(48);
334
335
		//write the config file
336
		$newConfigValues = [
337
			'passwordsalt' => $salt,
338
			'secret' => $secret,
339
			'trusted_domains' => $trustedDomains,
340
			'datadirectory' => $dataDir,
341
			'dbtype' => $dbType,
342
			'version' => implode('.', \OCP\Util::getVersion()),
343
		];
344
345
		if ($this->config->getValue('overwrite.cli.url', null) === null) {
346
			$newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
347
		}
348
349
		$this->config->setValues($newConfigValues);
350
351
		$dbSetup->initialize($options);
352
		try {
353
			$dbSetup->setupDatabase($username);
354
		} catch (\OC\DatabaseSetupException $e) {
355
			$error[] = [
356
				'error' => $e->getMessage(),
357
				'exception' => $e,
358
				'hint' => $e->getHint(),
359
			];
360
			return $error;
361
		} catch (Exception $e) {
362
			$error[] = [
363
				'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
364
				'exception' => $e,
365
				'hint' => '',
366
			];
367
			return $error;
368
		}
369
		try {
370
			// apply necessary migrations
371
			$dbSetup->runMigrations();
372
		} catch (Exception $e) {
373
			$error[] = [
374
				'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
375
				'exception' => $e,
376
				'hint' => '',
377
			];
378
			return $error;
379
		}
380
381
		//create the user and group
382
		$user = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $user is dead and can be removed.
Loading history...
383
		try {
384
			$user = \OC::$server->getUserManager()->createUser($username, $password);
385
			if (!$user) {
0 ignored issues
show
introduced by
$user is of type OC\User\User, thus it always evaluated to true.
Loading history...
386
				$error[] = "User <$username> could not be created.";
387
			}
388
		} catch (Exception $exception) {
389
			$error[] = $exception->getMessage();
390
		}
391
392
		if (empty($error)) {
393
			$config = \OC::$server->getConfig();
394
			$config->setAppValue('core', 'installedat', microtime(true));
395
			$config->setAppValue('core', 'lastupdatedat', microtime(true));
396
397
			$vendorData = $this->getVendorData();
398
			$config->setAppValue('core', 'vendor', $vendorData['vendor']);
399
			if ($vendorData['channel'] !== 'stable') {
400
				$config->setSystemValue('updater.release.channel', $vendorData['channel']);
401
			}
402
403
			$group = \OC::$server->getGroupManager()->createGroup('admin');
404
			if ($group instanceof IGroup) {
0 ignored issues
show
introduced by
$group is always a sub-type of OCP\IGroup.
Loading history...
405
				$group->addUser($user);
406
			}
407
408
			// Install shipped apps and specified app bundles
409
			Installer::installShippedApps();
410
411
			// create empty file in data dir, so we can later find
412
			// out that this is indeed an ownCloud data directory
413
			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
414
415
			// Update .htaccess files
416
			self::updateHtaccess();
417
			self::protectDataDirectory();
418
419
			self::installBackgroundJobs();
420
421
			//and we are done
422
			$config->setSystemValue('installed', true);
423
424
			$bootstrapCoordinator = \OC::$server->query(\OC\AppFramework\Bootstrap\Coordinator::class);
425
			$bootstrapCoordinator->runInitialRegistration();
426
427
			// Create a session token for the newly created user
428
			// The token provider requires a working db, so it's not injected on setup
429
			/* @var $userSession User\Session */
430
			$userSession = \OC::$server->getUserSession();
431
			$provider = \OC::$server->query(PublicKeyTokenProvider::class);
432
			$userSession->setTokenProvider($provider);
433
			$userSession->login($username, $password);
434
			$userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
435
436
			$session = $userSession->getSession();
437
			$session->set('last-password-confirm', \OC::$server->query(ITimeFactory::class)->getTime());
438
439
			// Set email for admin
440
			if (!empty($options['adminemail'])) {
441
				$user->setSystemEMailAddress($options['adminemail']);
442
			}
443
		}
444
445
		return $error;
446
	}
447
448
	public static function installBackgroundJobs() {
449
		$jobList = \OC::$server->getJobList();
450
		$jobList->add(TokenCleanupJob::class);
451
		$jobList->add(Rotate::class);
452
		$jobList->add(BackgroundCleanupJob::class);
453
	}
454
455
	/**
456
	 * @return string Absolute path to htaccess
457
	 */
458
	private function pathToHtaccess() {
459
		return \OC::$SERVERROOT . '/.htaccess';
460
	}
461
462
	/**
463
	 * Find webroot from config
464
	 *
465
	 * @param SystemConfig $config
466
	 * @return string
467
	 * @throws InvalidArgumentException when invalid value for overwrite.cli.url
468
	 */
469
	private static function findWebRoot(SystemConfig $config): string {
470
		// For CLI read the value from overwrite.cli.url
471
		if (\OC::$CLI) {
472
			$webRoot = $config->getValue('overwrite.cli.url', '');
473
			if ($webRoot === '') {
474
				throw new InvalidArgumentException('overwrite.cli.url is empty');
475
			}
476
			if (!filter_var($webRoot, FILTER_VALIDATE_URL)) {
477
				throw new InvalidArgumentException('invalid value for overwrite.cli.url');
478
			}
479
			$webRoot = rtrim((parse_url($webRoot, PHP_URL_PATH) ?? ''), '/');
480
		} else {
481
			$webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
482
		}
483
484
		return $webRoot;
485
	}
486
487
	/**
488
	 * Append the correct ErrorDocument path for Apache hosts
489
	 *
490
	 * @return bool True when success, False otherwise
491
	 * @throws \OCP\AppFramework\QueryException
492
	 */
493
	public static function updateHtaccess() {
494
		$config = \OC::$server->getSystemConfig();
495
496
		try {
497
			$webRoot = self::findWebRoot($config);
498
		} catch (InvalidArgumentException $e) {
499
			return false;
500
		}
501
502
		$setupHelper = new \OC\Setup(
503
			$config,
504
			\OC::$server->get(IniGetWrapper::class),
505
			\OC::$server->getL10N('lib'),
506
			\OC::$server->query(Defaults::class),
507
			\OC::$server->get(LoggerInterface::class),
508
			\OC::$server->getSecureRandom(),
509
			\OC::$server->query(Installer::class)
510
		);
511
512
		$htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
513
		$content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
514
		$htaccessContent = explode($content, $htaccessContent, 2)[0];
515
516
		//custom 403 error page
517
		$content .= "\nErrorDocument 403 " . $webRoot . '/index.php/error/403';
518
519
		//custom 404 error page
520
		$content .= "\nErrorDocument 404 " . $webRoot . '/index.php/error/404';
521
522
		// Add rewrite rules if the RewriteBase is configured
523
		$rewriteBase = $config->getValue('htaccess.RewriteBase', '');
524
		if ($rewriteBase !== '') {
525
			$content .= "\n<IfModule mod_rewrite.c>";
526
			$content .= "\n  Options -MultiViews";
527
			$content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
528
			$content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
529
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav|wasm|tflite)$";
530
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update\\.php";
531
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/img/(favicon\\.ico|manifest\\.json)$";
532
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/(cron|public|remote|status)\\.php";
533
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v(1|2)\\.php";
534
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots\\.txt";
535
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/(ocm-provider|ocs-provider|updater)/";
536
			$content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
537
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
538
			$content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
539
			$content .= "\n  RewriteBase " . $rewriteBase;
540
			$content .= "\n  <IfModule mod_env.c>";
541
			$content .= "\n    SetEnv front_controller_active true";
542
			$content .= "\n    <IfModule mod_dir.c>";
543
			$content .= "\n      DirectorySlash off";
544
			$content .= "\n    </IfModule>";
545
			$content .= "\n  </IfModule>";
546
			$content .= "\n</IfModule>";
547
		}
548
549
		if ($content !== '') {
550
			//suppress errors in case we don't have permissions for it
551
			return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
552
		}
553
554
		return false;
555
	}
556
557
	public static function protectDataDirectory() {
558
		//Require all denied
559
		$now = date('Y-m-d H:i:s');
560
		$content = "# Generated by Nextcloud on $now\n";
561
		$content .= "# Section for Apache 2.4 to 2.6\n";
562
		$content .= "<IfModule mod_authz_core.c>\n";
563
		$content .= "  Require all denied\n";
564
		$content .= "</IfModule>\n";
565
		$content .= "<IfModule mod_access_compat.c>\n";
566
		$content .= "  Order Allow,Deny\n";
567
		$content .= "  Deny from all\n";
568
		$content .= "  Satisfy All\n";
569
		$content .= "</IfModule>\n\n";
570
		$content .= "# Section for Apache 2.2\n";
571
		$content .= "<IfModule !mod_authz_core.c>\n";
572
		$content .= "  <IfModule !mod_access_compat.c>\n";
573
		$content .= "    <IfModule mod_authz_host.c>\n";
574
		$content .= "      Order Allow,Deny\n";
575
		$content .= "      Deny from all\n";
576
		$content .= "    </IfModule>\n";
577
		$content .= "    Satisfy All\n";
578
		$content .= "  </IfModule>\n";
579
		$content .= "</IfModule>\n\n";
580
		$content .= "# Section for Apache 2.2 to 2.6\n";
581
		$content .= "<IfModule mod_autoindex.c>\n";
582
		$content .= "  IndexIgnore *\n";
583
		$content .= "</IfModule>";
584
585
		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
586
		file_put_contents($baseDir . '/.htaccess', $content);
587
		file_put_contents($baseDir . '/index.html', '');
588
	}
589
590
	private function getVendorData(): array {
591
		// this should really be a JSON file
592
		require \OC::$SERVERROOT . '/version.php';
593
		/** @var mixed $vendor */
594
		/** @var mixed $OC_Channel */
595
		return [
596
			'vendor' => (string)$vendor,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $vendor seems to be never defined.
Loading history...
597
			'channel' => (string)$OC_Channel,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $OC_Channel seems to be never defined.
Loading history...
598
		];
599
	}
600
}
601