Passed
Push — master ( 51add7...7917f4 )
by Julius
13:12 queued 12s
created
core/Controller/WhatsNewController.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,89 +38,89 @@
 block discarded – undo
38 38
 
39 39
 class WhatsNewController extends OCSController {
40 40
 
41
-	/** @var IConfig */
42
-	protected $config;
43
-	/** @var IUserSession */
44
-	private $userSession;
45
-	/** @var ChangesCheck */
46
-	private $whatsNewService;
47
-	/** @var IFactory */
48
-	private $langFactory;
49
-	/** @var Defaults */
50
-	private $defaults;
41
+    /** @var IConfig */
42
+    protected $config;
43
+    /** @var IUserSession */
44
+    private $userSession;
45
+    /** @var ChangesCheck */
46
+    private $whatsNewService;
47
+    /** @var IFactory */
48
+    private $langFactory;
49
+    /** @var Defaults */
50
+    private $defaults;
51 51
 
52
-	public function __construct(
53
-		string $appName,
54
-		IRequest $request,
55
-		CapabilitiesManager $capabilitiesManager,
56
-		IUserSession $userSession,
57
-		IUserManager $userManager,
58
-		Manager $keyManager,
59
-		IConfig $config,
60
-		ChangesCheck $whatsNewService,
61
-		IFactory $langFactory,
62
-		Defaults $defaults
63
-	) {
64
-		parent::__construct($appName, $request, $capabilitiesManager, $userSession, $userManager, $keyManager);
65
-		$this->config = $config;
66
-		$this->userSession = $userSession;
67
-		$this->whatsNewService = $whatsNewService;
68
-		$this->langFactory = $langFactory;
69
-		$this->defaults = $defaults;
70
-	}
52
+    public function __construct(
53
+        string $appName,
54
+        IRequest $request,
55
+        CapabilitiesManager $capabilitiesManager,
56
+        IUserSession $userSession,
57
+        IUserManager $userManager,
58
+        Manager $keyManager,
59
+        IConfig $config,
60
+        ChangesCheck $whatsNewService,
61
+        IFactory $langFactory,
62
+        Defaults $defaults
63
+    ) {
64
+        parent::__construct($appName, $request, $capabilitiesManager, $userSession, $userManager, $keyManager);
65
+        $this->config = $config;
66
+        $this->userSession = $userSession;
67
+        $this->whatsNewService = $whatsNewService;
68
+        $this->langFactory = $langFactory;
69
+        $this->defaults = $defaults;
70
+    }
71 71
 
72
-	/**
73
-	 * @NoAdminRequired
74
-	 */
75
-	public function get():DataResponse {
76
-		$user = $this->userSession->getUser();
77
-		if ($user === null) {
78
-			throw new \RuntimeException("Acting user cannot be resolved");
79
-		}
80
-		$lastRead = $this->config->getUserValue($user->getUID(), 'core', 'whatsNewLastRead', 0);
81
-		$currentVersion = $this->whatsNewService->normalizeVersion($this->config->getSystemValue('version'));
72
+    /**
73
+     * @NoAdminRequired
74
+     */
75
+    public function get():DataResponse {
76
+        $user = $this->userSession->getUser();
77
+        if ($user === null) {
78
+            throw new \RuntimeException("Acting user cannot be resolved");
79
+        }
80
+        $lastRead = $this->config->getUserValue($user->getUID(), 'core', 'whatsNewLastRead', 0);
81
+        $currentVersion = $this->whatsNewService->normalizeVersion($this->config->getSystemValue('version'));
82 82
 
83
-		if (version_compare($lastRead, $currentVersion, '>=')) {
84
-			return new DataResponse([], Http::STATUS_NO_CONTENT);
85
-		}
83
+        if (version_compare($lastRead, $currentVersion, '>=')) {
84
+            return new DataResponse([], Http::STATUS_NO_CONTENT);
85
+        }
86 86
 
87
-		try {
88
-			$iterator = $this->langFactory->getLanguageIterator();
89
-			$whatsNew = $this->whatsNewService->getChangesForVersion($currentVersion);
90
-			$resultData = [
91
-				'changelogURL' => $whatsNew['changelogURL'],
92
-				'product' => $this->defaults->getProductName(),
93
-				'version' => $currentVersion,
94
-			];
95
-			do {
96
-				$lang = $iterator->current();
97
-				if (isset($whatsNew['whatsNew'][$lang])) {
98
-					$resultData['whatsNew'] = $whatsNew['whatsNew'][$lang];
99
-					break;
100
-				}
101
-				$iterator->next();
102
-			} while ($lang !== 'en' && $iterator->valid());
103
-			return new DataResponse($resultData);
104
-		} catch (DoesNotExistException $e) {
105
-			return new DataResponse([], Http::STATUS_NO_CONTENT);
106
-		}
107
-	}
87
+        try {
88
+            $iterator = $this->langFactory->getLanguageIterator();
89
+            $whatsNew = $this->whatsNewService->getChangesForVersion($currentVersion);
90
+            $resultData = [
91
+                'changelogURL' => $whatsNew['changelogURL'],
92
+                'product' => $this->defaults->getProductName(),
93
+                'version' => $currentVersion,
94
+            ];
95
+            do {
96
+                $lang = $iterator->current();
97
+                if (isset($whatsNew['whatsNew'][$lang])) {
98
+                    $resultData['whatsNew'] = $whatsNew['whatsNew'][$lang];
99
+                    break;
100
+                }
101
+                $iterator->next();
102
+            } while ($lang !== 'en' && $iterator->valid());
103
+            return new DataResponse($resultData);
104
+        } catch (DoesNotExistException $e) {
105
+            return new DataResponse([], Http::STATUS_NO_CONTENT);
106
+        }
107
+    }
108 108
 
109
-	/**
110
-	 * @NoAdminRequired
111
-	 *
112
-	 * @throws \OCP\PreConditionNotMetException
113
-	 * @throws DoesNotExistException
114
-	 */
115
-	public function dismiss(string $version):DataResponse {
116
-		$user = $this->userSession->getUser();
117
-		if ($user === null) {
118
-			throw new \RuntimeException("Acting user cannot be resolved");
119
-		}
120
-		$version = $this->whatsNewService->normalizeVersion($version);
121
-		// checks whether it's a valid version, throws an Exception otherwise
122
-		$this->whatsNewService->getChangesForVersion($version);
123
-		$this->config->setUserValue($user->getUID(), 'core', 'whatsNewLastRead', $version);
124
-		return new DataResponse();
125
-	}
109
+    /**
110
+     * @NoAdminRequired
111
+     *
112
+     * @throws \OCP\PreConditionNotMetException
113
+     * @throws DoesNotExistException
114
+     */
115
+    public function dismiss(string $version):DataResponse {
116
+        $user = $this->userSession->getUser();
117
+        if ($user === null) {
118
+            throw new \RuntimeException("Acting user cannot be resolved");
119
+        }
120
+        $version = $this->whatsNewService->normalizeVersion($version);
121
+        // checks whether it's a valid version, throws an Exception otherwise
122
+        $this->whatsNewService->getChangesForVersion($version);
123
+        $this->config->setUserValue($user->getUID(), 'core', 'whatsNewLastRead', $version);
124
+        return new DataResponse();
125
+    }
126 126
 }
Please login to merge, or discard this patch.
apps/theming/lib/ThemingDefaults.php 1 patch
Indentation   +397 added lines, -397 removed lines patch added patch discarded remove patch
@@ -51,401 +51,401 @@
 block discarded – undo
51 51
 
