Passed
Push — master ( d35a91...931a87 )
by Lukas
15:51 queued 12s
created

Setup   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 537
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 294
dl 0
loc 537
rs 4.5599
c 2
b 0
f 0
wmc 58

13 Methods

Rating   Name   Duplication   Size   Complexity  
A findWebRoot() 0 16 5
A pathToHtaccess() 0 2 1
A installBackgroundJobs() 0 5 1
A __construct() 0 16 1
A class_exists() 0 2 1
A is_callable() 0 2 1
A protectDataDirectory() 0 31 1
A updateHtaccess() 0 62 4
F install() 0 169 24
B getSystemInfo() 0 62 8
B getSupportedDatabases() 0 53 8
A getAvailableDbDriversForPdo() 0 5 2
A getVendor() 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\App\AppStore\Bundles\BundleFetcher;
55
use OC\Authentication\Token\DefaultTokenCleanupJob;
56
use OC\Authentication\Token\DefaultTokenProvider;
57
use OC\Log\Rotate;
58
use OC\Preview\BackgroundCleanupJob;
59
use OCP\AppFramework\Utility\ITimeFactory;
60
use OCP\Defaults;
61
use OCP\IGroup;
62
use OCP\IL10N;
63
use OCP\Security\ISecureRandom;
64
use Psr\Log\LoggerInterface;
65
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 LoggerInterface */
76
	protected $logger;
77
	/** @var ISecureRandom */
78
	protected $random;
79
	/** @var Installer */
80
	protected $installer;
81
82
	public function __construct(
83
		SystemConfig $config,
84
		IniGetWrapper $iniWrapper,
85
		IL10N $l10n,
86
		Defaults $defaults,
87
		LoggerInterface $logger,
88
		ISecureRandom $random,
89
		Installer $installer
90
	) {
91
		$this->config = $config;
92
		$this->iniWrapper = $iniWrapper;
93
		$this->l10n = $l10n;
94
		$this->defaults = $defaults;
95
		$this->logger = $logger;
96
		$this->random = $random;
97
		$this->installer = $installer;
98
	}
99
100
	protected static $dbSetupClasses = [
101
		'mysql' => \OC\Setup\MySQL::class,
102
		'pgsql' => \OC\Setup\PostgreSQL::class,
103
		'oci' => \OC\Setup\OCI::class,
104
		'sqlite' => \OC\Setup\Sqlite::class,
105
		'sqlite3' => \OC\Setup\Sqlite::class,
106
	];
107
108
	/**
109
	 * Wrapper around the "class_exists" PHP function to be able to mock it
110
	 *
111
	 * @param string $name
112
	 * @return bool
113
	 */
114
	protected function class_exists($name) {
115
		return class_exists($name);
116
	}
117
118
	/**
119
	 * Wrapper around the "is_callable" PHP function to be able to mock it
120
	 *
121
	 * @param string $name
122
	 * @return bool
123
	 */
124
	protected function is_callable($name) {
125
		return is_callable($name);
126
	}
127
128
	/**
129
	 * Wrapper around \PDO::getAvailableDrivers
130
	 *
131
	 * @return array
132
	 */
133
	protected function getAvailableDbDriversForPdo() {
134
		if (class_exists(\PDO::class)) {
135
			return \PDO::getAvailableDrivers();
136
		}
137
		return [];
138
	}
139
140
	/**
141
	 * Get the available and supported databases of this instance
142
	 *
143
	 * @param bool $allowAllDatabases
144
	 * @return array
145
	 * @throws Exception
146
	 */
147
	public function getSupportedDatabases($allowAllDatabases = false) {
148
		$availableDatabases = [
149
			'sqlite' => [
150
				'type' => 'pdo',
151
				'call' => 'sqlite',
152
				'name' => 'SQLite',
153
			],
154
			'mysql' => [
155
				'type' => 'pdo',
156
				'call' => 'mysql',
157
				'name' => 'MySQL/MariaDB',
158
			],
159
			'pgsql' => [
160
				'type' => 'pdo',
161
				'call' => 'pgsql',
162
				'name' => 'PostgreSQL',
163
			],
164
			'oci' => [
165
				'type' => 'function',
166
				'call' => 'oci_connect',
167
				'name' => 'Oracle',
168
			],
169
		];
170
		if ($allowAllDatabases) {
171
			$configuredDatabases = array_keys($availableDatabases);
172
		} else {
173
			$configuredDatabases = $this->config->getValue('supportedDatabases',
174
				['sqlite', 'mysql', 'pgsql']);
175
		}
176
		if (!is_array($configuredDatabases)) {
177
			throw new Exception('Supported databases are not properly configured.');
178
		}
179
180
		$supportedDatabases = [];
181
182
		foreach ($configuredDatabases as $database) {
183
			if (array_key_exists($database, $availableDatabases)) {
184
				$working = false;
185
				$type = $availableDatabases[$database]['type'];
186
				$call = $availableDatabases[$database]['call'];
187
188
				if ($type === 'function') {
189
					$working = $this->is_callable($call);
190
				} elseif ($type === 'pdo') {
191
					$working = in_array($call, $this->getAvailableDbDriversForPdo(), true);
192
				}
193
				if ($working) {
194
					$supportedDatabases[$database] = $availableDatabases[$database]['name'];
195
				}
196
			}
197
		}
198
199
		return $supportedDatabases;
200
	}
201
202
	/**
203
	 * Gathers system information like database type and does
204
	 * a few system checks.
205
	 *
206
	 * @return array of system info, including an "errors" value
207
	 * in case of errors/warnings
208
	 */
209
	public function getSystemInfo($allowAllDatabases = false) {
210
		$databases = $this->getSupportedDatabases($allowAllDatabases);
211
212
		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
213
214
		$errors = [];
215
216
		// Create data directory to test whether the .htaccess works
217
		// Notice that this is not necessarily the same data directory as the one
218
		// that will effectively be used.
219
		if (!file_exists($dataDir)) {
220
			@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

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