Passed
Push — master ( 8c7a35...ac1c73 )
by Blizzz
23:14 queued 14s
created

Setup   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 532
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 290
dl 0
loc 532
rs 5.5199
c 1
b 0
f 0
wmc 56

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 1
A class_exists() 0 2 1
A is_callable() 0 2 1
B getSystemInfo() 0 62 8
B getSupportedDatabases() 0 53 8
A getAvailableDbDriversForPdo() 0 5 2
A protectDataDirectory() 0 31 1
A findWebRoot() 0 16 5
A updateHtaccess() 0 62 4
F install() 0 164 22
A pathToHtaccess() 0 2 1
A installBackgroundJobs() 0 5 1
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\PublicKeyTokenProvider;
56
use OC\Authentication\Token\TokenCleanupJob;
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
407
			// create empty file in data dir, so we can later find
408
			// out that this is indeed an ownCloud data directory
409
			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
410
411
			// Update .htaccess files
412
			self::updateHtaccess();
413
			self::protectDataDirectory();
414
415
			self::installBackgroundJobs();
416
417
			//and we are done
418
			$config->setSystemValue('installed', true);
419
420
			$bootstrapCoordinator = \OC::$server->query(\OC\AppFramework\Bootstrap\Coordinator::class);
421
			$bootstrapCoordinator->runInitialRegistration();
422
423
			// Create a session token for the newly created user
424
			// The token provider requires a working db, so it's not injected on setup
425
			/* @var $userSession User\Session */
426
			$userSession = \OC::$server->getUserSession();
427
			$provider = \OC::$server->query(PublicKeyTokenProvider::class);
428
			$userSession->setTokenProvider($provider);
429
			$userSession->login($username, $password);
430
			$userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
431
432
			$session = $userSession->getSession();
433
			$session->set('last-password-confirm', \OC::$server->query(ITimeFactory::class)->getTime());
434
435
			// Set email for admin
436
			if (!empty($options['adminemail'])) {
437
				$user->setSystemEMailAddress($options['adminemail']);
438
			}
439
		}
440
441
		return $error;
442
	}
443
444
	public static function installBackgroundJobs() {
445
		$jobList = \OC::$server->getJobList();
446
		$jobList->add(TokenCleanupJob::class);
447
		$jobList->add(Rotate::class);
448
		$jobList->add(BackgroundCleanupJob::class);
449
	}
450
451
	/**
452
	 * @return string Absolute path to htaccess
453
	 */
454
	private function pathToHtaccess() {
455
		return \OC::$SERVERROOT . '/.htaccess';
456
	}
457
458
	/**
459
	 * Find webroot from config
460
	 *
461
	 * @param SystemConfig $config
462
	 * @return string
463
	 * @throws InvalidArgumentException when invalid value for overwrite.cli.url
464
	 */
465
	private static function findWebRoot(SystemConfig $config): string {
466
		// For CLI read the value from overwrite.cli.url
467
		if (\OC::$CLI) {
468
			$webRoot = $config->getValue('overwrite.cli.url', '');
469
			if ($webRoot === '') {
470
				throw new InvalidArgumentException('overwrite.cli.url is empty');
471
			}
472
			if (!filter_var($webRoot, FILTER_VALIDATE_URL)) {
473
				throw new InvalidArgumentException('invalid value for overwrite.cli.url');
474
			}
475
			$webRoot = rtrim((parse_url($webRoot, PHP_URL_PATH) ?? ''), '/');
476
		} else {
477
			$webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
478
		}
479
480
		return $webRoot;
481
	}
482
483
	/**
484
	 * Append the correct ErrorDocument path for Apache hosts
485
	 *
486
	 * @return bool True when success, False otherwise
487
	 * @throws \OCP\AppFramework\QueryException
488
	 */