52 52
 class ThemingDefaults extends \OC_Defaults {
53 53
 
54
-	/** @var IConfig */
55
-	private $config;
56
-	/** @var IL10N */
57
-	private $l;
58
-	/** @var ImageManager */
59
-	private $imageManager;
60
-	/** @var IURLGenerator */
61
-	private $urlGenerator;
62
-	/** @var ICacheFactory */
63
-	private $cacheFactory;
64
-	/** @var Util */
65
-	private $util;
66
-	/** @var IAppManager */
67
-	private $appManager;
68
-	/** @var INavigationManager */
69
-	private $navigationManager;
70
-
71
-	/** @var string */
72
-	private $name;
73
-	/** @var string */
74
-	private $title;
75
-	/** @var string */
76
-	private $entity;
77
-	/** @var string */
78
-	private $productName;
79
-	/** @var string */
80
-	private $url;
81
-	/** @var string */
82
-	private $color;
83
-
84
-	/** @var string */
85
-	private $iTunesAppId;
86
-	/** @var string */
87
-	private $iOSClientUrl;
88
-	/** @var string */
89
-	private $AndroidClientUrl;
90
-
91
-	/**
92
-	 * ThemingDefaults constructor.
93
-	 *
94
-	 * @param IConfig $config
95
-	 * @param IL10N $l
96
-	 * @param ImageManager $imageManager
97
-	 * @param IURLGenerator $urlGenerator
98
-	 * @param ICacheFactory $cacheFactory
99
-	 * @param Util $util
100
-	 * @param IAppManager $appManager
101
-	 */
102
-	public function __construct(IConfig $config,
103
-								IL10N $l,
104
-								IURLGenerator $urlGenerator,
105
-								ICacheFactory $cacheFactory,
106
-								Util $util,
107
-								ImageManager $imageManager,
108
-								IAppManager $appManager,
109
-								INavigationManager $navigationManager
110
-	) {
111
-		parent::__construct();
112
-		$this->config = $config;
113
-		$this->l = $l;
114
-		$this->imageManager = $imageManager;
115
-		$this->urlGenerator = $urlGenerator;
116
-		$this->cacheFactory = $cacheFactory;
117
-		$this->util = $util;
118
-		$this->appManager = $appManager;
119
-		$this->navigationManager = $navigationManager;
120
-
121
-		$this->name = parent::getName();
122
-		$this->title = parent::getTitle();
123
-		$this->entity = parent::getEntity();
124
-		$this->productName = parent::getName();
125
-		$this->url = parent::getBaseUrl();
126
-		$this->color = parent::getColorPrimary();
127
-		$this->iTunesAppId = parent::getiTunesAppId();
128
-		$this->iOSClientUrl = parent::getiOSClientUrl();
129
-		$this->AndroidClientUrl = parent::getAndroidClientUrl();
130
-	}
131
-
132
-	public function getName() {
133
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
134
-	}
135
-
136
-	public function getHTMLName() {
137
-		return $this->config->getAppValue('theming', 'name', $this->name);
138
-	}
139
-
140
-	public function getTitle() {
141
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
142
-	}
143
-
144
-	public function getEntity() {
145
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
146
-	}
147
-
148
-	public function getProductName() {
149
-		return strip_tags($this->config->getAppValue('theming', 'productName', $this->productName));
150
-	}
151
-
152
-	public function getBaseUrl() {
153
-		return $this->config->getAppValue('theming', 'url', $this->url);
154
-	}
155
-
156
-	public function getSlogan(?string $lang = null) {
157
-		return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', parent::getSlogan($lang)));
158
-	}
159
-
160
-	public function getImprintUrl() {
161
-		return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
162
-	}
163
-
164
-	public function getPrivacyUrl() {
165
-		return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
166
-	}
167
-
168
-	public function getShortFooter() {
169
-		$slogan = $this->getSlogan();
170
-		$baseUrl = $this->getBaseUrl();
171
-		if ($baseUrl !== '') {
172
-			$footer = '<a href="' . $baseUrl . '" target="_blank"' .
173
-				' rel="noreferrer noopener" class="entity-name">' . $this->getEntity() . '</a>';
174
-		} else {
175
-			$footer = '<span class="entity-name">' .$this->getEntity() . '</span>';
176
-		}
177
-		$footer .= ($slogan !== '' ? ' – ' . $slogan : '');
178
-
179
-		$links = [
180
-			[
181
-				'text' => $this->l->t('Legal notice'),
182
-				'url' => (string)$this->getImprintUrl()
183
-			],
184
-			[
185
-				'text' => $this->l->t('Privacy policy'),
186
-				'url' => (string)$this->getPrivacyUrl()
187
-			],
188
-		];
189
-
190
-		$navigation = $this->navigationManager->getAll(INavigationManager::TYPE_GUEST);
191
-		$guestNavigation = array_map(function ($nav) {
192
-			return [
193
-				'text' => $nav['name'],
194
-				'url' => $nav['href']
195
-			];
196
-		}, $navigation);
197
-		$links = array_merge($links, $guestNavigation);
198
-
199
-		$legalLinks = '';
200
-		$divider = '';
201
-		foreach ($links as $link) {
202
-			if ($link['url'] !== ''
203
-				&& filter_var($link['url'], FILTER_VALIDATE_URL)
204
-			) {
205
-				$legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
206
-					' rel="noreferrer noopener">' . $link['text'] . '</a>';
207
-				$divider = ' · ';
208
-			}
209
-		}
210
-		if ($legalLinks !== '') {
211
-			$footer .= '<br/>' . $legalLinks;
212
-		}
213
-
214
-		return $footer;
215
-	}
216
-
217
-	/**
218
-	 * Color that is used for the header as well as for mail headers
219
-	 *
220
-	 * @return string
221
-	 */
222
-	public function getColorPrimary() {
223
-		return $this->config->getAppValue('theming', 'color', $this->color);
224
-	}
225
-
226
-	/**
227
-	 * Themed logo url
228
-	 *
229
-	 * @param bool $useSvg Whether to point to the SVG image or a fallback
230
-	 * @return string
231
-	 */
232
-	public function getLogo($useSvg = true): string {
233
-		$logo = $this->config->getAppValue('theming', 'logoMime', '');
234
-
235
-		// short cut to avoid setting up the filesystem just to check if the logo is there
236
-		//
237
-		// explanation: if an SVG is requested and the app config value for logoMime is set then the logo is there.
238
-		// otherwise we need to check it and maybe also generate a PNG from the SVG (that's done in getImage() which
239
-		// needs to be called then)
240
-		if ($useSvg === true && $logo !== false) {
241
-			$logoExists = true;
242
-		} else {
243
-			try {
244
-				$this->imageManager->getImage('logo', $useSvg);
245
-				$logoExists = true;
246
-			} catch (\Exception $e) {
247
-				$logoExists = false;
248
-			}
249
-		}
250
-
251
-		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
252
-
253
-		if (!$logo || !$logoExists) {
254
-			if ($useSvg) {
255
-				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.svg');
256
-			} else {
257
-				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.png');
258
-			}
259
-			return $logo . '?v=' . $cacheBusterCounter;
260
-		}
261
-
262
-		return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
263
-	}
264
-
265
-	/**
266
-	 * Themed background image url
267
-	 *
268
-	 * @return string
269
-	 */
270
-	public function getBackground(): string {
271
-		return $this->imageManager->getImageUrl('background');
272
-	}
273
-
274
-	/**
275
-	 * @return string
276
-	 */
277
-	public function getiTunesAppId() {
278
-		return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
279
-	}
280
-
281
-	/**
282
-	 * @return string
283
-	 */
284
-	public function getiOSClientUrl() {
285
-		return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
286
-	}
287
-
288
-	/**
289
-	 * @return string
290
-	 */
291
-	public function getAndroidClientUrl() {
292
-		return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
293
-	}
294
-
295
-
296
-	/**
297
-	 * @return array scss variables to overwrite
298
-	 */
299
-	public function getScssVariables() {
300
-		$cacheBuster = $this->config->getAppValue('theming', 'cachebuster', '0');
301
-		$cache = $this->cacheFactory->createDistributed('theming-' . $cacheBuster . '-' . $this->urlGenerator->getBaseUrl());
302
-		if ($value = $cache->get('getScssVariables')) {
303
-			return $value;
304
-		}
305
-
306
-		$variables = [
307
-			'theming-cachebuster' => "'" . $cacheBuster . "'",
308
-			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime') . "'",
309
-			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime') . "'",
310
-			'theming-logoheader-mime' => "'" . $this->config->getAppValue('theming', 'logoheaderMime') . "'",
311
-			'theming-favicon-mime' => "'" . $this->config->getAppValue('theming', 'faviconMime') . "'"
312
-		];
313
-
314
-		$variables['image-logo'] = "url('".$this->imageManager->getImageUrl('logo')."')";
315
-		$variables['image-logoheader'] = "url('".$this->imageManager->getImageUrl('logoheader')."')";
316
-		$variables['image-favicon'] = "url('".$this->imageManager->getImageUrl('favicon')."')";
317
-		$variables['image-login-background'] = "url('".$this->imageManager->getImageUrl('background')."')";
318
-		$variables['image-login-plain'] = 'false';
319
-
320
-		if ($this->config->getAppValue('theming', 'color', '') !== '') {
321
-			$variables['color-primary'] = $this->getColorPrimary();
322
-			$variables['color-primary-text'] = $this->getTextColorPrimary();
323
-			$variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
324
-		}
325
-
326
-		if ($this->config->getAppValue('theming', 'backgroundMime', '') === 'backgroundColor') {
327
-			$variables['image-login-plain'] = 'true';
328
-		}
329
-
330
-		$variables['has-legal-links'] = 'false';
331
-		if ($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
332
-			$variables['has-legal-links'] = 'true';
333
-		}
334
-
335
-		$cache->set('getScssVariables', $variables);
336
-		return $variables;
337
-	}
338
-
339
-	/**
340
-	 * Check if the image should be replaced by the theming app
341
-	 * and return the new image location then
342
-	 *
343
-	 * @param string $app name of the app
344
-	 * @param string $image filename of the image
345
-	 * @return bool|string false if image should not replaced, otherwise the location of the image
346
-	 */
347
-	public function replaceImagePath($app, $image) {
348
-		if ($app === '' || $app === 'files_sharing') {
349
-			$app = 'core';
350
-		}
351
-		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
352
-
353
-		try {
354
-			$customFavicon = $this->imageManager->getImage('favicon');
355
-		} catch (NotFoundException $e) {
356
-			$customFavicon = null;
357
-		}
358
-
359
-		$route = false;
360
-		if ($image === 'favicon.ico' && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
361
-			$route = $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]);
362
-		}
363
-		if (($image === 'favicon-touch.png' || $image === 'favicon-fb.png') && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
364
-			$route = $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]);
365
-		}
366
-		if ($image === 'manifest.json') {
367
-			try {
368
-				$appPath = $this->appManager->getAppPath($app);
369
-				if (file_exists($appPath . '/img/manifest.json')) {
370
-					return false;
371
-				}
372
-			} catch (AppPathNotFoundException $e) {
373
-			}
374
-			$route = $this->urlGenerator->linkToRoute('theming.Theming.getManifest');
375
-		}
376
-		if (strpos($image, 'filetypes/') === 0 && file_exists(\OC::$SERVERROOT . '/core/img/' . $image)) {
377
-			$route = $this->urlGenerator->linkToRoute('theming.Icon.getThemedIcon', ['app' => $app, 'image' => $image]);
378
-		}
379
-
380
-		if ($route) {
381
-			return $route . '?v=' . $cacheBusterValue;
382
-		}
383
-
384
-		return false;
385
-	}
386
-
387
-	/**
388
-	 * Increases the cache buster key
389
-	 */
390
-	private function increaseCacheBuster() {
391
-		$cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
392
-		$this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey + 1);
393
-		$this->cacheFactory->createDistributed('theming-')->clear();
394
-		$this->cacheFactory->createDistributed('imagePath')->clear();
395
-	}
396
-
397
-	/**
398
-	 * Update setting in the database
399
-	 *
400
-	 * @param string $setting
401
-	 * @param string $value
402
-	 */
403
-	public function set($setting, $value) {
404
-		$this->config->setAppValue('theming', $setting, $value);
405
-		$this->increaseCacheBuster();
406
-	}
407
-
408
-	/**
409
-	 * Revert settings to the default value
410
-	 *
411
-	 * @param string $setting setting which should be reverted
412
-	 * @return string default value
413
-	 */
414
-	public function undo($setting) {
415
-		$this->config->deleteAppValue('theming', $setting);
416
-		$this->increaseCacheBuster();
417
-
418
-		$returnValue = '';
419
-		switch ($setting) {
420
-			case 'name':
421
-				$returnValue = $this->getEntity();
422
-				break;
423
-			case 'url':
424
-				$returnValue = $this->getBaseUrl();
425
-				break;
426
-			case 'slogan':
427
-				$returnValue = $this->getSlogan();
428
-				break;
429
-			case 'color':
430
-				$returnValue = $this->getColorPrimary();
431
-				break;
432
-			case 'logo':
433
-			case 'logoheader':
434
-			case 'background':
435
-			case 'favicon':
436
-				$this->imageManager->delete($setting);
437
-				break;
438
-		}
439
-
440
-		return $returnValue;
441
-	}
442
-
443
-	/**
444
-	 * Color of text in the header and primary buttons
445
-	 *
446
-	 * @return string
447
-	 */
448
-	public function getTextColorPrimary() {
449
-		return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
450
-	}
54
+    /** @var IConfig */
55
+    private $config;
56
+    /** @var IL10N */
57
+    private $l;
58
+    /** @var ImageManager */
59
+    private $imageManager;
60
+    /** @var IURLGenerator */
61
+    private $urlGenerator;
62
+    /** @var ICacheFactory */
63
+    private $cacheFactory;
64
+    /** @var Util */
65
+    private $util;
66
+    /** @var IAppManager */
67
+    private $appManager;
68
+    /** @var INavigationManager */
69
+    private $navigationManager;
70
+
71
+    /** @var string */
72
+    private $name;
73
+    /** @var string */
74
+    private $title;
75
+    /** @var string */
76
+    private $entity;
77
+    /** @var string */
78
+    private $productName;
79
+    /** @var string */
80
+    private $url;
81
+    /** @var string */
82
+    private $color;
83
+
84
+    /** @var string */
85
+    private $iTunesAppId;
86
+    /** @var string */
87
+    private $iOSClientUrl;
88
+    /** @var string */
89
+    private $AndroidClientUrl;
90
+
91
+    /**
92
+     * ThemingDefaults constructor.
93
+     *
94
+     * @param IConfig $config
95
+     * @param IL10N $l
96
+     * @param ImageManager $imageManager
97
+     * @param IURLGenerator $urlGenerator
98
+     * @param ICacheFactory $cacheFactory
99
+     * @param Util $util
100
+     * @param IAppManager $appManager
101
+     */
102
+    public function __construct(IConfig $config,
103
+                                IL10N $l,
104
+                                IURLGenerator $urlGenerator,
105
+                                ICacheFactory $cacheFactory,
106
+                                Util $util,
107
+                                ImageManager $imageManager,
108
+                                IAppManager $appManager,
109
+                                INavigationManager $navigationManager
110
+    ) {
111
+        parent::__construct();
112
+        $this->config = $config;
113
+        $this->l = $l;
114
+        $this->imageManager = $imageManager;
115
+        $this->urlGenerator = $urlGenerator;
116
+        $this->cacheFactory = $cacheFactory;
117
+        $this->util = $util;
118
+        $this->appManager = $appManager;
119
+        $this->navigationManager = $navigationManager;
120
+
121
+        $this->name = parent::getName();
122
+        $this->title = parent::getTitle();
123
+        $this->entity = parent::getEntity();
124
+        $this->productName = parent::getName();
125
+        $this->url = parent::getBaseUrl();
126
+        $this->color = parent::getColorPrimary();
127
+        $this->iTunesAppId = parent::getiTunesAppId();
128
+        $this->iOSClientUrl = parent::getiOSClientUrl();
129
+        $this->AndroidClientUrl = parent::getAndroidClientUrl();
130
+    }
131
+
132
+    public function getName() {
133
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
134
+    }
135
+
136
+    public function getHTMLName() {
137
+        return $this->config->getAppValue('theming', 'name', $this->name);
138
+    }
139
+
140
+    public function getTitle() {
141
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
142
+    }
143
+
144
+    public function getEntity() {
145
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
146
+    }
147
+
148
+    public function getProductName() {
149
+        return strip_tags($this->config->getAppValue('theming', 'productName', $this->productName));
150
+    }
151
+
152
+    public function getBaseUrl() {
153
+        return $this->config->getAppValue('theming', 'url', $this->url);
154
+    }
155
+
156
+    public function getSlogan(?string $lang = null) {
157
+        return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', parent::getSlogan($lang)));
158
+    }
159
+
160
+    public function getImprintUrl() {
161
+        return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
162
+    }
163
+
164
+    public function getPrivacyUrl() {
165
+        return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
166
+    }
167
+
168
+    public function getShortFooter() {
169
+        $slogan = $this->getSlogan();
170
+        $baseUrl = $this->getBaseUrl();
171
+        if ($baseUrl !== '') {
172
+            $footer = '<a href="' . $baseUrl . '" target="_blank"' .
173
+                ' rel="noreferrer noopener" class="entity-name">' . $this->getEntity() . '</a>';
174
+        } else {
175
+            $footer = '<span class="entity-name">' .$this->getEntity() . '</span>';
176
+        }
177
+        $footer .= ($slogan !== '' ? ' – ' . $slogan : '');
178
+
179
+        $links = [
180
+            [
181
+                'text' => $this->l->t('Legal notice'),
182
+                'url' => (string)$this->getImprintUrl()
183
+            ],
184
+            [
185
+                'text' => $this->l->t('Privacy policy'),
186
+                'url' => (string)$this->getPrivacyUrl()
187
+            ],
188
+        ];
189
+
190
+        $navigation = $this->navigationManager->getAll(INavigationManager::TYPE_GUEST);
191
+        $guestNavigation = array_map(function ($nav) {
192
+            return [
193
+                'text' => $nav['name'],
194
+                'url' => $nav['href']
195
+            ];
196
+        }, $navigation);
197
+        $links = array_merge($links, $guestNavigation);
198
+
199
+        $legalLinks = '';
200
+        $divider = '';
201
+        foreach ($links as $link) {
202
+            if ($link['url'] !== ''
203
+                && filter_var($link['url'], FILTER_VALIDATE_URL)
204
+            ) {
205
+                $legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
206
+                    ' rel="noreferrer noopener">' . $link['text'] . '</a>';
207
+                $divider = ' · ';
208
+            }
209
+        }
210
+        if ($legalLinks !== '') {
211
+            $footer .= '<br/>' . $legalLinks;
212
+        }
213
+
214
+        return $footer;
215
+    }
216
+
217
+    /**
218
+     * Color that is used for the header as well as for mail headers
219
+     *
220
+     * @return string
221
+     */
222
+    public function getColorPrimary() {
223
+        return $this->config->getAppValue('theming', 'color', $this->color);
224
+    }
225
+
226
+    /**
227
+     * Themed logo url
228
+     *
229
+     * @param bool $useSvg Whether to point to the SVG image or a fallback
230
+     * @return string
231
+     */
232
+    public function getLogo($useSvg = true): string {
233
+        $logo = $this->config->getAppValue('theming', 'logoMime', '');
234
+
235
+        // short cut to avoid setting up the filesystem just to check if the logo is there
236
+        //
237
+        // explanation: if an SVG is requested and the app config value for logoMime is set then the logo is there.
238
+        // otherwise we need to check it and maybe also generate a PNG from the SVG (that's done in getImage() which
239
+        // needs to be called then)
240
+        if ($useSvg === true && $logo !== false) {
241
+            $logoExists = true;
242
+        } else {
243
+            try {
244
+                $this->imageManager->getImage('logo', $useSvg);
245
+                $logoExists = true;
246
+            } catch (\Exception $e) {
247
+                $logoExists = false;
248
+            }
249
+        }
250
+
251
+        $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
252
+
253
+        if (!$logo || !$logoExists) {
254
+            if ($useSvg) {
255
+                $logo = $this->urlGenerator->imagePath('core', 'logo/logo.svg');
256
+            } else {
257
+                $logo = $this->urlGenerator->imagePath('core', 'logo/logo.png');
258
+            }
259
+            return $logo . '?v=' . $cacheBusterCounter;
260
+        }
261
+
262
+        return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
263
+    }
264
+
265
+    /**
266
+     * Themed background image url
267
+     *
268
+     * @return string
269
+     */
270
+    public function getBackground(): string {
271
+        return $this->imageManager->getImageUrl('background');
272
+    }
273
+
274
+    /**
275
+     * @return string
276
+     */
277
+    public function getiTunesAppId() {
278
+        return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
279
+    }
280
+
281
+    /**
282
+     * @return string
283
+     */
284
+    public function getiOSClientUrl() {
285
+        return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
286
+    }
287
+
288
+    /**
289
+     * @return string
290
+     */
291
+    public function getAndroidClientUrl() {
292
+        return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
293
+    }
294
+
295
+
296
+    /**
297
+     * @return array scss variables to overwrite
298
+     */
299
+    public function getScssVariables() {
300
+        $cacheBuster = $this->config->getAppValue('theming', 'cachebuster', '0');
301
+        $cache = $this->cacheFactory->createDistributed('theming-' . $cacheBuster . '-' . $this->urlGenerator->getBaseUrl());
302
+        if ($value = $cache->get('getScssVariables')) {
303
+            return $value;
304
+        }
305
+
306
+        $variables = [
307
+            'theming-cachebuster' => "'" . $cacheBuster . "'",
308
+            'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime') . "'",
309
+            'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime') . "'",
310
+            'theming-logoheader-mime' => "'" . $this->config->getAppValue('theming', 'logoheaderMime') . "'",
311
+            'theming-favicon-mime' => "'" . $this->config->getAppValue('theming', 'faviconMime') . "'"
312
+        ];
313
+
314
+        $variables['image-logo'] = "url('".$this->imageManager->getImageUrl('logo')."')";
315
+        $variables['image-logoheader'] = "url('".$this->imageManager->getImageUrl('logoheader')."')";
316
+        $variables['image-favicon'] = "url('".$this->imageManager->getImageUrl('favicon')."')";
317
+        $variables['image-login-background'] = "url('".$this->imageManager->getImageUrl('background')."')";
318
+        $variables['image-login-plain'] = 'false';
319
+
320
+        if ($this->config->getAppValue('theming', 'color', '') !== '') {
321
+            $variables['color-primary'] = $this->getColorPrimary();
322
+            $variables['color-primary-text'] = $this->getTextColorPrimary();
323
+            $variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
324
+        }
325
+
326
+        if ($this->config->getAppValue('theming', 'backgroundMime', '') === 'backgroundColor') {
327
+            $variables['image-login-plain'] = 'true';
328
+        }
329
+
330
+        $variables['has-legal-links'] = 'false';
331
+        if ($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
332
+            $variables['has-legal-links'] = 'true';
333
+        }
334
+
335
+        $cache->set('getScssVariables', $variables);
336
+        return $variables;
337
+    }
338
+
339
+    /**
340
+     * Check if the image should be replaced by the theming app
341
+     * and return the new image location then
342
+     *
343
+     * @param string $app name of the app
344
+     * @param string $image filename of the image
345
+     * @return bool|string false if image should not replaced, otherwise the location of the image
346
+     */
347
+    public function replaceImagePath($app, $image) {
348
+        if ($app === '' || $app === 'files_sharing') {
349
+            $app = 'core';
350
+        }
351
+        $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
352
+
353
+        try {
354
+            $customFavicon = $this->imageManager->getImage('favicon');
355
+        } catch (NotFoundException $e) {
356
+            $customFavicon = null;
357
+        }
358
+
359
+        $route = false;
360
+        if ($image === 'favicon.ico' && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
361
+            $route = $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]);
362
+        }
363
+        if (($image === 'favicon-touch.png' || $image === 'favicon-fb.png') && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
364
+            $route = $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]);
365
+        }
366
+        if ($image === 'manifest.json') {
367
+            try {
368
+                $appPath = $this->appManager->getAppPath($app);
369
+                if (file_exists($appPath . '/img/manifest.json')) {
370
+                    return false;
371
+                }
372
+            } catch (AppPathNotFoundException $e) {
373
+            }
374
+            $route = $this->urlGenerator->linkToRoute('theming.Theming.getManifest');
375
+        }
376
+        if (strpos($image, 'filetypes/') === 0 && file_exists(\OC::$SERVERROOT . '/core/img/' . $image)) {
377
+            $route = $this->urlGenerator->linkToRoute('theming.Icon.getThemedIcon', ['app' => $app, 'image' => $image]);
378
+        }
379
+
380
+        if ($route) {
381
+            return $route . '?v=' . $cacheBusterValue;
382
+        }
383
+
384
+        return false;
385
+    }
386
+
387
+    /**
388
+     * Increases the cache buster key
389
+     */
390
+    private function increaseCacheBuster() {
391
+        $cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
392
+        $this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey + 1);
393
+        $this->cacheFactory->createDistributed('theming-')->clear();
394
+        $this->cacheFactory->createDistributed('imagePath')->clear();
395
+    }
396
+
397
+    /**
398
+     * Update setting in the database
399
+     *
400
+     * @param string $setting
401
+     * @param string $value
402
+     */
403
+    public function set($setting, $value) {
404
+        $this->config->setAppValue('theming', $setting, $value);
405
+        $this->increaseCacheBuster();
406
+    }
407
+
408
+    /**
409
+     * Revert settings to the default value
410
+     *
411
+     * @param string $setting setting which should be reverted
412
+     * @return string default value
413
+     */
414
+    public function undo($setting) {
415
+        $this->config->deleteAppValue('theming', $setting);
416
+        $this->increaseCacheBuster();
417
+
418
+        $returnValue = '';
419
+        switch ($setting) {
420
+            case 'name':
421
+                $returnValue = $this->getEntity();
422
+                break;
423
+            case 'url':
424
+                $returnValue = $this->getBaseUrl();
425
+                break;
426
+            case 'slogan':
427
+                $returnValue = $this->getSlogan();
428
+                break;
429
+            case 'color':
430
+                $returnValue = $this->getColorPrimary();
431
+                break;
432
+            case 'logo':
433
+            case 'logoheader':
434
+            case 'background':
435
+            case 'favicon':
436
+                $this->imageManager->delete($setting);
437
+                break;
438
+        }
439
+
440
+        return $returnValue;
441
+    }
442
+
443
+    /**
444
+     * Color of text in the header and primary buttons
445
+     *
446
+     * @return string
447
+     */
448
+    public function getTextColorPrimary() {
449
+        return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
450
+    }
451 451
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareController.php 1 patch
Indentation   +661 added lines, -661 removed lines patch added patch discarded remove patch
@@ -84,667 +84,667 @@
 block discarded – undo
84 84
  */
85 85
 class ShareController extends AuthPublicShareController {
86 86
 
87
-	/** @var IConfig */
88
-	protected $config;
89
-	/** @var IUserManager */
90
-	protected $userManager;
91
-	/** @var ILogger */
92
-	protected $logger;
93
-	/** @var \OCP\Activity\IManager */
94
-	protected $activityManager;
95
-	/** @var IPreview */
96
-	protected $previewManager;
97
-	/** @var IRootFolder */
98
-	protected $rootFolder;
99
-	/** @var FederatedShareProvider */
100
-	protected $federatedShareProvider;
101
-	/** @var IAccountManager */
102
-	protected $accountManager;
103
-	/** @var IEventDispatcher */
104
-	protected $eventDispatcher;
105
-	/** @var IL10N */
106
-	protected $l10n;
107
-	/** @var Defaults */
108
-	protected $defaults;
109
-	/** @var ShareManager */
110
-	protected $shareManager;
111
-
112
-	/** @var Share\IShare */
113
-	protected $share;
114
-
115
-	/**
116
-	 * @param string $appName
117
-	 * @param IRequest $request
118
-	 * @param IConfig $config
119
-	 * @param IURLGenerator $urlGenerator
120
-	 * @param IUserManager $userManager
121
-	 * @param ILogger $logger
122
-	 * @param \OCP\Activity\IManager $activityManager
123
-	 * @param \OCP\Share\IManager $shareManager
124
-	 * @param ISession $session
125
-	 * @param IPreview $previewManager
126
-	 * @param IRootFolder $rootFolder
127
-	 * @param FederatedShareProvider $federatedShareProvider
128
-	 * @param IAccountManager $accountManager
129
-	 * @param IEventDispatcher $eventDispatcher
130
-	 * @param IL10N $l10n
131
-	 * @param Defaults $defaults
132
-	 */
133
-	public function __construct(string $appName,
134
-								IRequest $request,
135
-								IConfig $config,
136
-								IURLGenerator $urlGenerator,
137
-								IUserManager $userManager,
138
-								ILogger $logger,
139
-								\OCP\Activity\IManager $activityManager,
140
-								ShareManager $shareManager,
141
-								ISession $session,
142
-								IPreview $previewManager,
143
-								IRootFolder $rootFolder,
144
-								FederatedShareProvider $federatedShareProvider,
145
-								IAccountManager $accountManager,
146
-								IEventDispatcher $eventDispatcher,
147
-								IL10N $l10n,
148
-								Defaults $defaults) {
149
-		parent::__construct($appName, $request, $session, $urlGenerator);
150
-
151
-		$this->config = $config;
152
-		$this->userManager = $userManager;
153
-		$this->logger = $logger;
154
-		$this->activityManager = $activityManager;
155
-		$this->previewManager = $previewManager;
156
-		$this->rootFolder = $rootFolder;
157
-		$this->federatedShareProvider = $federatedShareProvider;
158
-		$this->accountManager = $accountManager;
159
-		$this->eventDispatcher = $eventDispatcher;
160
-		$this->l10n = $l10n;
161
-		$this->defaults = $defaults;
162
-		$this->shareManager = $shareManager;
163
-	}
164
-
165
-	/**
166
-	 * @PublicPage
167
-	 * @NoCSRFRequired
168
-	 *
169
-	 * Show the authentication page
170
-	 * The form has to submit to the authenticate method route
171
-	 */
172
-	public function showAuthenticate(): TemplateResponse {
173
-		$templateParameters = ['share' => $this->share];
174
-
175
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
176
-
177
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
178
-		if ($this->share->getSendPasswordByTalk()) {
179
-			$csp = new ContentSecurityPolicy();
180
-			$csp->addAllowedConnectDomain('*');
181
-			$csp->addAllowedMediaDomain('blob:');
182
-			$response->setContentSecurityPolicy($csp);
183
-		}
184
-
185
-		return $response;
186
-	}
187
-
188
-	/**
189
-	 * The template to show when authentication failed
190
-	 */
191
-	protected function showAuthFailed(): TemplateResponse {
192
-		$templateParameters = ['share' => $this->share, 'wrongpw' => true];
193
-
194
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
195
-
196
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
197
-		if ($this->share->getSendPasswordByTalk()) {
198
-			$csp = new ContentSecurityPolicy();
199
-			$csp->addAllowedConnectDomain('*');
200
-			$csp->addAllowedMediaDomain('blob:');
201
-			$response->setContentSecurityPolicy($csp);
202
-		}
203
-
204
-		return $response;
205
-	}
206
-
207
-	protected function verifyPassword(string $password): bool {
208
-		return $this->shareManager->checkPassword($this->share, $password);
209
-	}
210
-
211
-	protected function getPasswordHash(): string {
212
-		return $this->share->getPassword();
213
-	}
214
-
215
-	public function isValidToken(): bool {
216
-		try {
217
-			$this->share = $this->shareManager->getShareByToken($this->getToken());
218
-		} catch (ShareNotFound $e) {
219
-			return false;
220
-		}
221
-
222
-		return true;
223
-	}
224
-
225
-	protected function isPasswordProtected(): bool {
226
-		return $this->share->getPassword() !== null;
227
-	}
228
-
229
-	protected function authSucceeded() {
230
-		// For share this was always set so it is still used in other apps
231
-		$this->session->set('public_link_authenticated', (string)$this->share->getId());
232
-	}
233
-
234
-	protected function authFailed() {
235
-		$this->emitAccessShareHook($this->share, 403, 'Wrong password');
236
-	}
237
-
238
-	/**
239
-	 * throws hooks when a share is attempted to be accessed
240
-	 *
241
-	 * @param \OCP\Share\IShare|string $share the Share instance if available,
242
-	 * otherwise token
243
-	 * @param int $errorCode
244
-	 * @param string $errorMessage
245
-	 * @throws \OC\HintException
246
-	 * @throws \OC\ServerNotAvailableException
247
-	 */
248
-	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
249
-		$itemType = $itemSource = $uidOwner = '';
250
-		$token = $share;
251
-		$exception = null;
252
-		if ($share instanceof \OCP\Share\IShare) {
253
-			try {
254
-				$token = $share->getToken();
255
-				$uidOwner = $share->getSharedBy();
256
-				$itemType = $share->getNodeType();
257
-				$itemSource = $share->getNodeId();
258
-			} catch (\Exception $e) {
259
-				// we log what we know and pass on the exception afterwards
260
-				$exception = $e;
261
-			}
262
-		}
263
-		\OC_Hook::emit(Share::class, 'share_link_access', [
264
-			'itemType' => $itemType,
265
-			'itemSource' => $itemSource,
266
-			'uidOwner' => $uidOwner,
267
-			'token' => $token,
268
-			'errorCode' => $errorCode,
269
-			'errorMessage' => $errorMessage,
270
-		]);
271
-		if (!is_null($exception)) {
272
-			throw $exception;
273
-		}
274
-	}
275
-
276
-	/**
277
-	 * Validate the permissions of the share
278
-	 *
279
-	 * @param Share\IShare $share
280
-	 * @return bool
281
-	 */
282
-	private function validateShare(\OCP\Share\IShare $share) {
283
-		// If the owner is disabled no access to the linke is granted
284
-		$owner = $this->userManager->get($share->getShareOwner());
285
-		if ($owner === null || !$owner->isEnabled()) {
286
-			return false;
287
-		}
288
-
289
-		// If the initiator of the share is disabled no access is granted
290
-		$initiator = $this->userManager->get($share->getSharedBy());
291
-		if ($initiator === null || !$initiator->isEnabled()) {
292
-			return false;
293
-		}
294
-
295
-		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
296
-	}
297
-
298
-	/**
299
-	 * @PublicPage
300
-	 * @NoCSRFRequired
301
-	 *
302
-	 *
303
-	 * @param string $path
304
-	 * @return TemplateResponse
305
-	 * @throws NotFoundException
306
-	 * @throws \Exception
307
-	 */
308
-	public function showShare($path = ''): TemplateResponse {
309
-		\OC_User::setIncognitoMode(true);
310
-
311
-		// Check whether share exists
312
-		try {
313
-			$share = $this->shareManager->getShareByToken($this->getToken());
314
-		} catch (ShareNotFound $e) {
315
-			$this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
316
-			throw new NotFoundException();
317
-		}
318
-
319
-		if (!$this->validateShare($share)) {
320
-			throw new NotFoundException();
321
-		}
322
-
323
-		$shareNode = $share->getNode();
324
-
325
-		// We can't get the path of a file share
326
-		try {
327
-			if ($shareNode instanceof \OCP\Files\File && $path !== '') {
328
-				$this->emitAccessShareHook($share, 404, 'Share not found');
329
-				throw new NotFoundException();
330
-			}
331
-		} catch (\Exception $e) {
332
-			$this->emitAccessShareHook($share, 404, 'Share not found');
333
-			throw $e;
334
-		}
335
-
336
-		$shareTmpl = [];
337
-		$shareTmpl['owner'] = '';
338
-		$shareTmpl['shareOwner'] = '';
339
-
340
-		$owner = $this->userManager->get($share->getShareOwner());
341
-		if ($owner instanceof IUser) {
342
-			$ownerAccount = $this->accountManager->getAccount($owner);
343
-
344
-			$ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
345
-			if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
346
-				$shareTmpl['owner'] = $owner->getUID();
347
-				$shareTmpl['shareOwner'] = $owner->getDisplayName();
348
-			}
349
-		}
350
-
351
-		$shareTmpl['filename'] = $shareNode->getName();
352
-		$shareTmpl['directory_path'] = $share->getTarget();
353
-		$shareTmpl['note'] = $share->getNote();
354
-		$shareTmpl['mimetype'] = $shareNode->getMimetype();
355
-		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
356
-		$shareTmpl['dirToken'] = $this->getToken();
357
-		$shareTmpl['sharingToken'] = $this->getToken();
358
-		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
359
-		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
360
-		$shareTmpl['dir'] = '';
361
-		$shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
362
-		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
363
-		$shareTmpl['hideDownload'] = $share->getHideDownload();
364
-
365
-		$hideFileList = false;
366
-
367
-		if ($shareNode instanceof \OCP\Files\Folder) {
368
-			$shareIsFolder = true;
369
-
370
-			try {
371
-				$folderNode = $shareNode->get($path);
372
-			} catch (\OCP\Files\NotFoundException $e) {
373
-				$this->emitAccessShareHook($share, 404, 'Share not found');
374
-				throw new NotFoundException();
375
-			}
376
-
377
-			$shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
378
-
379
-			/*
87
+    /** @var IConfig */
88
+    protected $config;
89
+    /** @var IUserManager */
90
+    protected $userManager;
91
+    /** @var ILogger */
92
+    protected $logger;
93
+    /** @var \OCP\Activity\IManager */
94
+    protected $activityManager;
95
+    /** @var IPreview */
96
+    protected $previewManager;
97
+    /** @var IRootFolder */
98
+    protected $rootFolder;
99
+    /** @var FederatedShareProvider */
100
+    protected $federatedShareProvider;
101
+    /** @var IAccountManager */
102
+    protected $accountManager;
103
+    /** @var IEventDispatcher */
104
+    protected $eventDispatcher;
105
+    /** @var IL10N */
106
+    protected $l10n;
107
+    /** @var Defaults */
108
+    protected $defaults;
109
+    /** @var ShareManager */
110
+    protected $shareManager;
111
+
112
+    /** @var Share\IShare */
113
+    protected $share;
114
+
115
+    /**
116
+     * @param string $appName
117
+     * @param IRequest $request
118
+     * @param IConfig $config
119
+     * @param IURLGenerator $urlGenerator
120
+     * @param IUserManager $userManager
121
+     * @param ILogger $logger
122
+     * @param \OCP\Activity\IManager $activityManager
123
+     * @param \OCP\Share\IManager $shareManager
124
+     * @param ISession $session
125
+     * @param IPreview $previewManager
126
+     * @param IRootFolder $rootFolder
127
+     * @param FederatedShareProvider $federatedShareProvider
128
+     * @param IAccountManager $accountManager
129
+     * @param IEventDispatcher $eventDispatcher
130
+     * @param IL10N $l10n
131
+     * @param Defaults $defaults
132
+     */
133
+    public function __construct(string $appName,
134
+                                IRequest $request,
135
+                                IConfig $config,
136
+                                IURLGenerator $urlGenerator,
137
+                                IUserManager $userManager,
138
+                                ILogger $logger,
139
+                                \OCP\Activity\IManager $activityManager,
140
+                                ShareManager $shareManager,
141
+                                ISession $session,
142
+                                IPreview $previewManager,
143
+                                IRootFolder $rootFolder,
144
+                                FederatedShareProvider $federatedShareProvider,
145
+                                IAccountManager $accountManager,
146
+                                IEventDispatcher $eventDispatcher,
147
+                                IL10N $l10n,
148
+                                Defaults $defaults) {
149
+        parent::__construct($appName, $request, $session, $urlGenerator);
150
+
151
+        $this->config = $config;
152
+        $this->userManager = $userManager;
153
+        $this->logger = $logger;
154
+        $this->activityManager = $activityManager;
155
+        $this->previewManager = $previewManager;
156
+        $this->rootFolder = $rootFolder;
157
+        $this->federatedShareProvider = $federatedShareProvider;
158
+        $this->accountManager = $accountManager;
159
+        $this->eventDispatcher = $eventDispatcher;
160
+        $this->l10n = $l10n;
161
+        $this->defaults = $defaults;
162
+        $this->shareManager = $shareManager;
163
+    }
164
+
165
+    /**
166
+     * @PublicPage
167
+     * @NoCSRFRequired
168
+     *
169
+     * Show the authentication page
170
+     * The form has to submit to the authenticate method route
171
+     */
172
+    public function showAuthenticate(): TemplateResponse {
173
+        $templateParameters = ['share' => $this->share];
174
+
175
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
176
+
177
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
178
+        if ($this->share->getSendPasswordByTalk()) {
179
+            $csp = new ContentSecurityPolicy();
180
+            $csp->addAllowedConnectDomain('*');
181
+            $csp->addAllowedMediaDomain('blob:');
182
+            $response->setContentSecurityPolicy($csp);
183
+        }
184
+
185
+        return $response;
186
+    }
187
+
188
+    /**
189
+     * The template to show when authentication failed
190
+     */
191
+    protected function showAuthFailed(): TemplateResponse {
192
+        $templateParameters = ['share' => $this->share, 'wrongpw' => true];
193
+
194
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
195
+
196
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
197
+        if ($this->share->getSendPasswordByTalk()) {
198
+            $csp = new ContentSecurityPolicy();
199
+            $csp->addAllowedConnectDomain('*');
200
+            $csp->addAllowedMediaDomain('blob:');
201
+            $response->setContentSecurityPolicy($csp);
202
+        }
203
+
204
+        return $response;
205
+    }
206
+
207
+    protected function verifyPassword(string $password): bool {
208
+        return $this->shareManager->checkPassword($this->share, $password);
209
+    }
210
+
211
+    protected function getPasswordHash(): string {
212
+        return $this->share->getPassword();
213
+    }
214
+
215
+    public function isValidToken(): bool {
216
+        try {
217
+            $this->share = $this->shareManager->getShareByToken($this->getToken());
218
+        } catch (ShareNotFound $e) {
219
+            return false;
220
+        }
221
+
222
+        return true;
223
+    }
224
+
225
+    protected function isPasswordProtected(): bool {
226
+        return $this->share->getPassword() !== null;
227
+    }
228
+
229
+    protected function authSucceeded() {
230
+        // For share this was always set so it is still used in other apps
231
+        $this->session->set('public_link_authenticated', (string)$this->share->getId());
232
+    }
233
+
234
+    protected function authFailed() {
235
+        $this->emitAccessShareHook($this->share, 403, 'Wrong password');
236
+    }
237
+
238
+    /**
239
+     * throws hooks when a share is attempted to be accessed
240
+     *
241
+     * @param \OCP\Share\IShare|string $share the Share instance if available,
242
+     * otherwise token
243
+     * @param int $errorCode
244
+     * @param string $errorMessage
245
+     * @throws \OC\HintException
246
+     * @throws \OC\ServerNotAvailableException
247
+     */
248
+    protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
249
+        $itemType = $itemSource = $uidOwner = '';
250
+        $token = $share;
251
+        $exception = null;
252
+        if ($share instanceof \OCP\Share\IShare) {
253
+            try {
254
+                $token = $share->getToken();
255
+                $uidOwner = $share->getSharedBy();
256
+                $itemType = $share->getNodeType();
257
+                $itemSource = $share->getNodeId();
258
+            } catch (\Exception $e) {
259
+                // we log what we know and pass on the exception afterwards
260
+                $exception = $e;
261
+            }
262
+        }
263
+        \OC_Hook::emit(Share::class, 'share_link_access', [
264
+            'itemType' => $itemType,
265
+            'itemSource' => $itemSource,
266
+            'uidOwner' => $uidOwner,
267
+            'token' => $token,
268
+            'errorCode' => $errorCode,
269
+            'errorMessage' => $errorMessage,
270
+        ]);
271
+        if (!is_null($exception)) {
272
+            throw $exception;
273
+        }
274
+    }
275
+
276
+    /**
277
+     * Validate the permissions of the share
278
+     *
279
+     * @param Share\IShare $share
280
+     * @return bool
281
+     */
282
+    private function validateShare(\OCP\Share\IShare $share) {
283
+        // If the owner is disabled no access to the linke is granted
284
+        $owner = $this->userManager->get($share->getShareOwner());
285
+        if ($owner === null || !$owner->isEnabled()) {
286
+            return false;
287
+        }
288
+
289
+        // If the initiator of the share is disabled no access is granted
290
+        $initiator = $this->userManager->get($share->getSharedBy());
291
+        if ($initiator === null || !$initiator->isEnabled()) {
292
+            return false;
293
+        }
294
+
295
+        return $share->getNode()->isReadable() && $share->getNode()->isShareable();
296
+    }
297
+
298
+    /**
299
+     * @PublicPage
300
+     * @NoCSRFRequired
301
+     *
302
+     *
303
+     * @param string $path
304
+     * @return TemplateResponse
305
+     * @throws NotFoundException
306
+     * @throws \Exception
307
+     */
308
+    public function showShare($path = ''): TemplateResponse {
309
+        \OC_User::setIncognitoMode(true);
310
+
311
+        // Check whether share exists
312
+        try {
313
+            $share = $this->shareManager->getShareByToken($this->getToken());
314
+        } catch (ShareNotFound $e) {
315
+            $this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
316
+            throw new NotFoundException();
317
+        }
318
+
319
+        if (!$this->validateShare($share)) {
320
+            throw new NotFoundException();
321
+        }
322
+
323
+        $shareNode = $share->getNode();
324
+
325
+        // We can't get the path of a file share
326
+        try {
327
+            if ($shareNode instanceof \OCP\Files\File && $path !== '') {
328
+                $this->emitAccessShareHook($share, 404, 'Share not found');
329
+                throw new NotFoundException();
330
+            }
331
+        } catch (\Exception $e) {
332
+            $this->emitAccessShareHook($share, 404, 'Share not found');
333
+            throw $e;
334
+        }
335
+
336
+        $shareTmpl = [];
337
+        $shareTmpl['owner'] = '';
338
+        $shareTmpl['shareOwner'] = '';
339
+
340
+        $owner = $this->userManager->get($share->getShareOwner());
341
+        if ($owner instanceof IUser) {
342
+            $ownerAccount = $this->accountManager->getAccount($owner);
343
+
344
+            $ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
345
+            if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
346
+                $shareTmpl['owner'] = $owner->getUID();
347
+                $shareTmpl['shareOwner'] = $owner->getDisplayName();
348
+            }
349
+        }
350
+
351
+        $shareTmpl['filename'] = $shareNode->getName();
352
+        $shareTmpl['directory_path'] = $share->getTarget();
353
+        $shareTmpl['note'] = $share->getNote();
354
+        $shareTmpl['mimetype'] = $shareNode->getMimetype();
355
+        $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
356
+        $shareTmpl['dirToken'] = $this->getToken();
357
+        $shareTmpl['sharingToken'] = $this->getToken();
358
+        $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
359
+        $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
360
+        $shareTmpl['dir'] = '';
361
+        $shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
362
+        $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
363
+        $shareTmpl['hideDownload'] = $share->getHideDownload();
364
+
365
+        $hideFileList = false;
366
+
367
+        if ($shareNode instanceof \OCP\Files\Folder) {
368
+            $shareIsFolder = true;
369
+
370
+            try {
371
+                $folderNode = $shareNode->get($path);
372
+            } catch (\OCP\Files\NotFoundException $e) {
373
+                $this->emitAccessShareHook($share, 404, 'Share not found');
374
+                throw new NotFoundException();
375
+            }
376
+
377
+            $shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
378
+
379
+            /*
380 380
 			 * The OC_Util methods require a view. This just uses the node API
381 381
 			 */
382
-			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
383
-			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
384
-				$freeSpace = max($freeSpace, 0);
385
-			} else {
386
-				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
387
-			}
388
-
389
-			$hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
390
-			$maxUploadFilesize = $freeSpace;
391
-
392
-			$folder = new Template('files', 'list', '');
393
-
394
-			$folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
395
-			$folder->assign('dirToken', $this->getToken());
396
-			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
397
-			$folder->assign('isPublic', true);
398
-			$folder->assign('hideFileList', $hideFileList);
399
-			$folder->assign('publicUploadEnabled', 'no');
400
-			// default to list view
401
-			$folder->assign('showgridview', false);
402
-			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
403
-			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
404
-			$folder->assign('freeSpace', $freeSpace);
405
-			$folder->assign('usedSpacePercent', 0);
406
-			$folder->assign('trash', false);
407
-			$shareTmpl['folder'] = $folder->fetchPage();
408
-		} else {
409
-			$shareIsFolder = false;
410
-		}
411
-
412
-		// default to list view
413
-		$shareTmpl['showgridview'] = false;
414
-
415
-		$shareTmpl['hideFileList'] = $hideFileList;
416
-		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
417
-			'token' => $this->getToken(),
418
-			'filename' => $shareIsFolder ? null : $shareNode->getName()
419
-		]);
420
-		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
421
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
422
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
423
-		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
424
-		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
425
-		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
426
-		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
427
-
428
-		if ($shareTmpl['previewSupported']) {
429
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
430
-				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
431
-			$ogPreview = $shareTmpl['previewImage'];
432
-
433
-			// We just have direct previews for image files
434
-			if ($shareNode->getMimePart() === 'image') {
435
-				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
436
-
437
-				$ogPreview = $shareTmpl['previewURL'];
438
-
439
-				//Whatapp is kind of picky about their size requirements
440
-				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
441
-					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
442
-						'token' => $this->getToken(),
443
-						'x' => 256,
444
-						'y' => 256,
445
-						'a' => true,
446
-					]);
447
-				}
448
-			}
449
-		} else {
450
-			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
451
-			$ogPreview = $shareTmpl['previewImage'];
452
-		}
453
-
454
-		// Load files we need
455
-		\OCP\Util::addScript('files', 'semaphore');
456
-		\OCP\Util::addScript('files', 'file-upload');
457
-		\OCP\Util::addStyle('files_sharing', 'publicView');
458
-		\OCP\Util::addScript('files_sharing', 'public');
459
-		\OCP\Util::addScript('files_sharing', 'templates');
460
-		\OCP\Util::addScript('files', 'fileactions');
461
-		\OCP\Util::addScript('files', 'fileactionsmenu');
462
-		\OCP\Util::addScript('files', 'jquery.fileupload');
463
-		\OCP\Util::addScript('files_sharing', 'files_drop');
464
-
465
-		if (isset($shareTmpl['folder'])) {
466
-			// JS required for folders
467
-			\OCP\Util::addStyle('files', 'merged');
468
-			\OCP\Util::addScript('files', 'filesummary');
469
-			\OCP\Util::addScript('files', 'templates');
470
-			\OCP\Util::addScript('files', 'breadcrumb');
471
-			\OCP\Util::addScript('files', 'fileinfomodel');
472
-			\OCP\Util::addScript('files', 'newfilemenu');
473
-			\OCP\Util::addScript('files', 'files');
474
-			\OCP\Util::addScript('files', 'filemultiselectmenu');
475
-			\OCP\Util::addScript('files', 'filelist');
476
-			\OCP\Util::addScript('files', 'keyboardshortcuts');
477
-			\OCP\Util::addScript('files', 'operationprogressbar');
478
-
479
-			// Load Viewer scripts
480
-			if (class_exists(LoadViewer::class)) {
481
-				$this->eventDispatcher->dispatchTyped(new LoadViewer());
482
-			}
483
-		}
484
-
485
-		// OpenGraph Support: http://ogp.me/
486
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
487
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
488
-		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
489
-		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
490
-		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
491
-		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
492
-
493
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
494
-
495
-		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
496
-		$csp->addAllowedFrameDomain('\'self\'');
497
-
498
-		$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
499
-		$response->setHeaderTitle($shareTmpl['filename']);
500
-		if ($shareTmpl['shareOwner'] !== '') {
501
-			$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
502
-		}
503
-
504
-		$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
505
-
506
-		if ($isNoneFileDropFolder && !$share->getHideDownload()) {
507
-			\OCP\Util::addScript('files_sharing', 'public_note');
508
-
509
-			$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
510
-			$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
511
-			$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
512
-			$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
513
-			$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
514
-			// TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
515
-			$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your %s', [$this->defaults->getProductName()]), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
516
-
517
-			$responseComposer = [];
518
-
519
-			if ($shareIsFolder) {
520
-				$responseComposer[] = $downloadAllWhite;
521
-				$responseComposer[] = $downloadAll;
522
-			} else {
523
-				$responseComposer[] = $downloadWhite;
524
-				$responseComposer[] = $download;
525
-			}
526
-			$responseComposer[] = $directLink;
527
-			if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
528
-				$responseComposer[] = $externalShare;
529
-			}
530
-
531
-			$response->setHeaderActions($responseComposer);
532
-		}
533
-
534
-		$response->setContentSecurityPolicy($csp);
535
-
536
-		$this->emitAccessShareHook($share);
537
-
538
-		return $response;
539
-	}
540
-
541
-	/**
542
-	 * @PublicPage
543
-	 * @NoCSRFRequired
544
-	 * @NoSameSiteCookieRequired
545
-	 *
546
-	 * @param string $token
547
-	 * @param string $files
548
-	 * @param string $path
549
-	 * @param string $downloadStartSecret
550
-	 * @return void|\OCP\AppFramework\Http\Response
551
-	 * @throws NotFoundException
552
-	 */
553
-	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
554
-		\OC_User::setIncognitoMode(true);
555
-
556
-		$share = $this->shareManager->getShareByToken($token);
557
-
558
-		if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
559
-			return new \OCP\AppFramework\Http\DataResponse('Share has no read permission');
560
-		}
561
-
562
-		$files_list = null;
563
-		if (!is_null($files)) { // download selected files
564
-			$files_list = json_decode($files);
565
-			// in case we get only a single file
566
-			if ($files_list === null) {
567
-				$files_list = [$files];
568
-			}
569
-			// Just in case $files is a single int like '1234'
570
-			if (!is_array($files_list)) {
571
-				$files_list = [$files_list];
572
-			}
573
-		}
574
-
575
-		if (!$this->validateShare($share)) {
576
-			throw new NotFoundException();
577
-		}
578
-
579
-		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
580
-		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
581
-
582
-
583
-		// Single file share
584
-		if ($share->getNode() instanceof \OCP\Files\File) {
585
-			// Single file download
586
-			$this->singleFileDownloaded($share, $share->getNode());
587
-		}
588
-		// Directory share
589
-		else {
590
-			/** @var \OCP\Files\Folder $node */
591
-			$node = $share->getNode();
592
-
593
-			// Try to get the path
594
-			if ($path !== '') {
595
-				try {
596
-					$node = $node->get($path);
597
-				} catch (NotFoundException $e) {
598
-					$this->emitAccessShareHook($share, 404, 'Share not found');
599
-					return new NotFoundResponse();
600
-				}
601
-			}
602
-
603
-			$originalSharePath = $userFolder->getRelativePath($node->getPath());
604
-
605
-			if ($node instanceof \OCP\Files\File) {
606
-				// Single file download
607
-				$this->singleFileDownloaded($share, $share->getNode());
608
-			} else {
609
-				try {
610
-					if (!empty($files_list)) {
611
-						$this->fileListDownloaded($share, $files_list, $node);
612
-					} else {
613
-						// The folder is downloaded
614
-						$this->singleFileDownloaded($share, $share->getNode());
615
-					}
616
-				} catch (NotFoundException $e) {
617
-					return new NotFoundResponse();
618
-				}
619
-			}
620
-		}
621
-
622
-		/* FIXME: We should do this all nicely in OCP */
623
-		OC_Util::tearDownFS();
624
-		OC_Util::setupFS($share->getShareOwner());
625
-
626
-		/**
627
-		 * this sets a cookie to be able to recognize the start of the download
628
-		 * the content must not be longer than 32 characters and must only contain
629
-		 * alphanumeric characters
630
-		 */
631
-		if (!empty($downloadStartSecret)
632
-			&& !isset($downloadStartSecret[32])
633
-			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
634
-
635
-			// FIXME: set on the response once we use an actual app framework response
636
-			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
637
-		}
638
-
639
-		$this->emitAccessShareHook($share);
640
-
641
-		$server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
642
-
643
-		/**
644
-		 * Http range requests support
645
-		 */
646
-		if (isset($_SERVER['HTTP_RANGE'])) {
647
-			$server_params['range'] = $this->request->getHeader('Range');
648
-		}
649
-
650
-		// download selected files
651
-		if (!is_null($files) && $files !== '') {
652
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
653
-			// after dispatching the request which results in a "Cannot modify header information" notice.
654
-			OC_Files::get($originalSharePath, $files_list, $server_params);
655
-			exit();
656
-		} else {
657
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
658
-			// after dispatching the request which results in a "Cannot modify header information" notice.
659
-			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
660
-			exit();
661
-		}
662
-	}
663
-
664
-	/**
665
-	 * create activity for every downloaded file
666
-	 *
667
-	 * @param Share\IShare $share
668
-	 * @param array $files_list
669
-	 * @param \OCP\Files\Folder $node
670
-	 * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
671
-	 */
672
-	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
673
-		if ($share->getHideDownload() && count($files_list) > 1) {
674
-			throw new NotFoundException('Downloading more than 1 file');
675
-		}
676
-
677
-		foreach ($files_list as $file) {
678
-			$subNode = $node->get($file);
679
-			$this->singleFileDownloaded($share, $subNode);
680
-		}
681
-	}
682
-
683
-	/**
684
-	 * create activity if a single file was downloaded from a link share
685
-	 *
686
-	 * @param Share\IShare $share
687
-	 * @throws NotFoundException when trying to download a folder of a "hide download" share
688
-	 */
689
-	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
690
-		if ($share->getHideDownload() && $node instanceof Folder) {
691
-			throw new NotFoundException('Downloading a folder');
692
-		}
693
-
694
-		$fileId = $node->getId();
695
-
696
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
697
-		$userNodeList = $userFolder->getById($fileId);
698
-		$userNode = $userNodeList[0];
699
-		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
700
-		$userPath = $userFolder->getRelativePath($userNode->getPath());
701
-		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
702
-
703
-		$parameters = [$userPath];
704
-
705
-		if ($share->getShareType() === IShare::TYPE_EMAIL) {
706
-			if ($node instanceof \OCP\Files\File) {
707
-				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
708
-			} else {
709
-				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
710
-			}
711
-			$parameters[] = $share->getSharedWith();
712
-		} else {
713
-			if ($node instanceof \OCP\Files\File) {
714
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
715
-			} else {
716
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
717
-			}
718
-		}
719
-
720
-		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
721
-
722
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
723
-			$parameters[0] = $ownerPath;
724
-			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
725
-		}
726
-	}
727
-
728
-	/**
729
-	 * publish activity
730
-	 *
731
-	 * @param string $subject
732
-	 * @param array $parameters
733
-	 * @param string $affectedUser
734
-	 * @param int $fileId
735
-	 * @param string $filePath
736
-	 */
737
-	protected function publishActivity($subject,
738
-										array $parameters,
739
-										$affectedUser,
740
-										$fileId,
741
-										$filePath) {
742
-		$event = $this->activityManager->generateEvent();
743
-		$event->setApp('files_sharing')
744
-			->setType('public_links')
745
-			->setSubject($subject, $parameters)
746
-			->setAffectedUser($affectedUser)
747
-			->setObject('files', $fileId, $filePath);
748
-		$this->activityManager->publish($event);
749
-	}
382
+            $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
383
+            if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
384
+                $freeSpace = max($freeSpace, 0);
385
+            } else {
386
+                $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
387
+            }
388
+
389
+            $hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
390
+            $maxUploadFilesize = $freeSpace;
391
+
392
+            $folder = new Template('files', 'list', '');
393
+
394
+            $folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
395
+            $folder->assign('dirToken', $this->getToken());
396
+            $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
397
+            $folder->assign('isPublic', true);
398
+            $folder->assign('hideFileList', $hideFileList);
399
+            $folder->assign('publicUploadEnabled', 'no');
400
+            // default to list view
401
+            $folder->assign('showgridview', false);
402
+            $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
403
+            $folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
404
+            $folder->assign('freeSpace', $freeSpace);
405
+            $folder->assign('usedSpacePercent', 0);
406
+            $folder->assign('trash', false);
407
+            $shareTmpl['folder'] = $folder->fetchPage();
408
+        } else {
409
+            $shareIsFolder = false;
410
+        }
411
+
412
+        // default to list view
413
+        $shareTmpl['showgridview'] = false;
414
+
415
+        $shareTmpl['hideFileList'] = $hideFileList;
416
+        $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
417
+            'token' => $this->getToken(),
418
+            'filename' => $shareIsFolder ? null : $shareNode->getName()
419
+        ]);
420
+        $shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
421
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
422
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
423
+        $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
424
+        $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
425
+        $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
426
+        $shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
427
+
428
+        if ($shareTmpl['previewSupported']) {
429
+            $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
430
+                ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
431
+            $ogPreview = $shareTmpl['previewImage'];
432
+
433
+            // We just have direct previews for image files
434
+            if ($shareNode->getMimePart() === 'image') {
435
+                $shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
436
+
437
+                $ogPreview = $shareTmpl['previewURL'];
438
+
439
+                //Whatapp is kind of picky about their size requirements
440
+                if ($this->request->isUserAgent(['/^WhatsApp/'])) {
441
+                    $ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
442
+                        'token' => $this->getToken(),
443
+                        'x' => 256,
444
+                        'y' => 256,
445
+                        'a' => true,
446
+                    ]);
447
+                }
448
+            }
449
+        } else {
450
+            $shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
451
+            $ogPreview = $shareTmpl['previewImage'];
452
+        }
453
+
454
+        // Load files we need
455
+        \OCP\Util::addScript('files', 'semaphore');
456
+        \OCP\Util::addScript('files', 'file-upload');
457
+        \OCP\Util::addStyle('files_sharing', 'publicView');
458
+        \OCP\Util::addScript('files_sharing', 'public');
459
+        \OCP\Util::addScript('files_sharing', 'templates');
460
+        \OCP\Util::addScript('files', 'fileactions');
461
+        \OCP\Util::addScript('files', 'fileactionsmenu');
462
+        \OCP\Util::addScript('files', 'jquery.fileupload');
463
+        \OCP\Util::addScript('files_sharing', 'files_drop');
464
+
465
+        if (isset($shareTmpl['folder'])) {
466
+            // JS required for folders
467
+            \OCP\Util::addStyle('files', 'merged');
468
+            \OCP\Util::addScript('files', 'filesummary');
469
+            \OCP\Util::addScript('files', 'templates');
470
+            \OCP\Util::addScript('files', 'breadcrumb');
471
+            \OCP\Util::addScript('files', 'fileinfomodel');
472
+            \OCP\Util::addScript('files', 'newfilemenu');
473
+            \OCP\Util::addScript('files', 'files');
474
+            \OCP\Util::addScript('files', 'filemultiselectmenu');
475
+            \OCP\Util::addScript('files', 'filelist');
476
+            \OCP\Util::addScript('files', 'keyboardshortcuts');
477
+            \OCP\Util::addScript('files', 'operationprogressbar');
478
+
479
+            // Load Viewer scripts
480
+            if (class_exists(LoadViewer::class)) {
481
+                $this->eventDispatcher->dispatchTyped(new LoadViewer());
482
+            }
483
+        }
484
+
485
+        // OpenGraph Support: http://ogp.me/
486
+        \OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
487
+        \OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
488
+        \OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
489
+        \OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
490
+        \OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
491
+        \OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
492
+
493
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
494
+
495
+        $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
496
+        $csp->addAllowedFrameDomain('\'self\'');
497
+
498
+        $response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
499
+        $response->setHeaderTitle($shareTmpl['filename']);
500
+        if ($shareTmpl['shareOwner'] !== '') {
501
+            $response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
502
+        }
503
+
504
+        $isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
505
+
506
+        if ($isNoneFileDropFolder && !$share->getHideDownload()) {
507
+            \OCP\Util::addScript('files_sharing', 'public_note');
508
+
509
+            $downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
510
+            $downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
511
+            $download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
512
+            $downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
513
+            $directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
514
+            // TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
515
+            $externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your %s', [$this->defaults->getProductName()]), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
516
+
517
+            $responseComposer = [];
518
+
519
+            if ($shareIsFolder) {
520
+                $responseComposer[] = $downloadAllWhite;
521
+                $responseComposer[] = $downloadAll;
522
+            } else {
523
+                $responseComposer[] = $downloadWhite;
524
+                $responseComposer[] = $download;
525
+            }
526
+            $responseComposer[] = $directLink;
527
+            if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
528
+                $responseComposer[] = $externalShare;
529
+            }
530
+
531
+            $response->setHeaderActions($responseComposer);
532
+        }
533
+
534
+        $response->setContentSecurityPolicy($csp);
535
+
536
+        $this->emitAccessShareHook($share);
537
+
538
+        return $response;
539
+    }
540
+
541
+    /**
542
+     * @PublicPage
543
+     * @NoCSRFRequired
544
+     * @NoSameSiteCookieRequired
545
+     *
546
+     * @param string $token
547
+     * @param string $files
548
+     * @param string $path
549
+     * @param string $downloadStartSecret
550
+     * @return void|\OCP\AppFramework\Http\Response
551
+     * @throws NotFoundException
552
+     */
553
+    public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
554
+        \OC_User::setIncognitoMode(true);
555
+
556
+        $share = $this->shareManager->getShareByToken($token);
557
+
558
+        if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
559
+            return new \OCP\AppFramework\Http\DataResponse('Share has no read permission');
560
+        }
561
+
562
+        $files_list = null;
563
+        if (!is_null($files)) { // download selected files
564
+            $files_list = json_decode($files);
565
+            // in case we get only a single file
566
+            if ($files_list === null) {
567
+                $files_list = [$files];
568
+            }
569
+            // Just in case $files is a single int like '1234'
570
+            if (!is_array($files_list)) {
571
+                $files_list = [$files_list];
572
+            }
573
+        }
574
+
575
+        if (!$this->validateShare($share)) {
576
+            throw new NotFoundException();
577
+        }
578
+
579
+        $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
580
+        $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
581
+
582
+
583
+        // Single file share
584
+        if ($share->getNode() instanceof \OCP\Files\File) {
585
+            // Single file download
586
+            $this->singleFileDownloaded($share, $share->getNode());
587
+        }
588
+        // Directory share
589
+        else {
590
+            /** @var \OCP\Files\Folder $node */
591
+            $node = $share->getNode();
592
+
593
+            // Try to get the path
594
+            if ($path !== '') {
595
+                try {
596
+                    $node = $node->get($path);
597
+                } catch (NotFoundException $e) {
598
+                    $this->emitAccessShareHook($share, 404, 'Share not found');
599
+                    return new NotFoundResponse();
600
+                }
601
+            }
602
+
603
+            $originalSharePath = $userFolder->getRelativePath($node->getPath());
604
+
605
+            if ($node instanceof \OCP\Files\File) {
606
+                // Single file download
607
+                $this->singleFileDownloaded($share, $share->getNode());
608
+            } else {
609
+                try {
610
+                    if (!empty($files_list)) {
611
+                        $this->fileListDownloaded($share, $files_list, $node);
612
+                    } else {
613
+                        // The folder is downloaded
614
+                        $this->singleFileDownloaded($share, $share->getNode());
615
+                    }
616
+                } catch (NotFoundException $e) {
617
+                    return new NotFoundResponse();
618
+                }
619
+            }
620
+        }
621
+
622
+        /* FIXME: We should do this all nicely in OCP */
623
+        OC_Util::tearDownFS();
624
+        OC_Util::setupFS($share->getShareOwner());
625
+
626
+        /**
627
+         * this sets a cookie to be able to recognize the start of the download
628
+         * the content must not be longer than 32 characters and must only contain
629
+         * alphanumeric characters
630
+         */
631
+        if (!empty($downloadStartSecret)
632
+            && !isset($downloadStartSecret[32])
633
+            && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
634
+
635
+            // FIXME: set on the response once we use an actual app framework response
636
+            setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
637
+        }
638
+
639
+        $this->emitAccessShareHook($share);
640
+
641
+        $server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
642
+
643
+        /**
644
+         * Http range requests support
645
+         */
646
+        if (isset($_SERVER['HTTP_RANGE'])) {
647
+            $server_params['range'] = $this->request->getHeader('Range');
648
+        }
649
+
650
+        // download selected files
651
+        if (!is_null($files) && $files !== '') {
652
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
653
+            // after dispatching the request which results in a "Cannot modify header information" notice.
654
+            OC_Files::get($originalSharePath, $files_list, $server_params);
655
+            exit();
656
+        } else {
657
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
658
+            // after dispatching the request which results in a "Cannot modify header information" notice.
659
+            OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
660
+            exit();
661
+        }
662
+    }
663
+
664
+    /**
665
+     * create activity for every downloaded file
666
+     *
667
+     * @param Share\IShare $share
668
+     * @param array $files_list
669
+     * @param \OCP\Files\Folder $node
670
+     * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
671
+     */
672
+    protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
673
+        if ($share->getHideDownload() && count($files_list) > 1) {
674
+            throw new NotFoundException('Downloading more than 1 file');
675
+        }
676
+
677
+        foreach ($files_list as $file) {
678
+            $subNode = $node->get($file);
679
+            $this->singleFileDownloaded($share, $subNode);
680
+        }
681
+    }
682
+
683
+    /**
684
+     * create activity if a single file was downloaded from a link share
685
+     *
686
+     * @param Share\IShare $share
687
+     * @throws NotFoundException when trying to download a folder of a "hide download" share
688
+     */
689
+    protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
690
+        if ($share->getHideDownload() && $node instanceof Folder) {
691
+            throw new NotFoundException('Downloading a folder');
692
+        }
693
+
694
+        $fileId = $node->getId();
695
+
696
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
697
+        $userNodeList = $userFolder->getById($fileId);
698
+        $userNode = $userNodeList[0];
699
+        $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
700
+        $userPath = $userFolder->getRelativePath($userNode->getPath());
701
+        $ownerPath = $ownerFolder->getRelativePath($node->getPath());
702
+
703
+        $parameters = [$userPath];
704
+
705
+        if ($share->getShareType() === IShare::TYPE_EMAIL) {
706
+            if ($node instanceof \OCP\Files\File) {
707
+                $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
708
+            } else {
709
+                $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
710
+            }
711
+            $parameters[] = $share->getSharedWith();
712
+        } else {
713
+            if ($node instanceof \OCP\Files\File) {
714
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
715
+            } else {
716
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
717
+            }
718
+        }
719
+
720
+        $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
721
+
722
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
723
+            $parameters[0] = $ownerPath;
724
+            $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
725
+        }
726
+    }
727
+
728
+    /**
729
+     * publish activity
730
+     *
731
+     * @param string $subject
732
+     * @param array $parameters
733
+     * @param string $affectedUser
734
+     * @param int $fileId
735
+     * @param string $filePath
736
+     */
737
+    protected function publishActivity($subject,
738
+                                        array $parameters,
739
+                                        $affectedUser,
740
+                                        $fileId,
741
+                                        $filePath) {
742
+        $event = $this->activityManager->generateEvent();
743
+        $event->setApp('files_sharing')
744
+            ->setType('public_links')
745
+            ->setSubject($subject, $parameters)
746
+            ->setAffectedUser($affectedUser)
747
+            ->setObject('files', $fileId, $filePath);
748
+        $this->activityManager->publish($event);
749
+    }
750 750
 }