489
	public static function updateHtaccess() {
490
		$config = \OC::$server->getSystemConfig();
491
492
		try {
493
			$webRoot = self::findWebRoot($config);
494
		} catch (InvalidArgumentException $e) {
495
			return false;
496
		}
497
498
		$setupHelper = new \OC\Setup(
499
			$config,
500
			\OC::$server->get(IniGetWrapper::class),
501
			\OC::$server->getL10N('lib'),
502
			\OC::$server->query(Defaults::class),
503
			\OC::$server->get(LoggerInterface::class),
504
			\OC::$server->getSecureRandom(),
505
			\OC::$server->query(Installer::class)
506
		);
507
508
		$htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
509
		$content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
510
		$htaccessContent = explode($content, $htaccessContent, 2)[0];
511
512
		//custom 403 error page
513
		$content .= "\nErrorDocument 403 " . $webRoot . '/';
514
515
		//custom 404 error page
516
		$content .= "\nErrorDocument 404 " . $webRoot . '/';
517
518
		// Add rewrite rules if the RewriteBase is configured
519
		$rewriteBase = $config->getValue('htaccess.RewriteBase', '');
520
		if ($rewriteBase !== '') {
521
			$content .= "\n<IfModule mod_rewrite.c>";
522
			$content .= "\n  Options -MultiViews";
523
			$content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
524
			$content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
525
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav|wasm|tflite)$";
526
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update\\.php";
527
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/img/(favicon\\.ico|manifest\\.json)$";
528
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/(cron|public|remote|status)\\.php";
529
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v(1|2)\\.php";
530
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots\\.txt";
531
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/(ocm-provider|ocs-provider|updater)/";
532
			$content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
533
			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
534
			$content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
535
			$content .= "\n  RewriteBase " . $rewriteBase;
536
			$content .= "\n  <IfModule mod_env.c>";
537
			$content .= "\n    SetEnv front_controller_active true";
538
			$content .= "\n    <IfModule mod_dir.c>";
539
			$content .= "\n      DirectorySlash off";
540
			$content .= "\n    </IfModule>";
541
			$content .= "\n  </IfModule>";
542
			$content .= "\n</IfModule>";
543
		}
544
545
		if ($content !== '') {
546
			//suppress errors in case we don't have permissions for it
547
			return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
548
		}
549
550
		return false;
551
	}
552
553
	public static function protectDataDirectory() {
554
		//Require all denied
555
		$now = date('Y-m-d H:i:s');
556
		$content = "# Generated by Nextcloud on $now\n";
557
		$content .= "# Section for Apache 2.4 to 2.6\n";
558
		$content .= "<IfModule mod_authz_core.c>\n";
559
		$content .= "  Require all denied\n";
560
		$content .= "</IfModule>\n";
561
		$content .= "<IfModule mod_access_compat.c>\n";
562
		$content .= "  Order Allow,Deny\n";
563
		$content .= "  Deny from all\n";
564
		$content .= "  Satisfy All\n";
565
		$content .= "</IfModule>\n\n";
566
		$content .= "# Section for Apache 2.2\n";
567
		$content .= "<IfModule !mod_authz_core.c>\n";
568
		$content .= "  <IfModule !mod_access_compat.c>\n";
569
		$content .= "    <IfModule mod_authz_host.c>\n";
570
		$content .= "      Order Allow,Deny\n";
571
		$content .= "      Deny from all\n";
572
		$content .= "    </IfModule>\n";
573
		$content .= "    Satisfy All\n";
574
		$content .= "  </IfModule>\n";
575
		$content .= "</IfModule>\n\n";
576
		$content .= "# Section for Apache 2.2 to 2.6\n";
577
		$content .= "<IfModule mod_autoindex.c>\n";
578
		$content .= "  IndexIgnore *\n";
579
		$content .= "</IfModule>";
580
581
		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
582
		file_put_contents($baseDir . '/.htaccess', $content);
583
		file_put_contents($baseDir . '/index.html', '');
584
	}
585
586
	/**
587
	 * Return vendor from which this version was published
588
	 *
589
	 * @return string Get the vendor
590
	 *
591
	 * Copy of \OC\Updater::getVendor()
592
	 */
593
	private function getVendor() {
594
		// this should really be a JSON file
595
		require \OC::$SERVERROOT . '/version.php';
596
		/** @var string $vendor */
597
		return (string)$vendor;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $vendor seems to be never defined.
Loading history...
598
	}
599
}
600