Please login to merge, or discard this patch.
status.php 1 patch
Indentation   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -34,33 +34,33 @@
 block discarded – undo
34 34
 require_once __DIR__ . '/lib/versioncheck.php';
35 35
 
36 36
 try {
37
-	require_once __DIR__ . '/lib/base.php';
37
+    require_once __DIR__ . '/lib/base.php';
38 38
 
39
-	$systemConfig = \OC::$server->getSystemConfig();
39
+    $systemConfig = \OC::$server->getSystemConfig();
40 40
 
41
-	$installed = (bool) $systemConfig->getValue('installed', false);
42
-	$maintenance = (bool) $systemConfig->getValue('maintenance', false);
43
-	# see core/lib/private/legacy/defaults.php and core/themes/example/defaults.php
44
-	# for description and defaults
45
-	$defaults = new \OCP\Defaults();
46
-	$values = [
47
-		'installed' => $installed,
48
-		'maintenance' => $maintenance,
49
-		'needsDbUpgrade' => \OCP\Util::needUpgrade(),
50
-		'version' => implode('.', \OCP\Util::getVersion()),
51
-		'versionstring' => OC_Util::getVersionString(),
52
-		'edition' => '',
53
-		'productname' => $defaults->getProductName(),
54
-		'extendedSupport' => \OCP\Util::hasExtendedSupport()
55
-	];
56
-	if (OC::$CLI) {
57
-		print_r($values);
58
-	} else {
59
-		header('Access-Control-Allow-Origin: *');
60
-		header('Content-Type: application/json');
61
-		echo json_encode($values);
62
-	}
41
+    $installed = (bool) $systemConfig->getValue('installed', false);
42
+    $maintenance = (bool) $systemConfig->getValue('maintenance', false);
43
+    # see core/lib/private/legacy/defaults.php and core/themes/example/defaults.php
44
+    # for description and defaults
45
+    $defaults = new \OCP\Defaults();
46
+    $values = [
47
+        'installed' => $installed,
48
+        'maintenance' => $maintenance,
49
+        'needsDbUpgrade' => \OCP\Util::needUpgrade(),
50
+        'version' => implode('.', \OCP\Util::getVersion()),
51
+        'versionstring' => OC_Util::getVersionString(),
52
+        'edition' => '',
53
+        'productname' => $defaults->getProductName(),
54
+        'extendedSupport' => \OCP\Util::hasExtendedSupport()
55
+    ];
56
+    if (OC::$CLI) {
57
+        print_r($values);
58
+    } else {
59
+        header('Access-Control-Allow-Origin: *');
60
+        header('Content-Type: application/json');
61
+        echo json_encode($values);
62
+    }
63 63
 } catch (Exception $ex) {
64
-	http_response_code(500);
65
-	\OC::$server->getLogger()->logException($ex, ['app' => 'remote']);
64
+    http_response_code(500);
65
+    \OC::$server->getLogger()->logException($ex, ['app' => 'remote']);
66 66
 }
Please login to merge, or discard this patch.
lib/public/Defaults.php 1 patch
Indentation   +183 added lines, -183 removed lines patch added patch discarded remove patch
@@ -40,187 +40,187 @@
 block discarded – undo
40 40
  */
41 41
 class Defaults {
42 42
 
43
-	/**
44
-	 * \OC_Defaults instance to retrieve the defaults
45
-	 * @since 6.0.0
46
-	 */
47
-	private $defaults;
48
-
49
-	/**
50
-	 * creates a \OC_Defaults instance which is used in all methods to retrieve the
51
-	 * actual defaults
52
-	 * @since 6.0.0
53
-	 */
54
-	public function __construct(\OC_Defaults $defaults = null) {
55
-		if ($defaults === null) {
56
-			$defaults = \OC::$server->getThemingDefaults();
57
-		}
58
-		$this->defaults = $defaults;
59
-	}
60
-
61
-	/**
62
-	 * get base URL for the organisation behind your ownCloud instance
63
-	 * @return string
64
-	 * @since 6.0.0
65
-	 */
66
-	public function getBaseUrl(): string {
67
-		return $this->defaults->getBaseUrl();
68
-	}
69
-
70
-	/**
71
-	 * link to the desktop sync client
72
-	 * @return string
73
-	 * @since 6.0.0
74
-	 */
75
-	public function getSyncClientUrl(): string {
76
-		return $this->defaults->getSyncClientUrl();
77
-	}
78
-
79
-	/**
80
-	 * link to the iOS client
81
-	 * @return string
82
-	 * @since 8.0.0
83
-	 */
84
-	public function getiOSClientUrl(): string {
85
-		return $this->defaults->getiOSClientUrl();
86
-	}
87
-
88
-	/**
89
-	 * link to the Android client
90
-	 * @return string
91
-	 * @since 8.0.0
92
-	 */
93
-	public function getAndroidClientUrl(): string {
94
-		return $this->defaults->getAndroidClientUrl();
95
-	}
96
-
97
-	/**
98
-	 * base URL to the documentation of your ownCloud instance
99
-	 * @return string
100
-	 * @since 6.0.0
101
-	 */
102
-	public function getDocBaseUrl(): string {
103
-		return $this->defaults->getDocBaseUrl();
104
-	}
105
-
106
-	/**
107
-	 * name of your Nextcloud instance (e.g. MyPrivateCloud)
108
-	 * @return string
109
-	 * @since 6.0.0
110
-	 */
111
-	public function getName(): string {
112
-		return $this->defaults->getName();
113
-	}
114
-
115
-	/**
116
-	 * Name of the software product (defaults to Nextcloud)
117
-	 *
118
-	 * @return string
119
-	 * @since 22.0.0
120
-	 */
121
-	public function getProductName(): string {
122
-		return $this->defaults->getProductName();
123
-	}
124
-
125
-	/**
126
-	 * name of your ownCloud instance containing HTML styles
127
-	 * @return string
128
-	 * @since 8.0.0
129
-	 * @depreacted 22.0.0
130
-	 */
131
-	public function getHTMLName(): string {
132
-		return $this->defaults->getHTMLName();
133
-	}
134
-
135
-	/**
136
-	 * Entity behind your onwCloud instance
137
-	 * @return string
138
-	 * @since 6.0.0
139
-	 */
140
-	public function getEntity(): string {
141
-		return $this->defaults->getEntity();
142
-	}
143
-
144
-	/**
145
-	 * ownCloud slogan
146
-	 * @return string
147
-	 * @since 6.0.0
148
-	 */
149
-	public function getSlogan(?string $lang = null): string {
150
-		return $this->defaults->getSlogan($lang);
151
-	}
152
-
153
-	/**
154
-	 * footer, short version
155
-	 * @return string
156
-	 * @since 6.0.0
157
-	 */
158
-	public function getShortFooter(): string {
159
-		return $this->defaults->getShortFooter();
160
-	}
161
-
162
-	/**
163
-	 * footer, long version
164
-	 * @return string
165
-	 * @since 6.0.0
166
-	 */
167
-	public function getLongFooter(): string {
168
-		return $this->defaults->getLongFooter();
169
-	}
170
-
171
-	/**
172
-	 * Returns the AppId for the App Store for the iOS Client
173
-	 * @return string AppId
174
-	 * @since 8.0.0
175
-	 */
176
-	public function getiTunesAppId(): string {
177
-		return $this->defaults->getiTunesAppId();
178
-	}
179
-
180
-	/**
181
-	 * Themed logo url
182
-	 *
183
-	 * @param bool $useSvg Whether to point to the SVG image or a fallback
184
-	 * @return string
185
-	 * @since 12.0.0
186
-	 */
187
-	public function getLogo(bool $useSvg = true): string {
188
-		return $this->defaults->getLogo($useSvg);
189
-	}
190
-
191
-	/**
192
-	 * Returns primary color
193
-	 * @return string
194
-	 * @since 12.0.0
195
-	 */
196
-	public function getColorPrimary(): string {
197
-		return $this->defaults->getColorPrimary();
198
-	}
199
-
200
-	/**
201
-	 * @param string $key
202
-	 * @return string URL to doc with key
203
-	 * @since 12.0.0
204
-	 */
205
-	public function buildDocLinkToKey(string $key): string {
206
-		return $this->defaults->buildDocLinkToKey($key);
207
-	}
208
-
209
-	/**
210
-	 * Returns the title
211
-	 * @return string title
212
-	 * @since 12.0.0
213
-	 */
214
-	public function getTitle(): string {
215
-		return $this->defaults->getTitle();
216
-	}
217
-
218
-	/**
219
-	 * Returns primary color
220
-	 * @return string
221
-	 * @since 13.0.0
222
-	 */
223
-	public function getTextColorPrimary(): string {
224
-		return $this->defaults->getTextColorPrimary();
225
-	}
43
+    /**
44
+     * \OC_Defaults instance to retrieve the defaults
45
+     * @since 6.0.0
46
+     */
47
+    private $defaults;
48
+
49
+    /**
50
+     * creates a \OC_Defaults instance which is used in all methods to retrieve the
51
+     * actual defaults
52
+     * @since 6.0.0
53
+     */
54
+    public function __construct(\OC_Defaults $defaults = null) {
55
+        if ($defaults === null) {
56
+            $defaults = \OC::$server->getThemingDefaults();
57
+        }
58
+        $this->defaults = $defaults;
59
+    }
60
+
61
+    /**
62
+     * get base URL for the organisation behind your ownCloud instance
63
+     * @return string
64
+     * @since 6.0.0
65
+     */
66
+    public function getBaseUrl(): string {
67
+        return $this->defaults->getBaseUrl();
68
+    }
69
+
70
+    /**
71
+     * link to the desktop sync client
72
+     * @return string
73
+     * @since 6.0.0
74
+     */
75
+    public function getSyncClientUrl(): string {
76
+        return $this->defaults->getSyncClientUrl();
77
+    }
78
+
79
+    /**
80
+     * link to the iOS client
81
+     * @return string
82
+     * @since 8.0.0
83
+     */
84
+    public function getiOSClientUrl(): string {
85
+        return $this->defaults->getiOSClientUrl();
86
+    }
87
+
88
+    /**
89
+     * link to the Android client
90
+     * @return string
91
+     * @since 8.0.0
92
+     */
93
+    public function getAndroidClientUrl(): string {
94
+        return $this->defaults->getAndroidClientUrl();
95
+    }
96
+
97
+    /**
98
+     * base URL to the documentation of your ownCloud instance
99
+     * @return string
100
+     * @since 6.0.0
101
+     */
102
+    public function getDocBaseUrl(): string {
103
+        return $this->defaults->getDocBaseUrl();
104
+    }
105
+
106
+    /**
107
+     * name of your Nextcloud instance (e.g. MyPrivateCloud)
108
+     * @return string
109
+     * @since 6.0.0
110
+     */
111
+    public function getName(): string {
112
+        return $this->defaults->getName();
113
+    }
114
+
115
+    /**
116
+     * Name of the software product (defaults to Nextcloud)
117
+     *
118
+     * @return string
119
+     * @since 22.0.0
120
+     */
121
+    public function getProductName(): string {
122
+        return $this->defaults->getProductName();
123
+    }
124
+
125
+    /**
126
+     * name of your ownCloud instance containing HTML styles
127
+     * @return string
128
+     * @since 8.0.0
129
+     * @depreacted 22.0.0
130
+     */
131
+    public function getHTMLName(): string {
132
+        return $this->defaults->getHTMLName();
133
+    }
134
+
135
+    /**
136
+     * Entity behind your onwCloud instance
137
+     * @return string
138
+     * @since 6.0.0
139
+     */
140
+    public function getEntity(): string {
141
+        return $this->defaults->getEntity();
142
+    }
143
+
144
+    /**
145
+     * ownCloud slogan
146
+     * @return string
147
+     * @since 6.0.0
148
+     */
149
+    public function getSlogan(?string $lang = null): string {
150
+        return $this->defaults->getSlogan($lang);
151
+    }
152
+
153
+    /**
154
+     * footer, short version
155
+     * @return string
156
+     * @since 6.0.0
157
+     */
158
+    public function getShortFooter(): string {
159
+        return $this->defaults->getShortFooter();
160
+    }
161
+
162
+    /**
163
+     * footer, long version
164
+     * @return string
165
+     * @since 6.0.0
166
+     */
167
+    public function getLongFooter(): string {
168
+        return $this->defaults->getLongFooter();
169
+    }
170
+
171
+    /**
172
+     * Returns the AppId for the App Store for the iOS Client
173
+     * @return string AppId
174
+     * @since 8.0.0
175
+     */
176
+    public function getiTunesAppId(): string {
177
+        return $this->defaults->getiTunesAppId();
178
+    }
179
+
180
+    /**
181
+     * Themed logo url
182
+     *
183
+     * @param bool $useSvg Whether to point to the SVG image or a fallback
184
+     * @return string
185
+     * @since 12.0.0
186
+     */
187
+    public function getLogo(bool $useSvg = true): string {
188
+        return $this->defaults->getLogo($useSvg);
189
+    }
190
+
191
+    /**
192
+     * Returns primary color
193
+     * @return string
194
+     * @since 12.0.0
195
+     */
196
+    public function getColorPrimary(): string {
197
+        return $this->defaults->getColorPrimary();
198
+    }
199
+
200
+    /**
201
+     * @param string $key
202
+     * @return string URL to doc with key
203
+     * @since 12.0.0
204
+     */
205
+    public function buildDocLinkToKey(string $key): string {
206
+        return $this->defaults->buildDocLinkToKey($key);
207
+    }
208
+
209
+    /**
210
+     * Returns the title
211
+     * @return string title
212
+     * @since 12.0.0
213
+     */
214
+    public function getTitle(): string {
215
+        return $this->defaults->getTitle();
216
+    }
217
+
218
+    /**
219
+     * Returns primary color
220
+     * @return string
221
+     * @since 13.0.0
222
+     */
223
+    public function getTextColorPrimary(): string {
224
+        return $this->defaults->getTextColorPrimary();
225
+    }
226 226
 }
Please login to merge, or discard this patch.
lib/private/Template/JSConfigHelper.php 1 patch
Indentation   +284 added lines, -284 removed lines patch added patch discarded remove patch
@@ -47,288 +47,288 @@
 block discarded – undo
47 47
 
48 48
 class JSConfigHelper {
49 49
 
50
-	/** @var IL10N */
51
-	private $l;
52
-
53
-	/** @var Defaults */
54
-	private $defaults;
55
-
56
-	/** @var IAppManager */
57
-	private $appManager;
58
-
59
-	/** @var ISession */
60
-	private $session;
61
-
62
-	/** @var IUser|null */
63
-	private $currentUser;
64
-
65
-	/** @var IConfig */
66
-	private $config;
67
-
68
-	/** @var IGroupManager */
69
-	private $groupManager;
70
-
71
-	/** @var IniGetWrapper */
72
-	private $iniWrapper;
73
-
74
-	/** @var IURLGenerator */
75
-	private $urlGenerator;
76
-
77
-	/** @var CapabilitiesManager */
78
-	private $capabilitiesManager;
79
-
80
-	/** @var IInitialStateService */
81
-	private $initialStateService;
82
-
83
-	/** @var array user back-ends excluded from password verification */
84
-	private $excludedUserBackEnds = ['user_saml' => true, 'user_globalsiteselector' => true];
85
-
86
-	/**
87
-	 * @param IL10N $l
88
-	 * @param Defaults $defaults
89
-	 * @param IAppManager $appManager
90
-	 * @param ISession $session
91
-	 * @param IUser|null $currentUser
92
-	 * @param IConfig $config
93
-	 * @param IGroupManager $groupManager
94
-	 * @param IniGetWrapper $iniWrapper
95
-	 * @param IURLGenerator $urlGenerator
96
-	 * @param CapabilitiesManager $capabilitiesManager
97
-	 */
98
-	public function __construct(IL10N $l,
99
-								Defaults $defaults,
100
-								IAppManager $appManager,
101
-								ISession $session,
102
-								$currentUser,
103
-								IConfig $config,
104
-								IGroupManager $groupManager,
105
-								IniGetWrapper $iniWrapper,
106
-								IURLGenerator $urlGenerator,
107
-								CapabilitiesManager $capabilitiesManager,
108
-								IInitialStateService $initialStateService) {
109
-		$this->l = $l;
110
-		$this->defaults = $defaults;
111
-		$this->appManager = $appManager;
112
-		$this->session = $session;
113
-		$this->currentUser = $currentUser;
114
-		$this->config = $config;
115
-		$this->groupManager = $groupManager;
116
-		$this->iniWrapper = $iniWrapper;
117
-		$this->urlGenerator = $urlGenerator;
118
-		$this->capabilitiesManager = $capabilitiesManager;
119
-		$this->initialStateService = $initialStateService;
120
-	}
121
-
122
-	public function getConfig() {
123
-		$userBackendAllowsPasswordConfirmation = true;
124
-		if ($this->currentUser !== null) {
125
-			$uid = $this->currentUser->getUID();
126
-
127
-			$backend = $this->currentUser->getBackend();
128
-			if ($backend instanceof IPasswordConfirmationBackend) {
129
-				$userBackendAllowsPasswordConfirmation = $backend->canConfirmPassword($uid);
130
-			} elseif (isset($this->excludedUserBackEnds[$this->currentUser->getBackendClassName()])) {
131
-				$userBackendAllowsPasswordConfirmation = false;
132
-			}
133
-		} else {
134
-			$uid = null;
135
-		}
136
-
137
-		// Get the config
138
-		$apps_paths = [];
139
-
140
-		if ($this->currentUser === null) {
141
-			$apps = $this->appManager->getInstalledApps();
142
-		} else {
143
-			$apps = $this->appManager->getEnabledAppsForUser($this->currentUser);
144
-		}
145
-
146
-		foreach ($apps as $app) {
147
-			$apps_paths[$app] = \OC_App::getAppWebPath($app);
148
-		}
149
-
150
-
151
-		$enableLinkPasswordByDefault = $this->config->getAppValue('core', 'shareapi_enable_link_password_by_default', 'no');
152
-		$enableLinkPasswordByDefault = $enableLinkPasswordByDefault === 'yes';
153
-		$defaultExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
154
-		$defaultExpireDate = $enforceDefaultExpireDate = null;
155
-		if ($defaultExpireDateEnabled) {
156
-			$defaultExpireDate = (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
157
-			$enforceDefaultExpireDate = $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
158
-		}
159
-		$outgoingServer2serverShareEnabled = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
160
-
161
-		$defaultInternalExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no') === 'yes';
162
-		$defaultInternalExpireDate = $defaultInternalExpireDateEnforced = null;
163
-		if ($defaultInternalExpireDateEnabled) {
164
-			$defaultInternalExpireDate = (int)$this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7');
165
-			$defaultInternalExpireDateEnforced = $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes';
166
-		}
167
-
168
-		$defaultRemoteExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no') === 'yes';
169
-		$defaultRemoteExpireDate = $defaultRemoteExpireDateEnforced = null;
170
-		if ($defaultRemoteExpireDateEnabled) {
171
-			$defaultRemoteExpireDate = (int)$this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7');
172
-			$defaultRemoteExpireDateEnforced = $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes';
173
-		}
174
-
175
-		$countOfDataLocation = 0;
176
-		$dataLocation = str_replace(\OC::$SERVERROOT . '/', '', $this->config->getSystemValue('datadirectory', ''), $countOfDataLocation);
177
-		if ($countOfDataLocation !== 1 || $uid === null || !$this->groupManager->isAdmin($uid)) {
178
-			$dataLocation = false;
179
-		}
180
-
181
-		if ($this->currentUser instanceof IUser) {
182
-			$lastConfirmTimestamp = $this->session->get('last-password-confirm');
183
-			if (!is_int($lastConfirmTimestamp)) {
184
-				$lastConfirmTimestamp = 0;
185
-			}
186
-		} else {
187
-			$lastConfirmTimestamp = 0;
188
-		}
189
-
190
-		$capabilities = $this->capabilitiesManager->getCapabilities();
191
-
192
-		$config = [
193
-			'session_lifetime' => min($this->config->getSystemValue('session_lifetime', $this->iniWrapper->getNumeric('session.gc_maxlifetime')), $this->iniWrapper->getNumeric('session.gc_maxlifetime')),
194
-			'session_keepalive' => $this->config->getSystemValue('session_keepalive', true),
195
-			'auto_logout' => $this->config->getSystemValue('auto_logout', false),
196
-			'version' => implode('.', \OCP\Util::getVersion()),
197
-			'versionstring' => \OC_Util::getVersionString(),
198
-			'enable_avatars' => true, // here for legacy reasons - to not crash existing code that relies on this value
199
-			'lost_password_link' => $this->config->getSystemValue('lost_password_link', null),
200
-			'modRewriteWorking' => $this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true',
201
-			'sharing.maxAutocompleteResults' => max(0, $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)),
202
-			'sharing.minSearchStringLength' => $this->config->getSystemValueInt('sharing.minSearchStringLength', 0),
203
-			'blacklist_files_regex' => \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX,
204
-		];
205
-
206
-		$array = [
207
-			"_oc_debug" => $this->config->getSystemValue('debug', false) ? 'true' : 'false',
208
-			"_oc_isadmin" => $uid !== null && $this->groupManager->isAdmin($uid) ? 'true' : 'false',
209
-			"backendAllowsPasswordConfirmation" => $userBackendAllowsPasswordConfirmation ? 'true' : 'false',
210
-			"oc_dataURL" => is_string($dataLocation) ? "\"" . $dataLocation . "\"" : 'false',
211
-			"_oc_webroot" => "\"" . \OC::$WEBROOT . "\"",
212
-			"_oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution
213
-			"datepickerFormatDate" => json_encode($this->l->l('jsdate', null)),
214
-			'nc_lastLogin' => $lastConfirmTimestamp,
215
-			'nc_pageLoad' => time(),
216
-			"dayNames" => json_encode([
217
-				$this->l->t('Sunday'),
218
-				$this->l->t('Monday'),
219
-				$this->l->t('Tuesday'),
220
-				$this->l->t('Wednesday'),
221
-				$this->l->t('Thursday'),
222
-				$this->l->t('Friday'),
223
-				$this->l->t('Saturday')
224
-			]),
225
-			"dayNamesShort" => json_encode([
226
-				$this->l->t('Sun.'),
227
-				$this->l->t('Mon.'),
228
-				$this->l->t('Tue.'),
229
-				$this->l->t('Wed.'),
230
-				$this->l->t('Thu.'),
231
-				$this->l->t('Fri.'),
232
-				$this->l->t('Sat.')
233
-			]),
234
-			"dayNamesMin" => json_encode([
235
-				$this->l->t('Su'),
236
-				$this->l->t('Mo'),
237
-				$this->l->t('Tu'),
238
-				$this->l->t('We'),
239
-				$this->l->t('Th'),
240
-				$this->l->t('Fr'),
241
-				$this->l->t('Sa')
242
-			]),
243
-			"monthNames" => json_encode([
244
-				$this->l->t('January'),
245
-				$this->l->t('February'),
246
-				$this->l->t('March'),
247
-				$this->l->t('April'),
248
-				$this->l->t('May'),
249
-				$this->l->t('June'),
250
-				$this->l->t('July'),
251
-				$this->l->t('August'),
252
-				$this->l->t('September'),
253
-				$this->l->t('October'),
254
-				$this->l->t('November'),
255
-				$this->l->t('December')
256
-			]),
257
-			"monthNamesShort" => json_encode([
258
-				$this->l->t('Jan.'),
259
-				$this->l->t('Feb.'),
260
-				$this->l->t('Mar.'),
261
-				$this->l->t('Apr.'),
262
-				$this->l->t('May.'),
263
-				$this->l->t('Jun.'),
264
-				$this->l->t('Jul.'),
265
-				$this->l->t('Aug.'),
266
-				$this->l->t('Sep.'),
267
-				$this->l->t('Oct.'),
268
-				$this->l->t('Nov.'),
269
-				$this->l->t('Dec.')
270
-			]),
271
-			"firstDay" => json_encode($this->l->l('firstday', null)),
272
-			"_oc_config" => json_encode($config),
273
-			"oc_appconfig" => json_encode([
274
-				'core' => [
275
-					'defaultExpireDateEnabled' => $defaultExpireDateEnabled,
276
-					'defaultExpireDate' => $defaultExpireDate,
277
-					'defaultExpireDateEnforced' => $enforceDefaultExpireDate,
278
-					'enforcePasswordForPublicLink' => \OCP\Util::isPublicLinkPasswordRequired(),
279
-					'enableLinkPasswordByDefault' => $enableLinkPasswordByDefault,
280
-					'sharingDisabledForUser' => \OCP\Util::isSharingDisabledForUser(),
281
-					'resharingAllowed' => \OC\Share\Share::isResharingAllowed(),
282
-					'remoteShareAllowed' => $outgoingServer2serverShareEnabled,
283
-					'federatedCloudShareDoc' => $this->urlGenerator->linkToDocs('user-sharing-federated'),
284
-					'allowGroupSharing' => \OC::$server->getShareManager()->allowGroupSharing(),
285
-					'defaultInternalExpireDateEnabled' => $defaultInternalExpireDateEnabled,
286
-					'defaultInternalExpireDate' => $defaultInternalExpireDate,
287
-					'defaultInternalExpireDateEnforced' => $defaultInternalExpireDateEnforced,
288
-					'defaultRemoteExpireDateEnabled' => $defaultRemoteExpireDateEnabled,
289
-					'defaultRemoteExpireDate' => $defaultRemoteExpireDate,
290
-					'defaultRemoteExpireDateEnforced' => $defaultRemoteExpireDateEnforced,
291
-				]
292
-			]),
293
-			"_theme" => json_encode([
294
-				'entity' => $this->defaults->getEntity(),
295
-				'name' => $this->defaults->getName(),
296
-				'productName' => $this->defaults->getProductName(),
297
-				'title' => $this->defaults->getTitle(),
298
-				'baseUrl' => $this->defaults->getBaseUrl(),
299
-				'syncClientUrl' => $this->defaults->getSyncClientUrl(),
300
-				'docBaseUrl' => $this->defaults->getDocBaseUrl(),
301
-				'docPlaceholderUrl' => $this->defaults->buildDocLinkToKey('PLACEHOLDER'),
302
-				'slogan' => $this->defaults->getSlogan(),
303
-				'logoClaim' => '',
304
-				'shortFooter' => $this->defaults->getShortFooter(),
305
-				'longFooter' => $this->defaults->getLongFooter(),
306
-				'folder' => \OC_Util::getTheme(),
307
-			]),
308
-		];
309
-
310
-		if ($this->currentUser !== null) {
311
-			$array['oc_userconfig'] = json_encode([
312
-				'avatar' => [
313
-					'version' => (int)$this->config->getUserValue($uid, 'avatar', 'version', 0),
314
-					'generated' => $this->config->getUserValue($uid, 'avatar', 'generated', 'true') === 'true',
315
-				]
316
-			]);
317
-		}
318
-
319
-		$this->initialStateService->provideInitialState('core', 'config', $config);
320
-		$this->initialStateService->provideInitialState('core', 'capabilities', $capabilities);
321
-
322
-		// Allow hooks to modify the output values
323
-		\OC_Hook::emit('\OCP\Config', 'js', ['array' => &$array]);
324
-
325
-		$result = '';
326
-
327
-		// Echo it
328
-		foreach ($array as  $setting => $value) {
329
-			$result .= 'var '. $setting . '='. $value . ';' . PHP_EOL;
330
-		}
331
-
332
-		return $result;
333
-	}
50
+    /** @var IL10N */
51
+    private $l;
52
+
53
+    /** @var Defaults */
54
+    private $defaults;
55
+
56
+    /** @var IAppManager */
57
+    private $appManager;
58
+
59
+    /** @var ISession */
60
+    private $session;
61
+
62
+    /** @var IUser|null */
63
+    private $currentUser;
64
+
65
+    /** @var IConfig */
66
+    private $config;
67
+
68
+    /** @var IGroupManager */
69
+    private $groupManager;
70
+
71
+    /** @var IniGetWrapper */
72
+    private $iniWrapper;
73
+
74
+    /** @var IURLGenerator */
75
+    private $urlGenerator;
76
+
77
+    /** @var CapabilitiesManager */
78
+    private $capabilitiesManager;
79
+
80
+    /** @var IInitialStateService */
81
+    private $initialStateService;
82
+
83
+    /** @var array user back-ends excluded from password verification */
84
+    private $excludedUserBackEnds = ['user_saml' => true, 'user_globalsiteselector' => true];
85
+
86
+    /**
87
+     * @param IL10N $l
88
+     * @param Defaults $defaults
89
+     * @param IAppManager $appManager
90
+     * @param ISession $session
91
+     * @param IUser|null $currentUser
92
+     * @param IConfig $config
93
+     * @param IGroupManager $groupManager
94
+     * @param IniGetWrapper $iniWrapper
95
+     * @param IURLGenerator $urlGenerator
96
+     * @param CapabilitiesManager $capabilitiesManager
97
+     */
98
+    public function __construct(IL10N $l,
99
+                                Defaults $defaults,
100
+                                IAppManager $appManager,
101
+                                ISession $session,
102
+                                $currentUser,
103
+                                IConfig $config,
104
+                                IGroupManager $groupManager,
105
+                                IniGetWrapper $iniWrapper,
106
+                                IURLGenerator $urlGenerator,
107
+                                CapabilitiesManager $capabilitiesManager,
108
+                                IInitialStateService $initialStateService) {
109
+        $this->l = $l;
110
+        $this->defaults = $defaults;
111
+        $this->appManager = $appManager;
112
+        $this->session = $session;
113
+        $this->currentUser = $currentUser;
114
+        $this->config = $config;
115
+        $this->groupManager = $groupManager;
116
+        $this->iniWrapper = $iniWrapper;
117
+        $this->urlGenerator = $urlGenerator;
118
+        $this->capabilitiesManager = $capabilitiesManager;
119
+        $this->initialStateService = $initialStateService;
120
+    }
121
+
122
+    public function getConfig() {
123
+        $userBackendAllowsPasswordConfirmation = true;
124
+        if ($this->currentUser !== null) {
125
+            $uid = $this->currentUser->getUID();
126
+
127
+            $backend = $this->currentUser->getBackend();
128
+            if ($backend instanceof IPasswordConfirmationBackend) {
129
+                $userBackendAllowsPasswordConfirmation = $backend->canConfirmPassword($uid);
130
+            } elseif (isset($this->excludedUserBackEnds[$this->currentUser->getBackendClassName()])) {
131
+                $userBackendAllowsPasswordConfirmation = false;
132
+            }
133
+        } else {
134
+            $uid = null;
135
+        }
136
+
137
+        // Get the config
138
+        $apps_paths = [];
139
+
140
+        if ($this->currentUser === null) {
141
+            $apps = $this->appManager->getInstalledApps();
142
+        } else {
143
+            $apps = $this->appManager->getEnabledAppsForUser($this->currentUser);
144
+        }
145
+
146
+        foreach ($apps as $app) {
147
+            $apps_paths[$app] = \OC_App::getAppWebPath($app);
148
+        }
149
+
150
+
151
+        $enableLinkPasswordByDefault = $this->config->getAppValue('core', 'shareapi_enable_link_password_by_default', 'no');
152
+        $enableLinkPasswordByDefault = $enableLinkPasswordByDefault === 'yes';
153
+        $defaultExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
154
+        $defaultExpireDate = $enforceDefaultExpireDate = null;
155
+        if ($defaultExpireDateEnabled) {
156
+            $defaultExpireDate = (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
157
+            $enforceDefaultExpireDate = $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
158
+        }
159
+        $outgoingServer2serverShareEnabled = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
160
+
161
+        $defaultInternalExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no') === 'yes';
162
+        $defaultInternalExpireDate = $defaultInternalExpireDateEnforced = null;
163
+        if ($defaultInternalExpireDateEnabled) {
164
+            $defaultInternalExpireDate = (int)$this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7');
165
+            $defaultInternalExpireDateEnforced = $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes';
166
+        }
167
+
168
+        $defaultRemoteExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no') === 'yes';
169
+        $defaultRemoteExpireDate = $defaultRemoteExpireDateEnforced = null;
170
+        if ($defaultRemoteExpireDateEnabled) {
171
+            $defaultRemoteExpireDate = (int)$this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7');
172
+            $defaultRemoteExpireDateEnforced = $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes';
173
+        }
174
+
175
+        $countOfDataLocation = 0;
176
+        $dataLocation = str_replace(\OC::$SERVERROOT . '/', '', $this->config->getSystemValue('datadirectory', ''), $countOfDataLocation);
177
+        if ($countOfDataLocation !== 1 || $uid === null || !$this->groupManager->isAdmin($uid)) {
178
+            $dataLocation = false;
179
+        }
180
+
181
+        if ($this->currentUser instanceof IUser) {
182
+            $lastConfirmTimestamp = $this->session->get('last-password-confirm');
183
+            if (!is_int($lastConfirmTimestamp)) {
184
+                $lastConfirmTimestamp = 0;
185
+            }
186
+        } else {
187
+            $lastConfirmTimestamp = 0;
188
+        }
189
+
190
+        $capabilities = $this->capabilitiesManager->getCapabilities();
191
+
192
+        $config = [
193
+            'session_lifetime' => min($this->config->getSystemValue('session_lifetime', $this->iniWrapper->getNumeric('session.gc_maxlifetime')), $this->iniWrapper->getNumeric('session.gc_maxlifetime')),
194
+            'session_keepalive' => $this->config->getSystemValue('session_keepalive', true),
195
+            'auto_logout' => $this->config->getSystemValue('auto_logout', false),
196
+            'version' => implode('.', \OCP\Util::getVersion()),
197
+            'versionstring' => \OC_Util::getVersionString(),
198
+            'enable_avatars' => true, // here for legacy reasons - to not crash existing code that relies on this value
199
+            'lost_password_link' => $this->config->getSystemValue('lost_password_link', null),
200
+            'modRewriteWorking' => $this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true',
201
+            'sharing.maxAutocompleteResults' => max(0, $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)),
202
+            'sharing.minSearchStringLength' => $this->config->getSystemValueInt('sharing.minSearchStringLength', 0),
203
+            'blacklist_files_regex' => \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX,
204
+        ];
205
+
206
+        $array = [
207
+            "_oc_debug" => $this->config->getSystemValue('debug', false) ? 'true' : 'false',
208
+            "_oc_isadmin" => $uid !== null && $this->groupManager->isAdmin($uid) ? 'true' : 'false',
209
+            "backendAllowsPasswordConfirmation" => $userBackendAllowsPasswordConfirmation ? 'true' : 'false',
210
+            "oc_dataURL" => is_string($dataLocation) ? "\"" . $dataLocation . "\"" : 'false',
211
+            "_oc_webroot" => "\"" . \OC::$WEBROOT . "\"",
212
+            "_oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution
213
+            "datepickerFormatDate" => json_encode($this->l->l('jsdate', null)),
214
+            'nc_lastLogin' => $lastConfirmTimestamp,
215
+            'nc_pageLoad' => time(),
216
+            "dayNames" => json_encode([
217
+                $this->l->t('Sunday'),
218
+                $this->l->t('Monday'),
219
+                $this->l->t('Tuesday'),
220
+                $this->l->t('Wednesday'),
221
+                $this->l->t('Thursday'),
222
+                $this->l->t('Friday'),
223
+                $this->l->t('Saturday')
224
+            ]),
225
+            "dayNamesShort" => json_encode([
226
+                $this->l->t('Sun.'),
227
+                $this->l->t('Mon.'),
228
+                $this->l->t('Tue.'),
229
+                $this->l->t('Wed.'),
230
+                $this->l->t('Thu.'),
231
+                $this->l->t('Fri.'),
232
+                $this->l->t('Sat.')
233
+            ]),
234
+            "dayNamesMin" => json_encode([
235
+                $this->l->t('Su'),
236
+                $this->l->t('Mo'),
237
+                $this->l->t('Tu'),
238
+                $this->l->t('We'),
239
+                $this->l->t('Th'),
240
+                $this->l->t('Fr'),
241
+                $this->l->t('Sa')
242
+            ]),
243
+            "monthNames" => json_encode([
244
+                $this->l->t('January'),
245
+                $this->l->t('February'),
246
+                $this->l->t('March'),
247
+                $this->l->t('April'),
248
+                $this->l->t('May'),
249
+                $this->l->t('June'),
250
+                $this->l->t('July'),
251
+                $this->l->t('August'),
252
+                $this->l->t('September'),
253
+                $this->l->t('October'),
254
+                $this->l->t('November'),
255
+                $this->l->t('December')
256
+            ]),
257
+            "monthNamesShort" => json_encode([
258
+                $this->l->t('Jan.'),
259
+                $this->l->t('Feb.'),
260
+                $this->l->t('Mar.'),
261
+                $this->l->t('Apr.'),
262
+                $this->l->t('May.'),
263
+                $this->l->t('Jun.'),
264
+                $this->l->t('Jul.'),
265
+                $this->l->t('Aug.'),
266
+                $this->l->t('Sep.'),
267
+                $this->l->t('Oct.'),
268
+                $this->l->t('Nov.'),
269
+                $this->l->t('Dec.')
270
+            ]),
271
+            "firstDay" => json_encode($this->l->l('firstday', null)),
272
+            "_oc_config" => json_encode($config),
273
+            "oc_appconfig" => json_encode([
274
+                'core' => [
275
+                    'defaultExpireDateEnabled' => $defaultExpireDateEnabled,
276
+                    'defaultExpireDate' => $defaultExpireDate,
277
+                    'defaultExpireDateEnforced' => $enforceDefaultExpireDate,
278
+                    'enforcePasswordForPublicLink' => \OCP\Util::isPublicLinkPasswordRequired(),
279
+                    'enableLinkPasswordByDefault' => $enableLinkPasswordByDefault,
280
+                    'sharingDisabledForUser' => \OCP\Util::isSharingDisabledForUser(),
281
+                    'resharingAllowed' => \OC\Share\Share::isResharingAllowed(),
282
+                    'remoteShareAllowed' => $outgoingServer2serverShareEnabled,
283
+                    'federatedCloudShareDoc' => $this->urlGenerator->linkToDocs('user-sharing-federated'),
284
+                    'allowGroupSharing' => \OC::$server->getShareManager()->allowGroupSharing(),
285
+                    'defaultInternalExpireDateEnabled' => $defaultInternalExpireDateEnabled,
286
+                    'defaultInternalExpireDate' => $defaultInternalExpireDate,
287
+                    'defaultInternalExpireDateEnforced' => $defaultInternalExpireDateEnforced,
288
+                    'defaultRemoteExpireDateEnabled' => $defaultRemoteExpireDateEnabled,
289
+                    'defaultRemoteExpireDate' => $defaultRemoteExpireDate,
290
+                    'defaultRemoteExpireDateEnforced' => $defaultRemoteExpireDateEnforced,
291
+                ]
292
+            ]),
293
+            "_theme" => json_encode([
294
+                'entity' => $this->defaults->getEntity(),
295
+                'name' => $this->defaults->getName(),
296
+                'productName' => $this->defaults->getProductName(),
297
+                'title' => $this->defaults->getTitle(),
298
+                'baseUrl' => $this->defaults->getBaseUrl(),
299
+                'syncClientUrl' => $this->defaults->getSyncClientUrl(),
300
+                'docBaseUrl' => $this->defaults->getDocBaseUrl(),
301
+                'docPlaceholderUrl' => $this->defaults->buildDocLinkToKey('PLACEHOLDER'),
302
+                'slogan' => $this->defaults->getSlogan(),
303
+                'logoClaim' => '',
304
+                'shortFooter' => $this->defaults->getShortFooter(),
305
+                'longFooter' => $this->defaults->getLongFooter(),
306
+                'folder' => \OC_Util::getTheme(),
307
+            ]),
308
+        ];
309
+
310
+        if ($this->currentUser !== null) {
311
+            $array['oc_userconfig'] = json_encode([
312
+                'avatar' => [
313
+                    'version' => (int)$this->config->getUserValue($uid, 'avatar', 'version', 0),
314
+                    'generated' => $this->config->getUserValue($uid, 'avatar', 'generated', 'true') === 'true',
315
+                ]
316
+            ]);
317
+        }
318
+
319
+        $this->initialStateService->provideInitialState('core', 'config', $config);
320
+        $this->initialStateService->provideInitialState('core', 'capabilities', $capabilities);
321
+
322
+        // Allow hooks to modify the output values
323
+        \OC_Hook::emit('\OCP\Config', 'js', ['array' => &$array]);
324
+
325
+        $result = '';
326
+
327
+        // Echo it
328
+        foreach ($array as  $setting => $value) {
329
+            $result .= 'var '. $setting . '='. $value . ';' . PHP_EOL;
330
+        }
331
+
332
+        return $result;
333
+    }
334 334
 }
Please login to merge, or discard this patch.
lib/private/Setup.php 2 patches
Indentation   +541 added lines, -541 removed lines patch added patch discarded remove patch
@@ -64,545 +64,545 @@
 block discarded – undo
64 64
 use Psr\Log\LoggerInterface;
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 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
-		return \PDO::getAvailableDrivers();
135
-	}
136
-
137
-	/**
138
-	 * Get the available and supported databases of this instance
139
-	 *
140
-	 * @param bool $allowAllDatabases
141
-	 * @return array
142
-	 * @throws Exception
143
-	 */
144
-	public function getSupportedDatabases($allowAllDatabases = false) {
145
-		$availableDatabases = [
146
-			'sqlite' => [
147
-				'type' => 'pdo',
148
-				'call' => 'sqlite',
149
-				'name' => 'SQLite',
150
-			],
151
-			'mysql' => [
152
-				'type' => 'pdo',
153
-				'call' => 'mysql',
154
-				'name' => 'MySQL/MariaDB',
155
-			],
156
-			'pgsql' => [
157
-				'type' => 'pdo',
158
-				'call' => 'pgsql',
159
-				'name' => 'PostgreSQL',
160
-			],
161
-			'oci' => [
162
-				'type' => 'function',
163
-				'call' => 'oci_connect',
164
-				'name' => 'Oracle',
165
-			],
166
-		];
167
-		if ($allowAllDatabases) {
168
-			$configuredDatabases = array_keys($availableDatabases);
169
-		} else {
170
-			$configuredDatabases = $this->config->getValue('supportedDatabases',
171
-				['sqlite', 'mysql', 'pgsql']);
172
-		}
173
-		if (!is_array($configuredDatabases)) {
174
-			throw new Exception('Supported databases are not properly configured.');
175
-		}
176
-
177
-		$supportedDatabases = [];
178
-
179
-		foreach ($configuredDatabases as $database) {
180
-			if (array_key_exists($database, $availableDatabases)) {
181
-				$working = false;
182
-				$type = $availableDatabases[$database]['type'];
183
-				$call = $availableDatabases[$database]['call'];
184
-
185
-				if ($type === 'function') {
186
-					$working = $this->is_callable($call);
187
-				} elseif ($type === 'pdo') {
188
-					$working = in_array($call, $this->getAvailableDbDriversForPdo(), true);
189
-				}
190
-				if ($working) {
191
-					$supportedDatabases[$database] = $availableDatabases[$database]['name'];
192
-				}
193
-			}
194
-		}
195
-
196
-		return $supportedDatabases;
197
-	}
198
-
199
-	/**
200
-	 * Gathers system information like database type and does
201
-	 * a few system checks.
202
-	 *
203
-	 * @return array of system info, including an "errors" value
204
-	 * in case of errors/warnings
205
-	 */
206
-	public function getSystemInfo($allowAllDatabases = false) {
207
-		$databases = $this->getSupportedDatabases($allowAllDatabases);
208
-
209
-		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
210
-
211
-		$errors = [];
212
-
213
-		// Create data directory to test whether the .htaccess works
214
-		// Notice that this is not necessarily the same data directory as the one
215
-		// that will effectively be used.
216
-		if (!file_exists($dataDir)) {
217
-			@mkdir($dataDir);
218
-		}
219
-		$htAccessWorking = true;
220
-		if (is_dir($dataDir) && is_writable($dataDir)) {
221
-			// Protect data directory here, so we can test if the protection is working
222
-			self::protectDataDirectory();
223
-
224
-			try {
225
-				$util = new \OC_Util();
226
-				$htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
227
-			} catch (\OC\HintException $e) {
228
-				$errors[] = [
229
-					'error' => $e->getMessage(),
230
-					'exception' => $e,
231
-					'hint' => $e->getHint(),
232
-				];
233
-				$htAccessWorking = false;
234
-			}
235
-		}
236
-
237
-		if (\OC_Util::runningOnMac()) {
238
-			$errors[] = [
239
-				'error' => $this->l10n->t(
240
-					'Mac OS X is not supported and %s will not work properly on this platform. ' .
241
-					'Use it at your own risk! ',
242
-					[$this->defaults->getProductName()]
243
-				),
244
-				'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.'),
245
-			];
246
-		}
247
-
248
-		if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
249
-			$errors[] = [
250
-				'error' => $this->l10n->t(
251
-					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
252
-					'This will lead to problems with files over 4 GB and is highly discouraged.',
253
-					[$this->defaults->getProductName()]
254
-				),
255
-				'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.'),
256
-			];
257
-		}
258
-
259
-		return [
260
-			'hasSQLite' => isset($databases['sqlite']),
261
-			'hasMySQL' => isset($databases['mysql']),
262
-			'hasPostgreSQL' => isset($databases['pgsql']),
263
-			'hasOracle' => isset($databases['oci']),
264
-			'databases' => $databases,
265
-			'directory' => $dataDir,
266
-			'htaccessWorking' => $htAccessWorking,
267
-			'errors' => $errors,
268
-		];
269
-	}
270
-
271
-	/**
272
-	 * @param $options
273
-	 * @return array
274
-	 */
275
-	public function install($options) {
276
-		$l = $this->l10n;
277
-
278
-		$error = [];
279
-		$dbType = $options['dbtype'];
280
-
281
-		if (empty($options['adminlogin'])) {
282
-			$error[] = $l->t('Set an admin username.');
283
-		}
284
-		if (empty($options['adminpass'])) {
285
-			$error[] = $l->t('Set an admin password.');
286
-		}
287
-		if (empty($options['directory'])) {
288
-			$options['directory'] = \OC::$SERVERROOT . "/data";
289
-		}
290
-
291
-		if (!isset(self::$dbSetupClasses[$dbType])) {
292
-			$dbType = 'sqlite';
293
-		}
294
-
295
-		$username = htmlspecialchars_decode($options['adminlogin']);
296
-		$password = htmlspecialchars_decode($options['adminpass']);
297
-		$dataDir = htmlspecialchars_decode($options['directory']);
298
-
299
-		$class = self::$dbSetupClasses[$dbType];
300
-		/** @var \OC\Setup\AbstractDatabase $dbSetup */
301
-		$dbSetup = new $class($l, $this->config, $this->logger, $this->random);
302
-		$error = array_merge($error, $dbSetup->validate($options));
303
-
304
-		// validate the data directory
305
-		if ((!is_dir($dataDir) && !mkdir($dataDir)) || !is_writable($dataDir)) {
306
-			$error[] = $l->t("Cannot create or write into the data directory %s", [$dataDir]);
307
-		}
308
-
309
-		if (!empty($error)) {
310
-			return $error;
311
-		}
312
-
313
-		$request = \OC::$server->getRequest();
314
-
315
-		//no errors, good
316
-		if (isset($options['trusted_domains'])
317
-			&& is_array($options['trusted_domains'])) {
318
-			$trustedDomains = $options['trusted_domains'];
319
-		} else {
320
-			$trustedDomains = [$request->getInsecureServerHost()];
321
-		}
322
-
323
-		//use sqlite3 when available, otherwise sqlite2 will be used.
324
-		if ($dbType === 'sqlite' && class_exists('SQLite3')) {
325
-			$dbType = 'sqlite3';
326
-		}
327
-
328
-		//generate a random salt that is used to salt the local user passwords
329
-		$salt = $this->random->generate(30);
330
-		// generate a secret
331
-		$secret = $this->random->generate(48);
332
-
333
-		//write the config file
334
-		$newConfigValues = [
335
-			'passwordsalt' => $salt,
336
-			'secret' => $secret,
337
-			'trusted_domains' => $trustedDomains,
338
-			'datadirectory' => $dataDir,
339
-			'dbtype' => $dbType,
340
-			'version' => implode('.', \OCP\Util::getVersion()),
341
-		];
342
-
343
-		if ($this->config->getValue('overwrite.cli.url', null) === null) {
344
-			$newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
345
-		}
346
-
347
-		$this->config->setValues($newConfigValues);
348
-
349
-		$dbSetup->initialize($options);
350
-		try {
351
-			$dbSetup->setupDatabase($username);
352
-		} catch (\OC\DatabaseSetupException $e) {
353
-			$error[] = [
354
-				'error' => $e->getMessage(),
355
-				'exception' => $e,
356
-				'hint' => $e->getHint(),
357
-			];
358
-			return $error;
359
-		} catch (Exception $e) {
360
-			$error[] = [
361
-				'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
362
-				'exception' => $e,
363
-				'hint' => '',
364
-			];
365
-			return $error;
366
-		}
367
-		try {
368
-			// apply necessary migrations
369
-			$dbSetup->runMigrations();
370
-		} catch (Exception $e) {
371
-			$error[] = [
372
-				'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
373
-				'exception' => $e,
374
-				'hint' => '',
375
-			];
376
-			return $error;
377
-		}
378
-
379
-		//create the user and group
380
-		$user = null;
381
-		try {
382
-			$user = \OC::$server->getUserManager()->createUser($username, $password);
383
-			if (!$user) {
384
-				$error[] = "User <$username> could not be created.";
385
-			}
386
-		} catch (Exception $exception) {
387
-			$error[] = $exception->getMessage();
388
-		}
389
-
390
-		if (empty($error)) {
391
-			$config = \OC::$server->getConfig();
392
-			$config->setAppValue('core', 'installedat', microtime(true));
393
-			$config->setAppValue('core', 'lastupdatedat', microtime(true));
394
-			$config->setAppValue('core', 'vendor', $this->getVendor());
395
-
396
-			$group = \OC::$server->getGroupManager()->createGroup('admin');
397
-			if ($group instanceof IGroup) {
398
-				$group->addUser($user);
399
-			}
400
-
401
-			// Install shipped apps and specified app bundles
402
-			Installer::installShippedApps();
403
-			$bundleFetcher = new BundleFetcher(\OC::$server->getL10N('lib'));
404
-			$defaultInstallationBundles = $bundleFetcher->getDefaultInstallationBundle();
405
-			foreach ($defaultInstallationBundles as $bundle) {
406
-				try {
407
-					$this->installer->installAppBundle($bundle);
408
-				} catch (Exception $e) {
409
-				}
410
-			}
411
-
412
-			// create empty file in data dir, so we can later find
413
-			// out that this is indeed an ownCloud data directory
414
-			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
415
-
416
-			// Update .htaccess files
417
-			self::updateHtaccess();
418
-			self::protectDataDirectory();
419
-
420
-			self::installBackgroundJobs();
421
-
422
-			//and we are done
423
-			$config->setSystemValue('installed', true);
424
-
425
-			// Create a session token for the newly created user
426
-			// The token provider requires a working db, so it's not injected on setup
427
-			/* @var $userSession User\Session */
428
-			$userSession = \OC::$server->getUserSession();
429
-			$defaultTokenProvider = \OC::$server->query(DefaultTokenProvider::class);
430
-			$userSession->setTokenProvider($defaultTokenProvider);
431
-			$userSession->login($username, $password);
432
-			$userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
433
-
434
-			$session = $userSession->getSession();
435
-			$session->set('last-password-confirm', \OC::$server->query(ITimeFactory::class)->getTime());
436
-
437
-			// Set email for admin
438
-			if (!empty($options['adminemail'])) {
439
-				$config->setUserValue($user->getUID(), 'settings', 'email', $options['adminemail']);
440
-			}
441
-		}
442
-
443
-		return $error;
444
-	}
445
-
446
-	public static function installBackgroundJobs() {
447
-		$jobList = \OC::$server->getJobList();
448
-		$jobList->add(DefaultTokenCleanupJob::class);
449
-		$jobList->add(Rotate::class);
450
-		$jobList->add(BackgroundCleanupJob::class);
451
-	}
452
-
453
-	/**
454
-	 * @return string Absolute path to htaccess
455
-	 */
456
-	private function pathToHtaccess() {
457
-		return \OC::$SERVERROOT . '/.htaccess';
458
-	}
459
-
460
-	/**
461
-	 * Find webroot from config
462
-	 *
463
-	 * @param SystemConfig $config
464
-	 * @return string
465
-	 * @throws InvalidArgumentException when invalid value for overwrite.cli.url
466
-	 */
467
-	private static function findWebRoot(SystemConfig $config): string {
468
-		// For CLI read the value from overwrite.cli.url
469
-		if (\OC::$CLI) {
470
-			$webRoot = $config->getValue('overwrite.cli.url', '');
471
-			if ($webRoot === '') {
472
-				throw new InvalidArgumentException('overwrite.cli.url is empty');
473
-			}
474
-			if (!filter_var($webRoot, FILTER_VALIDATE_URL)) {
475
-				throw new InvalidArgumentException('invalid value for overwrite.cli.url');
476
-			}
477
-			$webRoot = rtrim(parse_url($webRoot, PHP_URL_PATH), '/');
478
-		} else {
479
-			$webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
480
-		}
481
-
482
-		return $webRoot;
483
-	}
484
-
485
-	/**
486
-	 * Append the correct ErrorDocument path for Apache hosts
487
-	 *
488
-	 * @return bool True when success, False otherwise
489
-	 * @throws \OCP\AppFramework\QueryException
490
-	 */
491
-	public static function updateHtaccess() {
492
-		$config = \OC::$server->getSystemConfig();
493
-
494
-		try {
495
-			$webRoot = self::findWebRoot($config);
496
-		} catch (InvalidArgumentException $e) {
497
-			return false;
498
-		}
499
-
500
-		$setupHelper = new \OC\Setup(
501
-			$config,
502
-			\OC::$server->get(IniGetWrapper::class),
503
-			\OC::$server->getL10N('lib'),
504
-			\OC::$server->query(Defaults::class),
505
-			\OC::$server->get(LoggerInterface::class),
506
-			\OC::$server->getSecureRandom(),
507
-			\OC::$server->query(Installer::class)
508
-		);
509
-
510
-		$htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
511
-		$content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
512
-		$htaccessContent = explode($content, $htaccessContent, 2)[0];
513
-
514
-		//custom 403 error page
515
-		$content .= "\nErrorDocument 403 " . $webRoot . '/';
516
-
517
-		//custom 404 error page
518
-		$content .= "\nErrorDocument 404 " . $webRoot . '/';
519
-
520
-		// Add rewrite rules if the RewriteBase is configured
521
-		$rewriteBase = $config->getValue('htaccess.RewriteBase', '');
522
-		if ($rewriteBase !== '') {
523
-			$content .= "\n<IfModule mod_rewrite.c>";
524
-			$content .= "\n  Options -MultiViews";
525
-			$content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
526
-			$content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
527
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav)$";
528
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$";
529
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/manifest.json$";
530
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/remote.php";
531
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/public.php";
532
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/cron.php";
533
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php";
534
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/status.php";
535
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php";
536
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php";
537
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots.txt";
538
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/updater/";
539
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
540
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocm-provider/";
541
-			$content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
542
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
543
-			$content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
544
-			$content .= "\n  RewriteBase " . $rewriteBase;
545
-			$content .= "\n  <IfModule mod_env.c>";
546
-			$content .= "\n    SetEnv front_controller_active true";
547
-			$content .= "\n    <IfModule mod_dir.c>";
548
-			$content .= "\n      DirectorySlash off";
549
-			$content .= "\n    </IfModule>";
550
-			$content .= "\n  </IfModule>";
551
-			$content .= "\n</IfModule>";
552
-		}
553
-
554
-		if ($content !== '') {
555
-			//suppress errors in case we don't have permissions for it
556
-			return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
557
-		}
558
-
559
-		return false;
560
-	}
561
-
562
-	public static function protectDataDirectory() {
563
-		//Require all denied
564
-		$now = date('Y-m-d H:i:s');
565
-		$content = "# Generated by Nextcloud on $now\n";
566
-		$content .= "# Section for Apache 2.4 to 2.6\n";
567
-		$content .= "<IfModule mod_authz_core.c>\n";
568
-		$content .= "  Require all denied\n";
569
-		$content .= "</IfModule>\n";
570
-		$content .= "<IfModule mod_access_compat.c>\n";
571
-		$content .= "  Order Allow,Deny\n";
572
-		$content .= "  Deny from all\n";
573
-		$content .= "  Satisfy All\n";
574
-		$content .= "</IfModule>\n\n";
575
-		$content .= "# Section for Apache 2.2\n";
576
-		$content .= "<IfModule !mod_authz_core.c>\n";
577
-		$content .= "  <IfModule !mod_access_compat.c>\n";
578
-		$content .= "    <IfModule mod_authz_host.c>\n";
579
-		$content .= "      Order Allow,Deny\n";
580
-		$content .= "      Deny from all\n";
581
-		$content .= "    </IfModule>\n";
582
-		$content .= "    Satisfy All\n";
583
-		$content .= "  </IfModule>\n";
584
-		$content .= "</IfModule>\n\n";
585
-		$content .= "# Section for Apache 2.2 to 2.6\n";
586
-		$content .= "<IfModule mod_autoindex.c>\n";
587
-		$content .= "  IndexIgnore *\n";
588
-		$content .= "</IfModule>";
589
-
590
-		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
591
-		file_put_contents($baseDir . '/.htaccess', $content);
592
-		file_put_contents($baseDir . '/index.html', '');
593
-	}
594
-
595
-	/**
596
-	 * Return vendor from which this version was published
597
-	 *
598
-	 * @return string Get the vendor
599
-	 *
600
-	 * Copy of \OC\Updater::getVendor()
601
-	 */
602
-	private function getVendor() {
603
-		// this should really be a JSON file
604
-		require \OC::$SERVERROOT . '/version.php';
605
-		/** @var string $vendor */
606
-		return (string)$vendor;
607
-	}
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
+        return \PDO::getAvailableDrivers();
135
+    }
136
+
137
+    /**
138
+     * Get the available and supported databases of this instance
139
+     *
140
+     * @param bool $allowAllDatabases
141
+     * @return array
142
+     * @throws Exception
143
+     */
144
+    public function getSupportedDatabases($allowAllDatabases = false) {
145
+        $availableDatabases = [
146
+            'sqlite' => [
147
+                'type' => 'pdo',
148
+                'call' => 'sqlite',
149
+                'name' => 'SQLite',
150
+            ],
151
+            'mysql' => [
152
+                'type' => 'pdo',
153
+                'call' => 'mysql',
154
+                'name' => 'MySQL/MariaDB',
155
+            ],
156
+            'pgsql' => [
157
+                'type' => 'pdo',
158
+                'call' => 'pgsql',
159
+                'name' => 'PostgreSQL',
160
+            ],
161
+            'oci' => [
162
+                'type' => 'function',
163
+                'call' => 'oci_connect',
164
+                'name' => 'Oracle',
165
+            ],
166
+        ];
167
+        if ($allowAllDatabases) {
168
+            $configuredDatabases = array_keys($availableDatabases);
169
+        } else {
170
+            $configuredDatabases = $this->config->getValue('supportedDatabases',
171
+                ['sqlite', 'mysql', 'pgsql']);
172
+        }
173
+        if (!is_array($configuredDatabases)) {
174
+            throw new Exception('Supported databases are not properly configured.');
175
+        }
176
+
177
+        $supportedDatabases = [];
178
+
179
+        foreach ($configuredDatabases as $database) {
180
+            if (array_key_exists($database, $availableDatabases)) {
181
+                $working = false;
182
+                $type = $availableDatabases[$database]['type'];
183
+                $call = $availableDatabases[$database]['call'];
184
+
185
+                if ($type === 'function') {
186
+                    $working = $this->is_callable($call);
187
+                } elseif ($type === 'pdo') {
188
+                    $working = in_array($call, $this->getAvailableDbDriversForPdo(), true);
189
+                }
190
+                if ($working) {
191
+                    $supportedDatabases[$database] = $availableDatabases[$database]['name'];
192
+                }
193
+            }
194
+        }
195
+
196
+        return $supportedDatabases;
197
+    }
198
+
199
+    /**
200
+     * Gathers system information like database type and does
201
+     * a few system checks.
202
+     *
203
+     * @return array of system info, including an "errors" value
204
+     * in case of errors/warnings
205
+     */
206
+    public function getSystemInfo($allowAllDatabases = false) {
207
+        $databases = $this->getSupportedDatabases($allowAllDatabases);
208
+
209
+        $dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
210
+
211
+        $errors = [];
212
+
213
+        // Create data directory to test whether the .htaccess works
214
+        // Notice that this is not necessarily the same data directory as the one
215
+        // that will effectively be used.
216
+        if (!file_exists($dataDir)) {
217
+            @mkdir($dataDir);
218
+        }
219
+        $htAccessWorking = true;
220
+        if (is_dir($dataDir) && is_writable($dataDir)) {
221
+            // Protect data directory here, so we can test if the protection is working
222
+            self::protectDataDirectory();
223
+
224
+            try {
225
+                $util = new \OC_Util();
226
+                $htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
227
+            } catch (\OC\HintException $e) {
228
+                $errors[] = [
229
+                    'error' => $e->getMessage(),
230
+                    'exception' => $e,
231
+                    'hint' => $e->getHint(),
232
+                ];
233
+                $htAccessWorking = false;
234
+            }
235
+        }
236
+
237
+        if (\OC_Util::runningOnMac()) {
238
+            $errors[] = [
239
+                'error' => $this->l10n->t(
240
+                    'Mac OS X is not supported and %s will not work properly on this platform. ' .
241
+                    'Use it at your own risk! ',
242
+                    [$this->defaults->getProductName()]
243
+                ),
244
+                'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.'),
245
+            ];
246
+        }
247
+
248
+        if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
249
+            $errors[] = [
250
+                'error' => $this->l10n->t(
251
+                    'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
252
+                    'This will lead to problems with files over 4 GB and is highly discouraged.',
253
+                    [$this->defaults->getProductName()]
254
+                ),
255
+                'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.'),
256
+            ];
257
+        }
258
+
259
+        return [
260
+            'hasSQLite' => isset($databases['sqlite']),
261
+            'hasMySQL' => isset($databases['mysql']),
262
+            'hasPostgreSQL' => isset($databases['pgsql']),
263
+            'hasOracle' => isset($databases['oci']),
264
+            'databases' => $databases,
265
+            'directory' => $dataDir,
266
+            'htaccessWorking' => $htAccessWorking,
267
+            'errors' => $errors,
268
+        ];
269
+    }
270
+
271
+    /**
272
+     * @param $options
273
+     * @return array
274
+     */
275
+    public function install($options) {
276
+        $l = $this->l10n;
277
+
278
+        $error = [];
279
+        $dbType = $options['dbtype'];
280
+
281
+        if (empty($options['adminlogin'])) {
282
+            $error[] = $l->t('Set an admin username.');
283
+        }
284
+        if (empty($options['adminpass'])) {
285
+            $error[] = $l->t('Set an admin password.');
286
+        }
287
+        if (empty($options['directory'])) {
288
+            $options['directory'] = \OC::$SERVERROOT . "/data";
289
+        }
290
+
291
+        if (!isset(self::$dbSetupClasses[$dbType])) {
292
+            $dbType = 'sqlite';
293
+        }
294
+
295
+        $username = htmlspecialchars_decode($options['adminlogin']);
296
+        $password = htmlspecialchars_decode($options['adminpass']);
297
+        $dataDir = htmlspecialchars_decode($options['directory']);
298
+
299
+        $class = self::$dbSetupClasses[$dbType];
300
+        /** @var \OC\Setup\AbstractDatabase $dbSetup */
301
+        $dbSetup = new $class($l, $this->config, $this->logger, $this->random);
302
+        $error = array_merge($error, $dbSetup->validate($options));
303
+
304
+        // validate the data directory
305
+        if ((!is_dir($dataDir) && !mkdir($dataDir)) || !is_writable($dataDir)) {
306
+            $error[] = $l->t("Cannot create or write into the data directory %s", [$dataDir]);
307
+        }
308
+
309
+        if (!empty($error)) {
310
+            return $error;
311
+        }
312
+
313
+        $request = \OC::$server->getRequest();
314
+
315
+        //no errors, good
316
+        if (isset($options['trusted_domains'])
317
+            && is_array($options['trusted_domains'])) {
318
+            $trustedDomains = $options['trusted_domains'];
319
+        } else {
320
+            $trustedDomains = [$request->getInsecureServerHost()];
321
+        }
322
+
323
+        //use sqlite3 when available, otherwise sqlite2 will be used.
324
+        if ($dbType === 'sqlite' && class_exists('SQLite3')) {
325
+            $dbType = 'sqlite3';
326
+        }
327
+
328
+        //generate a random salt that is used to salt the local user passwords
329
+        $salt = $this->random->generate(30);
330
+        // generate a secret
331
+        $secret = $this->random->generate(48);
332
+
333
+        //write the config file
334
+        $newConfigValues = [
335
+            'passwordsalt' => $salt,
336
+            'secret' => $secret,
337
+            'trusted_domains' => $trustedDomains,
338
+            'datadirectory' => $dataDir,
339
+            'dbtype' => $dbType,
340
+            'version' => implode('.', \OCP\Util::getVersion()),
341
+        ];
342
+
343
+        if ($this->config->getValue('overwrite.cli.url', null) === null) {
344
+            $newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
345
+        }
346
+
347
+        $this->config->setValues($newConfigValues);
348
+
349
+        $dbSetup->initialize($options);
350
+        try {
351
+            $dbSetup->setupDatabase($username);
352
+        } catch (\OC\DatabaseSetupException $e) {
353
+            $error[] = [
354
+                'error' => $e->getMessage(),
355
+                'exception' => $e,
356
+                'hint' => $e->getHint(),
357
+            ];
358
+            return $error;
359
+        } catch (Exception $e) {
360
+            $error[] = [
361
+                'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
362
+                'exception' => $e,
363
+                'hint' => '',
364
+            ];
365
+            return $error;
366
+        }
367
+        try {
368
+            // apply necessary migrations
369
+            $dbSetup->runMigrations();
370
+        } catch (Exception $e) {
371
+            $error[] = [
372
+                'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
373
+                'exception' => $e,
374
+                'hint' => '',
375
+            ];
376
+            return $error;
377
+        }
378
+
379
+        //create the user and group
380
+        $user = null;
381
+        try {
382
+            $user = \OC::$server->getUserManager()->createUser($username, $password);
383
+            if (!$user) {
384
+                $error[] = "User <$username> could not be created.";
385
+            }
386
+        } catch (Exception $exception) {
387
+            $error[] = $exception->getMessage();
388
+        }
389
+
390
+        if (empty($error)) {
391
+            $config = \OC::$server->getConfig();
392
+            $config->setAppValue('core', 'installedat', microtime(true));
393
+            $config->setAppValue('core', 'lastupdatedat', microtime(true));
394
+            $config->setAppValue('core', 'vendor', $this->getVendor());
395
+
396
+            $group = \OC::$server->getGroupManager()->createGroup('admin');
397
+            if ($group instanceof IGroup) {
398
+                $group->addUser($user);
399
+            }
400
+
401
+            // Install shipped apps and specified app bundles
402
+            Installer::installShippedApps();
403
+            $bundleFetcher = new BundleFetcher(\OC::$server->getL10N('lib'));
404
+            $defaultInstallationBundles = $bundleFetcher->getDefaultInstallationBundle();
405
+            foreach ($defaultInstallationBundles as $bundle) {
406
+                try {
407
+                    $this->installer->installAppBundle($bundle);
408
+                } catch (Exception $e) {
409
+                }
410
+            }
411
+
412
+            // create empty file in data dir, so we can later find
413
+            // out that this is indeed an ownCloud data directory
414
+            file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
415
+
416
+            // Update .htaccess files
417
+            self::updateHtaccess();
418
+            self::protectDataDirectory();
419
+
420
+            self::installBackgroundJobs();
421
+
422
+            //and we are done
423
+            $config->setSystemValue('installed', true);
424
+
425
+            // Create a session token for the newly created user
426
+            // The token provider requires a working db, so it's not injected on setup
427
+            /* @var $userSession User\Session */
428
+            $userSession = \OC::$server->getUserSession();
429
+            $defaultTokenProvider = \OC::$server->query(DefaultTokenProvider::class);
430
+            $userSession->setTokenProvider($defaultTokenProvider);
431
+            $userSession->login($username, $password);
432
+            $userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
433
+
434
+            $session = $userSession->getSession();
435
+            $session->set('last-password-confirm', \OC::$server->query(ITimeFactory::class)->getTime());
436
+
437
+            // Set email for admin
438
+            if (!empty($options['adminemail'])) {
439
+                $config->setUserValue($user->getUID(), 'settings', 'email', $options['adminemail']);
440
+            }
441
+        }
442
+
443
+        return $error;
444
+    }
445
+
446
+    public static function installBackgroundJobs() {
447
+        $jobList = \OC::$server->getJobList();
448
+        $jobList->add(DefaultTokenCleanupJob::class);
449
+        $jobList->add(Rotate::class);
450
+        $jobList->add(BackgroundCleanupJob::class);
451
+    }
452
+
453
+    /**
454
+     * @return string Absolute path to htaccess
455
+     */
456
+    private function pathToHtaccess() {
457
+        return \OC::$SERVERROOT . '/.htaccess';
458
+    }
459
+
460
+    /**
461
+     * Find webroot from config
462
+     *
463
+     * @param SystemConfig $config
464
+     * @return string
465
+     * @throws InvalidArgumentException when invalid value for overwrite.cli.url
466
+     */
467
+    private static function findWebRoot(SystemConfig $config): string {
468
+        // For CLI read the value from overwrite.cli.url
469
+        if (\OC::$CLI) {
470
+            $webRoot = $config->getValue('overwrite.cli.url', '');
471
+            if ($webRoot === '') {
472
+                throw new InvalidArgumentException('overwrite.cli.url is empty');
473
+            }
474
+            if (!filter_var($webRoot, FILTER_VALIDATE_URL)) {
475
+                throw new InvalidArgumentException('invalid value for overwrite.cli.url');
476
+            }
477
+            $webRoot = rtrim(parse_url($webRoot, PHP_URL_PATH), '/');
478
+        } else {
479
+            $webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
480
+        }
481
+
482
+        return $webRoot;
483
+    }
484
+
485
+    /**
486
+     * Append the correct ErrorDocument path for Apache hosts
487
+     *
488
+     * @return bool True when success, False otherwise
489
+     * @throws \OCP\AppFramework\QueryException
490
+     */
491
+    public static function updateHtaccess() {
492
+        $config = \OC::$server->getSystemConfig();
493
+
494
+        try {
495
+            $webRoot = self::findWebRoot($config);
496
+        } catch (InvalidArgumentException $e) {
497
+            return false;
498
+        }
499
+
500
+        $setupHelper = new \OC\Setup(
501
+            $config,
502
+            \OC::$server->get(IniGetWrapper::class),
503
+            \OC::$server->getL10N('lib'),
504
+            \OC::$server->query(Defaults::class),
505
+            \OC::$server->get(LoggerInterface::class),
506
+            \OC::$server->getSecureRandom(),
507
+            \OC::$server->query(Installer::class)
508
+        );
509
+
510
+        $htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
511
+        $content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
512
+        $htaccessContent = explode($content, $htaccessContent, 2)[0];
513
+
514
+        //custom 403 error page
515
+        $content .= "\nErrorDocument 403 " . $webRoot . '/';
516
+
517
+        //custom 404 error page
518
+        $content .= "\nErrorDocument 404 " . $webRoot . '/';
519
+
520
+        // Add rewrite rules if the RewriteBase is configured
521
+        $rewriteBase = $config->getValue('htaccess.RewriteBase', '');
522
+        if ($rewriteBase !== '') {
523
+            $content .= "\n<IfModule mod_rewrite.c>";
524
+            $content .= "\n  Options -MultiViews";
525
+            $content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
526
+            $content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
527
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav)$";
528
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$";
529
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/manifest.json$";
530
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/remote.php";
531
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/public.php";
532
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/cron.php";
533
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php";
534
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/status.php";
535
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php";
536
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php";
537
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots.txt";
538
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/updater/";
539
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
540
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocm-provider/";
541
+            $content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
542
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
543
+            $content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
544
+            $content .= "\n  RewriteBase " . $rewriteBase;
545
+            $content .= "\n  <IfModule mod_env.c>";
546
+            $content .= "\n    SetEnv front_controller_active true";
547
+            $content .= "\n    <IfModule mod_dir.c>";
548
+            $content .= "\n      DirectorySlash off";
549
+            $content .= "\n    </IfModule>";
550
+            $content .= "\n  </IfModule>";
551
+            $content .= "\n</IfModule>";
552
+        }
553
+
554
+        if ($content !== '') {
555
+            //suppress errors in case we don't have permissions for it
556
+            return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
557
+        }
558
+
559
+        return false;
560
+    }
561
+
562
+    public static function protectDataDirectory() {
563
+        //Require all denied
564
+        $now = date('Y-m-d H:i:s');
565
+        $content = "# Generated by Nextcloud on $now\n";
566
+        $content .= "# Section for Apache 2.4 to 2.6\n";
567
+        $content .= "<IfModule mod_authz_core.c>\n";
568
+        $content .= "  Require all denied\n";
569
+        $content .= "</IfModule>\n";
570
+        $content .= "<IfModule mod_access_compat.c>\n";
571
+        $content .= "  Order Allow,Deny\n";
572
+        $content .= "  Deny from all\n";
573
+        $content .= "  Satisfy All\n";
574
+        $content .= "</IfModule>\n\n";
575
+        $content .= "# Section for Apache 2.2\n";
576
+        $content .= "<IfModule !mod_authz_core.c>\n";
577
+        $content .= "  <IfModule !mod_access_compat.c>\n";
578
+        $content .= "    <IfModule mod_authz_host.c>\n";
579
+        $content .= "      Order Allow,Deny\n";
580
+        $content .= "      Deny from all\n";
581
+        $content .= "    </IfModule>\n";
582
+        $content .= "    Satisfy All\n";
583
+        $content .= "  </IfModule>\n";
584
+        $content .= "</IfModule>\n\n";
585
+        $content .= "# Section for Apache 2.2 to 2.6\n";
586
+        $content .= "<IfModule mod_autoindex.c>\n";
587
+        $content .= "  IndexIgnore *\n";
588
+        $content .= "</IfModule>";
589
+
590
+        $baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
591
+        file_put_contents($baseDir . '/.htaccess', $content);
592
+        file_put_contents($baseDir . '/index.html', '');
593
+    }
594
+
595
+    /**
596
+     * Return vendor from which this version was published
597
+     *
598
+     * @return string Get the vendor
599
+     *
600
+     * Copy of \OC\Updater::getVendor()
601
+     */
602
+    private function getVendor() {
603
+        // this should really be a JSON file
604
+        require \OC::$SERVERROOT . '/version.php';
605
+        /** @var string $vendor */
606
+        return (string)$vendor;
607
+    }
608 608
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -206,7 +206,7 @@  discard block
 block discarded – undo
206 206
 	public function getSystemInfo($allowAllDatabases = false) {
207 207
 		$databases = $this->getSupportedDatabases($allowAllDatabases);
208 208
 
209
-		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT . '/data');
209
+		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT.'/data');
210 210
 
211 211
 		$errors = [];
212 212
 
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
 		if (\OC_Util::runningOnMac()) {
238 238
 			$errors[] = [
239 239
 				'error' => $this->l10n->t(
240
-					'Mac OS X is not supported and %s will not work properly on this platform. ' .
240
+					'Mac OS X is not supported and %s will not work properly on this platform. '.
241 241
 					'Use it at your own risk! ',
242 242
 					[$this->defaults->getProductName()]
243 243
 				),
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
 		if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
249 249
 			$errors[] = [
250 250
 				'error' => $this->l10n->t(
251
-					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
251
+					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. '.
252 252
 					'This will lead to problems with files over 4 GB and is highly discouraged.',
253 253
 					[$this->defaults->getProductName()]
254 254
 				),
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
 			$error[] = $l->t('Set an admin password.');
286 286
 		}
287 287
 		if (empty($options['directory'])) {
288
-			$options['directory'] = \OC::$SERVERROOT . "/data";
288
+			$options['directory'] = \OC::$SERVERROOT."/data";
289 289
 		}
290 290
 
291 291
 		if (!isset(self::$dbSetupClasses[$dbType])) {
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
 		];
342 342
 
343 343
 		if ($this->config->getValue('overwrite.cli.url', null) === null) {
344
-			$newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
344
+			$newConfigValues['overwrite.cli.url'] = $request->getServerProtocol().'://'.$request->getInsecureServerHost().\OC::$WEBROOT;
345 345
 		}
346 346
 
347 347
 		$this->config->setValues($newConfigValues);
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
 			return $error;
359 359
 		} catch (Exception $e) {
360 360
 			$error[] = [
361
-				'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
361
+				'error' => 'Error while trying to create admin user: '.$e->getMessage(),
362 362
 				'exception' => $e,
363 363
 				'hint' => '',
364 364
 			];
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
 			$dbSetup->runMigrations();
370 370
 		} catch (Exception $e) {
371 371
 			$error[] = [
372
-				'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
372
+				'error' => 'Error while trying to initialise the database: '.$e->getMessage(),
373 373
 				'exception' => $e,
374 374
 				'hint' => '',
375 375
 			];
@@ -411,7 +411,7 @@  discard block
 block discarded – undo
411 411
 
412 412
 			// create empty file in data dir, so we can later find
413 413
 			// out that this is indeed an ownCloud data directory
414
-			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
414
+			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/.ocdata', '');
415 415
 
416 416
 			// Update .htaccess files
417 417
 			self::updateHtaccess();
@@ -454,7 +454,7 @@  discard block
 block discarded – undo
454 454
 	 * @return string Absolute path to htaccess
455 455
 	 */
456 456
 	private function pathToHtaccess() {
457
-		return \OC::$SERVERROOT . '/.htaccess';
457
+		return \OC::$SERVERROOT.'/.htaccess';
458 458
 	}
459 459
 
460 460
 	/**
@@ -512,10 +512,10 @@  discard block
 block discarded – undo
512 512
 		$htaccessContent = explode($content, $htaccessContent, 2)[0];
513 513
 
514 514
 		//custom 403 error page
515
-		$content .= "\nErrorDocument 403 " . $webRoot . '/';
515
+		$content .= "\nErrorDocument 403 ".$webRoot.'/';
516 516
 
517 517
 		//custom 404 error page
518
-		$content .= "\nErrorDocument 404 " . $webRoot . '/';
518
+		$content .= "\nErrorDocument 404 ".$webRoot.'/';
519 519
 
520 520
 		// Add rewrite rules if the RewriteBase is configured
521 521
 		$rewriteBase = $config->getValue('htaccess.RewriteBase', '');
@@ -541,7 +541,7 @@  discard block
 block discarded – undo
541 541
 			$content .= "\n  RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
542 542
 			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$";
543 543
 			$content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
544
-			$content .= "\n  RewriteBase " . $rewriteBase;
544
+			$content .= "\n  RewriteBase ".$rewriteBase;
545 545
 			$content .= "\n  <IfModule mod_env.c>";
546 546
 			$content .= "\n    SetEnv front_controller_active true";
547 547
 			$content .= "\n    <IfModule mod_dir.c>";
@@ -553,7 +553,7 @@  discard block
 block discarded – undo
553 553
 
554 554
 		if ($content !== '') {
555 555
 			//suppress errors in case we don't have permissions for it
556
-			return (bool)@file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent . $content . "\n");
556
+			return (bool) @file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent.$content."\n");
557 557
 		}
558 558
 
559 559
 		return false;
@@ -587,9 +587,9 @@  discard block
 block discarded – undo
587 587
 		$content .= "  IndexIgnore *\n";
588 588
 		$content .= "</IfModule>";
589 589
 
590
-		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
591
-		file_put_contents($baseDir . '/.htaccess', $content);
592
-		file_put_contents($baseDir . '/index.html', '');
590
+		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data');
591
+		file_put_contents($baseDir.'/.htaccess', $content);
592
+		file_put_contents($baseDir.'/index.html', '');
593 593
 	}
594 594
 
595 595
 	/**
@@ -601,8 +601,8 @@  discard block
 block discarded – undo
601 601
 	 */
602 602
 	private function getVendor() {
603 603
 		// this should really be a JSON file
604
-		require \OC::$SERVERROOT . '/version.php';
604
+		require \OC::$SERVERROOT.'/version.php';
605 605
 		/** @var string $vendor */
606
-		return (string)$vendor;
606
+		return (string) $vendor;
607 607
 	}
608 608
 }
Please login to merge, or discard this patch.