Completed
Pull Request — master (#9293)
by Blizzz
16:29
created
lib/private/Installer.php 3 patches
Indentation   +548 added lines, -548 removed lines patch added patch discarded remove patch
@@ -52,552 +52,552 @@
 block discarded – undo
52 52
  * This class provides the functionality needed to install, update and remove apps
53 53
  */
54 54
 class Installer {
55
-	/** @var AppFetcher */
56
-	private $appFetcher;
57
-	/** @var IClientService */
58
-	private $clientService;
59
-	/** @var ITempManager */
60
-	private $tempManager;
61
-	/** @var ILogger */
62
-	private $logger;
63
-	/** @var IConfig */
64
-	private $config;
65
-	/** @var array - for caching the result of app fetcher */
66
-	private $apps = null;
67
-	/** @var bool|null - for caching the result of the ready status */
68
-	private $isInstanceReadyForUpdates = null;
69
-
70
-	/**
71
-	 * @param AppFetcher $appFetcher
72
-	 * @param IClientService $clientService
73
-	 * @param ITempManager $tempManager
74
-	 * @param ILogger $logger
75
-	 * @param IConfig $config
76
-	 */
77
-	public function __construct(AppFetcher $appFetcher,
78
-								IClientService $clientService,
79
-								ITempManager $tempManager,
80
-								ILogger $logger,
81
-								IConfig $config) {
82
-		$this->appFetcher = $appFetcher;
83
-		$this->clientService = $clientService;
84
-		$this->tempManager = $tempManager;
85
-		$this->logger = $logger;
86
-		$this->config = $config;
87
-	}
88
-
89
-	/**
90
-	 * Installs an app that is located in one of the app folders already
91
-	 *
92
-	 * @param string $appId App to install
93
-	 * @throws \Exception
94
-	 * @return string app ID
95
-	 */
96
-	public function installApp($appId) {
97
-		$app = \OC_App::findAppInDirectories($appId);
98
-		if($app === false) {
99
-			throw new \Exception('App not found in any app directory');
100
-		}
101
-
102
-		$basedir = $app['path'].'/'.$appId;
103
-		$info = OC_App::getAppInfo($basedir.'/appinfo/info.xml', true);
104
-
105
-		$l = \OC::$server->getL10N('core');
106
-
107
-		if(!is_array($info)) {
108
-			throw new \Exception(
109
-				$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
110
-					[$appId]
111
-				)
112
-			);
113
-		}
114
-
115
-		$version = implode('.', \OCP\Util::getVersion());
116
-		if (!\OC_App::isAppCompatible($version, $info)) {
117
-			throw new \Exception(
118
-				// TODO $l
119
-				$l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
120
-					[$info['name']]
121
-				)
122
-			);
123
-		}
124
-
125
-		// check for required dependencies
126
-		\OC_App::checkAppDependencies($this->config, $l, $info);
127
-		\OC_App::registerAutoloading($appId, $basedir);
128
-
129
-		//install the database
130
-		if(is_file($basedir.'/appinfo/database.xml')) {
131
-			if (\OC::$server->getConfig()->getAppValue($info['id'], 'installed_version') === null) {
132
-				OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
133
-			} else {
134
-				OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml');
135
-			}
136
-		} else {
137
-			$ms = new \OC\DB\MigrationService($info['id'], \OC::$server->getDatabaseConnection());
138
-			$ms->migrate();
139
-		}
140
-
141
-		\OC_App::setupBackgroundJobs($info['background-jobs']);
142
-
143
-		//run appinfo/install.php
144
-		self::includeAppScript($basedir . '/appinfo/install.php');
145
-
146
-		$appData = OC_App::getAppInfo($appId);
147
-		OC_App::executeRepairSteps($appId, $appData['repair-steps']['install']);
148
-
149
-		//set the installed version
150
-		\OC::$server->getConfig()->setAppValue($info['id'], 'installed_version', OC_App::getAppVersion($info['id'], false));
151
-		\OC::$server->getConfig()->setAppValue($info['id'], 'enabled', 'no');
152
-
153
-		//set remote/public handlers
154
-		foreach($info['remote'] as $name=>$path) {
155
-			\OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path);
156
-		}
157
-		foreach($info['public'] as $name=>$path) {
158
-			\OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path);
159
-		}
160
-
161
-		OC_App::setAppTypes($info['id']);
162
-
163
-		return $info['id'];
164
-	}
165
-
166
-	/**
167
-	 * Updates the specified app from the appstore
168
-	 *
169
-	 * @param string $appId
170
-	 * @return bool
171
-	 */
172
-	public function updateAppstoreApp($appId) {
173
-		if($this->isUpdateAvailable($appId)) {
174
-			try {
175
-				$this->downloadApp($appId);
176
-			} catch (\Exception $e) {
177
-				$this->logger->logException($e, [
178
-					'level' => ILogger::ERROR,
179
-					'app' => 'core',
180
-				]);
181
-				return false;
182
-			}
183
-			return OC_App::updateApp($appId);
184
-		}
185
-
186
-		return false;
187
-	}
188
-
189
-	/**
190
-	 * Downloads an app and puts it into the app directory
191
-	 *
192
-	 * @param string $appId
193
-	 *
194
-	 * @throws \Exception If the installation was not successful
195
-	 */
196
-	public function downloadApp($appId) {
197
-		$appId = strtolower($appId);
198
-
199
-		$apps = $this->appFetcher->get();
200
-		foreach($apps as $app) {
201
-			if($app['id'] === $appId) {
202
-				// Load the certificate
203
-				$certificate = new X509();
204
-				$certificate->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
205
-				$loadedCertificate = $certificate->loadX509($app['certificate']);
206
-
207
-				// Verify if the certificate has been revoked
208
-				$crl = new X509();
209
-				$crl->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
210
-				$crl->loadCRL(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crl'));
211
-				if($crl->validateSignature() !== true) {
212
-					throw new \Exception('Could not validate CRL signature');
213
-				}
214
-				$csn = $loadedCertificate['tbsCertificate']['serialNumber']->toString();
215
-				$revoked = $crl->getRevoked($csn);
216
-				if ($revoked !== false) {
217
-					throw new \Exception(
218
-						sprintf(
219
-							'Certificate "%s" has been revoked',
220
-							$csn
221
-						)
222
-					);
223
-				}
224
-
225
-				// Verify if the certificate has been issued by the Nextcloud Code Authority CA
226
-				if($certificate->validateSignature() !== true) {
227
-					throw new \Exception(
228
-						sprintf(
229
-							'App with id %s has a certificate not issued by a trusted Code Signing Authority',
230
-							$appId
231
-						)
232
-					);
233
-				}
234
-
235
-				// Verify if the certificate is issued for the requested app id
236
-				$certInfo = openssl_x509_parse($app['certificate']);
237
-				if(!isset($certInfo['subject']['CN'])) {
238
-					throw new \Exception(
239
-						sprintf(
240
-							'App with id %s has a cert with no CN',
241
-							$appId
242
-						)
243
-					);
244
-				}
245
-				if($certInfo['subject']['CN'] !== $appId) {
246
-					throw new \Exception(
247
-						sprintf(
248
-							'App with id %s has a cert issued to %s',
249
-							$appId,
250
-							$certInfo['subject']['CN']
251
-						)
252
-					);
253
-				}
254
-
255
-				// Download the release
256
-				$tempFile = $this->tempManager->getTemporaryFile('.tar.gz');
257
-				$client = $this->clientService->newClient();
258
-				$client->get($app['releases'][0]['download'], ['save_to' => $tempFile]);
259
-
260
-				// Check if the signature actually matches the downloaded content
261
-				$certificate = openssl_get_publickey($app['certificate']);
262
-				$verified = (bool)openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
263
-				openssl_free_key($certificate);
264
-
265
-				if($verified === true) {
266
-					// Seems to match, let's proceed
267
-					$extractDir = $this->tempManager->getTemporaryFolder();
268
-					$archive = new TAR($tempFile);
269
-
270
-					if($archive) {
271
-						if (!$archive->extract($extractDir)) {
272
-							throw new \Exception(
273
-								sprintf(
274
-									'Could not extract app %s',
275
-									$appId
276
-								)
277
-							);
278
-						}
279
-						$allFiles = scandir($extractDir);
280
-						$folders = array_diff($allFiles, ['.', '..']);
281
-						$folders = array_values($folders);
282
-
283
-						if(count($folders) > 1) {
284
-							throw new \Exception(
285
-								sprintf(
286
-									'Extracted app %s has more than 1 folder',
287
-									$appId
288
-								)
289
-							);
290
-						}
291
-
292
-						// Check if appinfo/info.xml has the same app ID as well
293
-						$loadEntities = libxml_disable_entity_loader(false);
294
-						$xml = simplexml_load_file($extractDir . '/' . $folders[0] . '/appinfo/info.xml');
295
-						libxml_disable_entity_loader($loadEntities);
296
-						if((string)$xml->id !== $appId) {
297
-							throw new \Exception(
298
-								sprintf(
299
-									'App for id %s has a wrong app ID in info.xml: %s',
300
-									$appId,
301
-									(string)$xml->id
302
-								)
303
-							);
304
-						}
305
-
306
-						// Check if the version is lower than before
307
-						$currentVersion = OC_App::getAppVersion($appId);
308
-						$newVersion = (string)$xml->version;
309
-						if(version_compare($currentVersion, $newVersion) === 1) {
310
-							throw new \Exception(
311
-								sprintf(
312
-									'App for id %s has version %s and tried to update to lower version %s',
313
-									$appId,
314
-									$currentVersion,
315
-									$newVersion
316
-								)
317
-							);
318
-						}
319
-
320
-						$baseDir = OC_App::getInstallPath() . '/' . $appId;
321
-						// Remove old app with the ID if existent
322
-						OC_Helper::rmdirr($baseDir);
323
-						// Move to app folder
324
-						if(@mkdir($baseDir)) {
325
-							$extractDir .= '/' . $folders[0];
326
-							OC_Helper::copyr($extractDir, $baseDir);
327
-						}
328
-						OC_Helper::copyr($extractDir, $baseDir);
329
-						OC_Helper::rmdirr($extractDir);
330
-						return;
331
-					} else {
332
-						throw new \Exception(
333
-							sprintf(
334
-								'Could not extract app with ID %s to %s',
335
-								$appId,
336
-								$extractDir
337
-							)
338
-						);
339
-					}
340
-				} else {
341
-					// Signature does not match
342
-					throw new \Exception(
343
-						sprintf(
344
-							'App with id %s has invalid signature',
345
-							$appId
346
-						)
347
-					);
348
-				}
349
-			}
350
-		}
351
-
352
-		throw new \Exception(
353
-			sprintf(
354
-				'Could not download app %s',
355
-				$appId
356
-			)
357
-		);
358
-	}
359
-
360
-	/**
361
-	 * Check if an update for the app is available
362
-	 *
363
-	 * @param string $appId
364
-	 * @return string|false false or the version number of the update
365
-	 */
366
-	public function isUpdateAvailable($appId) {
367
-		if ($this->isInstanceReadyForUpdates === null) {
368
-			$installPath = OC_App::getInstallPath();
369
-			if ($installPath === false || $installPath === null) {
370
-				$this->isInstanceReadyForUpdates = false;
371
-			} else {
372
-				$this->isInstanceReadyForUpdates = true;
373
-			}
374
-		}
375
-
376
-		if ($this->isInstanceReadyForUpdates === false) {
377
-			return false;
378
-		}
379
-
380
-		if ($this->isInstalledFromGit($appId) === true) {
381
-			return false;
382
-		}
383
-
384
-		if ($this->apps === null) {
385
-			$this->apps = $this->appFetcher->get();
386
-		}
387
-
388
-		foreach($this->apps as $app) {
389
-			if($app['id'] === $appId) {
390
-				$currentVersion = OC_App::getAppVersion($appId);
391
-				$newestVersion = $app['releases'][0]['version'];
392
-				if (version_compare($newestVersion, $currentVersion, '>')) {
393
-					return $newestVersion;
394
-				} else {
395
-					return false;
396
-				}
397
-			}
398
-		}
399
-
400
-		return false;
401
-	}
402
-
403
-	/**
404
-	 * Check if app has been installed from git
405
-	 * @param string $name name of the application to remove
406
-	 * @return boolean
407
-	 *
408
-	 * The function will check if the path contains a .git folder
409
-	 */
410
-	private function isInstalledFromGit($appId) {
411
-		$app = \OC_App::findAppInDirectories($appId);
412
-		if($app === false) {
413
-			return false;
414
-		}
415
-		$basedir = $app['path'].'/'.$appId;
416
-		return file_exists($basedir.'/.git/');
417
-	}
418
-
419
-	/**
420
-	 * Check if app is already downloaded
421
-	 * @param string $name name of the application to remove
422
-	 * @return boolean
423
-	 *
424
-	 * The function will check if the app is already downloaded in the apps repository
425
-	 */
426
-	public function isDownloaded($name) {
427
-		foreach(\OC::$APPSROOTS as $dir) {
428
-			$dirToTest  = $dir['path'];
429
-			$dirToTest .= '/';
430
-			$dirToTest .= $name;
431
-			$dirToTest .= '/';
432
-
433
-			if (is_dir($dirToTest)) {
434
-				return true;
435
-			}
436
-		}
437
-
438
-		return false;
439
-	}
440
-
441
-	/**
442
-	 * Removes an app
443
-	 * @param string $appId ID of the application to remove
444
-	 * @return boolean
445
-	 *
446
-	 *
447
-	 * This function works as follows
448
-	 *   -# call uninstall repair steps
449
-	 *   -# removing the files
450
-	 *
451
-	 * The function will not delete preferences, tables and the configuration,
452
-	 * this has to be done by the function oc_app_uninstall().
453
-	 */
454
-	public function removeApp($appId) {
455
-		if($this->isDownloaded( $appId )) {
456
-			if (\OC::$server->getAppManager()->isShipped($appId)) {
457
-				return false;
458
-			}
459
-			$appDir = OC_App::getInstallPath() . '/' . $appId;
460
-			OC_Helper::rmdirr($appDir);
461
-			return true;
462
-		}else{
463
-			\OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', ILogger::ERROR);
464
-
465
-			return false;
466
-		}
467
-
468
-	}
469
-
470
-	/**
471
-	 * Installs the app within the bundle and marks the bundle as installed
472
-	 *
473
-	 * @param Bundle $bundle
474
-	 * @throws \Exception If app could not get installed
475
-	 */
476
-	public function installAppBundle(Bundle $bundle) {
477
-		$appIds = $bundle->getAppIdentifiers();
478
-		foreach($appIds as $appId) {
479
-			if(!$this->isDownloaded($appId)) {
480
-				$this->downloadApp($appId);
481
-			}
482
-			$this->installApp($appId);
483
-			$app = new OC_App();
484
-			$app->enable($appId);
485
-		}
486
-		$bundles = json_decode($this->config->getAppValue('core', 'installed.bundles', json_encode([])), true);
487
-		$bundles[] = $bundle->getIdentifier();
488
-		$this->config->setAppValue('core', 'installed.bundles', json_encode($bundles));
489
-	}
490
-
491
-	/**
492
-	 * Installs shipped apps
493
-	 *
494
-	 * This function installs all apps found in the 'apps' directory that should be enabled by default;
495
-	 * @param bool $softErrors When updating we ignore errors and simply log them, better to have a
496
-	 *                         working ownCloud at the end instead of an aborted update.
497
-	 * @return array Array of error messages (appid => Exception)
498
-	 */
499
-	public static function installShippedApps($softErrors = false) {
500
-		$appManager = \OC::$server->getAppManager();
501
-		$config = \OC::$server->getConfig();
502
-		$errors = [];
503
-		foreach(\OC::$APPSROOTS as $app_dir) {
504
-			if($dir = opendir( $app_dir['path'] )) {
505
-				while( false !== ( $filename = readdir( $dir ))) {
506
-					if( $filename[0] !== '.' and is_dir($app_dir['path']."/$filename") ) {
507
-						if( file_exists( $app_dir['path']."/$filename/appinfo/info.xml" )) {
508
-							if($config->getAppValue($filename, "installed_version", null) === null) {
509
-								$info=OC_App::getAppInfo($filename);
510
-								$enabled = isset($info['default_enable']);
511
-								if (($enabled || in_array($filename, $appManager->getAlwaysEnabledApps()))
512
-									  && $config->getAppValue($filename, 'enabled') !== 'no') {
513
-									if ($softErrors) {
514
-										try {
515
-											Installer::installShippedApp($filename);
516
-										} catch (HintException $e) {
517
-											if ($e->getPrevious() instanceof TableExistsException) {
518
-												$errors[$filename] = $e;
519
-												continue;
520
-											}
521
-											throw $e;
522
-										}
523
-									} else {
524
-										Installer::installShippedApp($filename);
525
-									}
526
-									$config->setAppValue($filename, 'enabled', 'yes');
527
-								}
528
-							}
529
-						}
530
-					}
531
-				}
532
-				closedir( $dir );
533
-			}
534
-		}
535
-
536
-		return $errors;
537
-	}
538
-
539
-	/**
540
-	 * install an app already placed in the app folder
541
-	 * @param string $app id of the app to install
542
-	 * @return integer
543
-	 */
544
-	public static function installShippedApp($app) {
545
-		//install the database
546
-		$appPath = OC_App::getAppPath($app);
547
-		\OC_App::registerAutoloading($app, $appPath);
548
-
549
-		if(is_file("$appPath/appinfo/database.xml")) {
550
-			try {
551
-				OC_DB::createDbFromStructure("$appPath/appinfo/database.xml");
552
-			} catch (TableExistsException $e) {
553
-				throw new HintException(
554
-					'Failed to enable app ' . $app,
555
-					'Please ask for help via one of our <a href="https://nextcloud.com/support/" target="_blank" rel="noreferrer noopener">support channels</a>.',
556
-					0, $e
557
-				);
558
-			}
559
-		} else {
560
-			$ms = new \OC\DB\MigrationService($app, \OC::$server->getDatabaseConnection());
561
-			$ms->migrate();
562
-		}
563
-
564
-		//run appinfo/install.php
565
-		self::includeAppScript("$appPath/appinfo/install.php");
566
-
567
-		$info = OC_App::getAppInfo($app);
568
-		if (is_null($info)) {
569
-			return false;
570
-		}
571
-		\OC_App::setupBackgroundJobs($info['background-jobs']);
572
-
573
-		OC_App::executeRepairSteps($app, $info['repair-steps']['install']);
574
-
575
-		$config = \OC::$server->getConfig();
576
-
577
-		$config->setAppValue($app, 'installed_version', OC_App::getAppVersion($app));
578
-		if (array_key_exists('ocsid', $info)) {
579
-			$config->setAppValue($app, 'ocsid', $info['ocsid']);
580
-		}
581
-
582
-		//set remote/public handlers
583
-		foreach($info['remote'] as $name=>$path) {
584
-			$config->setAppValue('core', 'remote_'.$name, $app.'/'.$path);
585
-		}
586
-		foreach($info['public'] as $name=>$path) {
587
-			$config->setAppValue('core', 'public_'.$name, $app.'/'.$path);
588
-		}
589
-
590
-		OC_App::setAppTypes($info['id']);
591
-
592
-		return $info['id'];
593
-	}
594
-
595
-	/**
596
-	 * @param string $script
597
-	 */
598
-	private static function includeAppScript($script) {
599
-		if ( file_exists($script) ){
600
-			include $script;
601
-		}
602
-	}
55
+    /** @var AppFetcher */
56
+    private $appFetcher;
57
+    /** @var IClientService */
58
+    private $clientService;
59
+    /** @var ITempManager */
60
+    private $tempManager;
61
+    /** @var ILogger */
62
+    private $logger;
63
+    /** @var IConfig */
64
+    private $config;
65
+    /** @var array - for caching the result of app fetcher */
66
+    private $apps = null;
67
+    /** @var bool|null - for caching the result of the ready status */
68
+    private $isInstanceReadyForUpdates = null;
69
+
70
+    /**
71
+     * @param AppFetcher $appFetcher
72
+     * @param IClientService $clientService
73
+     * @param ITempManager $tempManager
74
+     * @param ILogger $logger
75
+     * @param IConfig $config
76
+     */
77
+    public function __construct(AppFetcher $appFetcher,
78
+                                IClientService $clientService,
79
+                                ITempManager $tempManager,
80
+                                ILogger $logger,
81
+                                IConfig $config) {
82
+        $this->appFetcher = $appFetcher;
83
+        $this->clientService = $clientService;
84
+        $this->tempManager = $tempManager;
85
+        $this->logger = $logger;
86
+        $this->config = $config;
87
+    }
88
+
89
+    /**
90
+     * Installs an app that is located in one of the app folders already
91
+     *
92
+     * @param string $appId App to install
93
+     * @throws \Exception
94
+     * @return string app ID
95
+     */
96
+    public function installApp($appId) {
97
+        $app = \OC_App::findAppInDirectories($appId);
98
+        if($app === false) {
99
+            throw new \Exception('App not found in any app directory');
100
+        }
101
+
102
+        $basedir = $app['path'].'/'.$appId;
103
+        $info = OC_App::getAppInfo($basedir.'/appinfo/info.xml', true);
104
+
105
+        $l = \OC::$server->getL10N('core');
106
+
107
+        if(!is_array($info)) {
108
+            throw new \Exception(
109
+                $l->t('App "%s" cannot be installed because appinfo file cannot be read.',
110
+                    [$appId]
111
+                )
112
+            );
113
+        }
114
+
115
+        $version = implode('.', \OCP\Util::getVersion());
116
+        if (!\OC_App::isAppCompatible($version, $info)) {
117
+            throw new \Exception(
118
+                // TODO $l
119
+                $l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
120
+                    [$info['name']]
121
+                )
122
+            );
123
+        }
124
+
125
+        // check for required dependencies
126
+        \OC_App::checkAppDependencies($this->config, $l, $info);
127
+        \OC_App::registerAutoloading($appId, $basedir);
128
+
129
+        //install the database
130
+        if(is_file($basedir.'/appinfo/database.xml')) {
131
+            if (\OC::$server->getConfig()->getAppValue($info['id'], 'installed_version') === null) {
132
+                OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
133
+            } else {
134
+                OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml');
135
+            }
136
+        } else {
137
+            $ms = new \OC\DB\MigrationService($info['id'], \OC::$server->getDatabaseConnection());
138
+            $ms->migrate();
139
+        }
140
+
141
+        \OC_App::setupBackgroundJobs($info['background-jobs']);
142
+
143
+        //run appinfo/install.php
144
+        self::includeAppScript($basedir . '/appinfo/install.php');
145
+
146
+        $appData = OC_App::getAppInfo($appId);
147
+        OC_App::executeRepairSteps($appId, $appData['repair-steps']['install']);
148
+
149
+        //set the installed version
150
+        \OC::$server->getConfig()->setAppValue($info['id'], 'installed_version', OC_App::getAppVersion($info['id'], false));
151
+        \OC::$server->getConfig()->setAppValue($info['id'], 'enabled', 'no');
152
+
153
+        //set remote/public handlers
154
+        foreach($info['remote'] as $name=>$path) {
155
+            \OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path);
156
+        }
157
+        foreach($info['public'] as $name=>$path) {
158
+            \OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path);
159
+        }
160
+
161
+        OC_App::setAppTypes($info['id']);
162
+
163
+        return $info['id'];
164
+    }
165
+
166
+    /**
167
+     * Updates the specified app from the appstore
168
+     *
169
+     * @param string $appId
170
+     * @return bool
171
+     */
172
+    public function updateAppstoreApp($appId) {
173
+        if($this->isUpdateAvailable($appId)) {
174
+            try {
175
+                $this->downloadApp($appId);
176
+            } catch (\Exception $e) {
177
+                $this->logger->logException($e, [
178
+                    'level' => ILogger::ERROR,
179
+                    'app' => 'core',
180
+                ]);
181
+                return false;
182
+            }
183
+            return OC_App::updateApp($appId);
184
+        }
185
+
186
+        return false;
187
+    }
188
+
189
+    /**
190
+     * Downloads an app and puts it into the app directory
191
+     *
192
+     * @param string $appId
193
+     *
194
+     * @throws \Exception If the installation was not successful
195
+     */
196
+    public function downloadApp($appId) {
197
+        $appId = strtolower($appId);
198
+
199
+        $apps = $this->appFetcher->get();
200
+        foreach($apps as $app) {
201
+            if($app['id'] === $appId) {
202
+                // Load the certificate
203
+                $certificate = new X509();
204
+                $certificate->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
205
+                $loadedCertificate = $certificate->loadX509($app['certificate']);
206
+
207
+                // Verify if the certificate has been revoked
208
+                $crl = new X509();
209
+                $crl->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
210
+                $crl->loadCRL(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crl'));
211
+                if($crl->validateSignature() !== true) {
212
+                    throw new \Exception('Could not validate CRL signature');
213
+                }
214
+                $csn = $loadedCertificate['tbsCertificate']['serialNumber']->toString();
215
+                $revoked = $crl->getRevoked($csn);
216
+                if ($revoked !== false) {
217
+                    throw new \Exception(
218
+                        sprintf(
219
+                            'Certificate "%s" has been revoked',
220
+                            $csn
221
+                        )
222
+                    );
223
+                }
224
+
225
+                // Verify if the certificate has been issued by the Nextcloud Code Authority CA
226
+                if($certificate->validateSignature() !== true) {
227
+                    throw new \Exception(
228
+                        sprintf(
229
+                            'App with id %s has a certificate not issued by a trusted Code Signing Authority',
230
+                            $appId
231
+                        )
232
+                    );
233
+                }
234
+
235
+                // Verify if the certificate is issued for the requested app id
236
+                $certInfo = openssl_x509_parse($app['certificate']);
237
+                if(!isset($certInfo['subject']['CN'])) {
238
+                    throw new \Exception(
239
+                        sprintf(
240
+                            'App with id %s has a cert with no CN',
241
+                            $appId
242
+                        )
243
+                    );
244
+                }
245
+                if($certInfo['subject']['CN'] !== $appId) {
246
+                    throw new \Exception(
247
+                        sprintf(
248
+                            'App with id %s has a cert issued to %s',
249
+                            $appId,
250
+                            $certInfo['subject']['CN']
251
+                        )
252
+                    );
253
+                }
254
+
255
+                // Download the release
256
+                $tempFile = $this->tempManager->getTemporaryFile('.tar.gz');
257
+                $client = $this->clientService->newClient();
258
+                $client->get($app['releases'][0]['download'], ['save_to' => $tempFile]);
259
+
260
+                // Check if the signature actually matches the downloaded content
261
+                $certificate = openssl_get_publickey($app['certificate']);
262
+                $verified = (bool)openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
263
+                openssl_free_key($certificate);
264
+
265
+                if($verified === true) {
266
+                    // Seems to match, let's proceed
267
+                    $extractDir = $this->tempManager->getTemporaryFolder();
268
+                    $archive = new TAR($tempFile);
269
+
270
+                    if($archive) {
271
+                        if (!$archive->extract($extractDir)) {
272
+                            throw new \Exception(
273
+                                sprintf(
274
+                                    'Could not extract app %s',
275
+                                    $appId
276
+                                )
277
+                            );
278
+                        }
279
+                        $allFiles = scandir($extractDir);
280
+                        $folders = array_diff($allFiles, ['.', '..']);
281
+                        $folders = array_values($folders);
282
+
283
+                        if(count($folders) > 1) {
284
+                            throw new \Exception(
285
+                                sprintf(
286
+                                    'Extracted app %s has more than 1 folder',
287
+                                    $appId
288
+                                )
289
+                            );
290
+                        }
291
+
292
+                        // Check if appinfo/info.xml has the same app ID as well
293
+                        $loadEntities = libxml_disable_entity_loader(false);
294
+                        $xml = simplexml_load_file($extractDir . '/' . $folders[0] . '/appinfo/info.xml');
295
+                        libxml_disable_entity_loader($loadEntities);
296
+                        if((string)$xml->id !== $appId) {
297
+                            throw new \Exception(
298
+                                sprintf(
299
+                                    'App for id %s has a wrong app ID in info.xml: %s',
300
+                                    $appId,
301
+                                    (string)$xml->id
302
+                                )
303
+                            );
304
+                        }
305
+
306
+                        // Check if the version is lower than before
307
+                        $currentVersion = OC_App::getAppVersion($appId);
308
+                        $newVersion = (string)$xml->version;
309
+                        if(version_compare($currentVersion, $newVersion) === 1) {
310
+                            throw new \Exception(
311
+                                sprintf(
312
+                                    'App for id %s has version %s and tried to update to lower version %s',
313
+                                    $appId,
314
+                                    $currentVersion,
315
+                                    $newVersion
316
+                                )
317
+                            );
318
+                        }
319
+
320
+                        $baseDir = OC_App::getInstallPath() . '/' . $appId;
321
+                        // Remove old app with the ID if existent
322
+                        OC_Helper::rmdirr($baseDir);
323
+                        // Move to app folder
324
+                        if(@mkdir($baseDir)) {
325
+                            $extractDir .= '/' . $folders[0];
326
+                            OC_Helper::copyr($extractDir, $baseDir);
327
+                        }
328
+                        OC_Helper::copyr($extractDir, $baseDir);
329
+                        OC_Helper::rmdirr($extractDir);
330
+                        return;
331
+                    } else {
332
+                        throw new \Exception(
333
+                            sprintf(
334
+                                'Could not extract app with ID %s to %s',
335
+                                $appId,
336
+                                $extractDir
337
+                            )
338
+                        );
339
+                    }
340
+                } else {
341
+                    // Signature does not match
342
+                    throw new \Exception(
343
+                        sprintf(
344
+                            'App with id %s has invalid signature',
345
+                            $appId
346
+                        )
347
+                    );
348
+                }
349
+            }
350
+        }
351
+
352
+        throw new \Exception(
353
+            sprintf(
354
+                'Could not download app %s',
355
+                $appId
356
+            )
357
+        );
358
+    }
359
+
360
+    /**
361
+     * Check if an update for the app is available
362
+     *
363
+     * @param string $appId
364
+     * @return string|false false or the version number of the update
365
+     */
366
+    public function isUpdateAvailable($appId) {
367
+        if ($this->isInstanceReadyForUpdates === null) {
368
+            $installPath = OC_App::getInstallPath();
369
+            if ($installPath === false || $installPath === null) {
370
+                $this->isInstanceReadyForUpdates = false;
371
+            } else {
372
+                $this->isInstanceReadyForUpdates = true;
373
+            }
374
+        }
375
+
376
+        if ($this->isInstanceReadyForUpdates === false) {
377
+            return false;
378
+        }
379
+
380
+        if ($this->isInstalledFromGit($appId) === true) {
381
+            return false;
382
+        }
383
+
384
+        if ($this->apps === null) {
385
+            $this->apps = $this->appFetcher->get();
386
+        }
387
+
388
+        foreach($this->apps as $app) {
389
+            if($app['id'] === $appId) {
390
+                $currentVersion = OC_App::getAppVersion($appId);
391
+                $newestVersion = $app['releases'][0]['version'];
392
+                if (version_compare($newestVersion, $currentVersion, '>')) {
393
+                    return $newestVersion;
394
+                } else {
395
+                    return false;
396
+                }
397
+            }
398
+        }
399
+
400
+        return false;
401
+    }
402
+
403
+    /**
404
+     * Check if app has been installed from git
405
+     * @param string $name name of the application to remove
406
+     * @return boolean
407
+     *
408
+     * The function will check if the path contains a .git folder
409
+     */
410
+    private function isInstalledFromGit($appId) {
411
+        $app = \OC_App::findAppInDirectories($appId);
412
+        if($app === false) {
413
+            return false;
414
+        }
415
+        $basedir = $app['path'].'/'.$appId;
416
+        return file_exists($basedir.'/.git/');
417
+    }
418
+
419
+    /**
420
+     * Check if app is already downloaded
421
+     * @param string $name name of the application to remove
422
+     * @return boolean
423
+     *
424
+     * The function will check if the app is already downloaded in the apps repository
425
+     */
426
+    public function isDownloaded($name) {
427
+        foreach(\OC::$APPSROOTS as $dir) {
428
+            $dirToTest  = $dir['path'];
429
+            $dirToTest .= '/';
430
+            $dirToTest .= $name;
431
+            $dirToTest .= '/';
432
+
433
+            if (is_dir($dirToTest)) {
434
+                return true;
435
+            }
436
+        }
437
+
438
+        return false;
439
+    }
440
+
441
+    /**
442
+     * Removes an app
443
+     * @param string $appId ID of the application to remove
444
+     * @return boolean
445
+     *
446
+     *
447
+     * This function works as follows
448
+     *   -# call uninstall repair steps
449
+     *   -# removing the files
450
+     *
451
+     * The function will not delete preferences, tables and the configuration,
452
+     * this has to be done by the function oc_app_uninstall().
453
+     */
454
+    public function removeApp($appId) {
455
+        if($this->isDownloaded( $appId )) {
456
+            if (\OC::$server->getAppManager()->isShipped($appId)) {
457
+                return false;
458
+            }
459
+            $appDir = OC_App::getInstallPath() . '/' . $appId;
460
+            OC_Helper::rmdirr($appDir);
461
+            return true;
462
+        }else{
463
+            \OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', ILogger::ERROR);
464
+
465
+            return false;
466
+        }
467
+
468
+    }
469
+
470
+    /**
471
+     * Installs the app within the bundle and marks the bundle as installed
472
+     *
473
+     * @param Bundle $bundle
474
+     * @throws \Exception If app could not get installed
475
+     */
476
+    public function installAppBundle(Bundle $bundle) {
477
+        $appIds = $bundle->getAppIdentifiers();
478
+        foreach($appIds as $appId) {
479
+            if(!$this->isDownloaded($appId)) {
480
+                $this->downloadApp($appId);
481
+            }
482
+            $this->installApp($appId);
483
+            $app = new OC_App();
484
+            $app->enable($appId);
485
+        }
486
+        $bundles = json_decode($this->config->getAppValue('core', 'installed.bundles', json_encode([])), true);
487
+        $bundles[] = $bundle->getIdentifier();
488
+        $this->config->setAppValue('core', 'installed.bundles', json_encode($bundles));
489
+    }
490
+
491
+    /**
492
+     * Installs shipped apps
493
+     *
494
+     * This function installs all apps found in the 'apps' directory that should be enabled by default;
495
+     * @param bool $softErrors When updating we ignore errors and simply log them, better to have a
496
+     *                         working ownCloud at the end instead of an aborted update.
497
+     * @return array Array of error messages (appid => Exception)
498
+     */
499
+    public static function installShippedApps($softErrors = false) {
500
+        $appManager = \OC::$server->getAppManager();
501
+        $config = \OC::$server->getConfig();
502
+        $errors = [];
503
+        foreach(\OC::$APPSROOTS as $app_dir) {
504
+            if($dir = opendir( $app_dir['path'] )) {
505
+                while( false !== ( $filename = readdir( $dir ))) {
506
+                    if( $filename[0] !== '.' and is_dir($app_dir['path']."/$filename") ) {
507
+                        if( file_exists( $app_dir['path']."/$filename/appinfo/info.xml" )) {
508
+                            if($config->getAppValue($filename, "installed_version", null) === null) {
509
+                                $info=OC_App::getAppInfo($filename);
510
+                                $enabled = isset($info['default_enable']);
511
+                                if (($enabled || in_array($filename, $appManager->getAlwaysEnabledApps()))
512
+                                      && $config->getAppValue($filename, 'enabled') !== 'no') {
513
+                                    if ($softErrors) {
514
+                                        try {
515
+                                            Installer::installShippedApp($filename);
516
+                                        } catch (HintException $e) {
517
+                                            if ($e->getPrevious() instanceof TableExistsException) {
518
+                                                $errors[$filename] = $e;
519
+                                                continue;
520
+                                            }
521
+                                            throw $e;
522
+                                        }
523
+                                    } else {
524
+                                        Installer::installShippedApp($filename);
525
+                                    }
526
+                                    $config->setAppValue($filename, 'enabled', 'yes');
527
+                                }
528
+                            }
529
+                        }
530
+                    }
531
+                }
532
+                closedir( $dir );
533
+            }
534
+        }
535
+
536
+        return $errors;
537
+    }
538
+
539
+    /**
540
+     * install an app already placed in the app folder
541
+     * @param string $app id of the app to install
542
+     * @return integer
543
+     */
544
+    public static function installShippedApp($app) {
545
+        //install the database
546
+        $appPath = OC_App::getAppPath($app);
547
+        \OC_App::registerAutoloading($app, $appPath);
548
+
549
+        if(is_file("$appPath/appinfo/database.xml")) {
550
+            try {
551
+                OC_DB::createDbFromStructure("$appPath/appinfo/database.xml");
552
+            } catch (TableExistsException $e) {
553
+                throw new HintException(
554
+                    'Failed to enable app ' . $app,
555
+                    'Please ask for help via one of our <a href="https://nextcloud.com/support/" target="_blank" rel="noreferrer noopener">support channels</a>.',
556
+                    0, $e
557
+                );
558
+            }
559
+        } else {
560
+            $ms = new \OC\DB\MigrationService($app, \OC::$server->getDatabaseConnection());
561
+            $ms->migrate();
562
+        }
563
+
564
+        //run appinfo/install.php
565
+        self::includeAppScript("$appPath/appinfo/install.php");
566
+
567
+        $info = OC_App::getAppInfo($app);
568
+        if (is_null($info)) {
569
+            return false;
570
+        }
571
+        \OC_App::setupBackgroundJobs($info['background-jobs']);
572
+
573
+        OC_App::executeRepairSteps($app, $info['repair-steps']['install']);
574
+
575
+        $config = \OC::$server->getConfig();
576
+
577
+        $config->setAppValue($app, 'installed_version', OC_App::getAppVersion($app));
578
+        if (array_key_exists('ocsid', $info)) {
579
+            $config->setAppValue($app, 'ocsid', $info['ocsid']);
580
+        }
581
+
582
+        //set remote/public handlers
583
+        foreach($info['remote'] as $name=>$path) {
584
+            $config->setAppValue('core', 'remote_'.$name, $app.'/'.$path);
585
+        }
586
+        foreach($info['public'] as $name=>$path) {
587
+            $config->setAppValue('core', 'public_'.$name, $app.'/'.$path);
588
+        }
589
+
590
+        OC_App::setAppTypes($info['id']);
591
+
592
+        return $info['id'];
593
+    }
594
+
595
+    /**
596
+     * @param string $script
597
+     */
598
+    private static function includeAppScript($script) {
599
+        if ( file_exists($script) ){
600
+            include $script;
601
+        }
602
+    }
603 603
 }
Please login to merge, or discard this patch.
Spacing   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
 	 */
96 96
 	public function installApp($appId) {
97 97
 		$app = \OC_App::findAppInDirectories($appId);
98
-		if($app === false) {
98
+		if ($app === false) {
99 99
 			throw new \Exception('App not found in any app directory');
100 100
 		}
101 101
 
@@ -104,7 +104,7 @@  discard block
 block discarded – undo
104 104
 
105 105
 		$l = \OC::$server->getL10N('core');
106 106
 
107
-		if(!is_array($info)) {
107
+		if (!is_array($info)) {
108 108
 			throw new \Exception(
109 109
 				$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
110 110
 					[$appId]
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
 		\OC_App::registerAutoloading($appId, $basedir);
128 128
 
129 129
 		//install the database
130
-		if(is_file($basedir.'/appinfo/database.xml')) {
130
+		if (is_file($basedir.'/appinfo/database.xml')) {
131 131
 			if (\OC::$server->getConfig()->getAppValue($info['id'], 'installed_version') === null) {
132 132
 				OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
133 133
 			} else {
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
 		\OC_App::setupBackgroundJobs($info['background-jobs']);
142 142
 
143 143
 		//run appinfo/install.php
144
-		self::includeAppScript($basedir . '/appinfo/install.php');
144
+		self::includeAppScript($basedir.'/appinfo/install.php');
145 145
 
146 146
 		$appData = OC_App::getAppInfo($appId);
147 147
 		OC_App::executeRepairSteps($appId, $appData['repair-steps']['install']);
@@ -151,10 +151,10 @@  discard block
 block discarded – undo
151 151
 		\OC::$server->getConfig()->setAppValue($info['id'], 'enabled', 'no');
152 152
 
153 153
 		//set remote/public handlers
154
-		foreach($info['remote'] as $name=>$path) {
154
+		foreach ($info['remote'] as $name=>$path) {
155 155
 			\OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path);
156 156
 		}
157
-		foreach($info['public'] as $name=>$path) {
157
+		foreach ($info['public'] as $name=>$path) {
158 158
 			\OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path);
159 159
 		}
160 160
 
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
 	 * @return bool
171 171
 	 */
172 172
 	public function updateAppstoreApp($appId) {
173
-		if($this->isUpdateAvailable($appId)) {
173
+		if ($this->isUpdateAvailable($appId)) {
174 174
 			try {
175 175
 				$this->downloadApp($appId);
176 176
 			} catch (\Exception $e) {
@@ -197,18 +197,18 @@  discard block
 block discarded – undo
197 197
 		$appId = strtolower($appId);
198 198
 
199 199
 		$apps = $this->appFetcher->get();
200
-		foreach($apps as $app) {
201
-			if($app['id'] === $appId) {
200
+		foreach ($apps as $app) {
201
+			if ($app['id'] === $appId) {
202 202
 				// Load the certificate
203 203
 				$certificate = new X509();
204
-				$certificate->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
204
+				$certificate->loadCA(file_get_contents(__DIR__.'/../../resources/codesigning/root.crt'));
205 205
 				$loadedCertificate = $certificate->loadX509($app['certificate']);
206 206
 
207 207
 				// Verify if the certificate has been revoked
208 208
 				$crl = new X509();
209
-				$crl->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
210
-				$crl->loadCRL(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crl'));
211
-				if($crl->validateSignature() !== true) {
209
+				$crl->loadCA(file_get_contents(__DIR__.'/../../resources/codesigning/root.crt'));
210
+				$crl->loadCRL(file_get_contents(__DIR__.'/../../resources/codesigning/root.crl'));
211
+				if ($crl->validateSignature() !== true) {
212 212
 					throw new \Exception('Could not validate CRL signature');
213 213
 				}
214 214
 				$csn = $loadedCertificate['tbsCertificate']['serialNumber']->toString();
@@ -223,7 +223,7 @@  discard block
 block discarded – undo
223 223
 				}
224 224
 
225 225
 				// Verify if the certificate has been issued by the Nextcloud Code Authority CA
226
-				if($certificate->validateSignature() !== true) {
226
+				if ($certificate->validateSignature() !== true) {
227 227
 					throw new \Exception(
228 228
 						sprintf(
229 229
 							'App with id %s has a certificate not issued by a trusted Code Signing Authority',
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
 
235 235
 				// Verify if the certificate is issued for the requested app id
236 236
 				$certInfo = openssl_x509_parse($app['certificate']);
237
-				if(!isset($certInfo['subject']['CN'])) {
237
+				if (!isset($certInfo['subject']['CN'])) {
238 238
 					throw new \Exception(
239 239
 						sprintf(
240 240
 							'App with id %s has a cert with no CN',
@@ -242,7 +242,7 @@  discard block
 block discarded – undo
242 242
 						)
243 243
 					);
244 244
 				}
245
-				if($certInfo['subject']['CN'] !== $appId) {
245
+				if ($certInfo['subject']['CN'] !== $appId) {
246 246
 					throw new \Exception(
247 247
 						sprintf(
248 248
 							'App with id %s has a cert issued to %s',
@@ -259,15 +259,15 @@  discard block
 block discarded – undo
259 259
 
260 260
 				// Check if the signature actually matches the downloaded content
261 261
 				$certificate = openssl_get_publickey($app['certificate']);
262
-				$verified = (bool)openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
262
+				$verified = (bool) openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
263 263
 				openssl_free_key($certificate);
264 264
 
265
-				if($verified === true) {
265
+				if ($verified === true) {
266 266
 					// Seems to match, let's proceed
267 267
 					$extractDir = $this->tempManager->getTemporaryFolder();
268 268
 					$archive = new TAR($tempFile);
269 269
 
270
-					if($archive) {
270
+					if ($archive) {
271 271
 						if (!$archive->extract($extractDir)) {
272 272
 							throw new \Exception(
273 273
 								sprintf(
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
 						$folders = array_diff($allFiles, ['.', '..']);
281 281
 						$folders = array_values($folders);
282 282
 
283
-						if(count($folders) > 1) {
283
+						if (count($folders) > 1) {
284 284
 							throw new \Exception(
285 285
 								sprintf(
286 286
 									'Extracted app %s has more than 1 folder',
@@ -291,22 +291,22 @@  discard block
 block discarded – undo
291 291
 
292 292
 						// Check if appinfo/info.xml has the same app ID as well
293 293
 						$loadEntities = libxml_disable_entity_loader(false);
294
-						$xml = simplexml_load_file($extractDir . '/' . $folders[0] . '/appinfo/info.xml');
294
+						$xml = simplexml_load_file($extractDir.'/'.$folders[0].'/appinfo/info.xml');
295 295
 						libxml_disable_entity_loader($loadEntities);
296
-						if((string)$xml->id !== $appId) {
296
+						if ((string) $xml->id !== $appId) {
297 297
 							throw new \Exception(
298 298
 								sprintf(
299 299
 									'App for id %s has a wrong app ID in info.xml: %s',
300 300
 									$appId,
301
-									(string)$xml->id
301
+									(string) $xml->id
302 302
 								)
303 303
 							);
304 304
 						}
305 305
 
306 306
 						// Check if the version is lower than before
307 307
 						$currentVersion = OC_App::getAppVersion($appId);
308
-						$newVersion = (string)$xml->version;
309
-						if(version_compare($currentVersion, $newVersion) === 1) {
308
+						$newVersion = (string) $xml->version;
309
+						if (version_compare($currentVersion, $newVersion) === 1) {
310 310
 							throw new \Exception(
311 311
 								sprintf(
312 312
 									'App for id %s has version %s and tried to update to lower version %s',
@@ -317,12 +317,12 @@  discard block
 block discarded – undo
317 317
 							);
318 318
 						}
319 319
 
320
-						$baseDir = OC_App::getInstallPath() . '/' . $appId;
320
+						$baseDir = OC_App::getInstallPath().'/'.$appId;
321 321
 						// Remove old app with the ID if existent
322 322
 						OC_Helper::rmdirr($baseDir);
323 323
 						// Move to app folder
324
-						if(@mkdir($baseDir)) {
325
-							$extractDir .= '/' . $folders[0];
324
+						if (@mkdir($baseDir)) {
325
+							$extractDir .= '/'.$folders[0];
326 326
 							OC_Helper::copyr($extractDir, $baseDir);
327 327
 						}
328 328
 						OC_Helper::copyr($extractDir, $baseDir);
@@ -385,8 +385,8 @@  discard block
 block discarded – undo
385 385
 			$this->apps = $this->appFetcher->get();
386 386
 		}
387 387
 
388
-		foreach($this->apps as $app) {
389
-			if($app['id'] === $appId) {
388
+		foreach ($this->apps as $app) {
389
+			if ($app['id'] === $appId) {
390 390
 				$currentVersion = OC_App::getAppVersion($appId);
391 391
 				$newestVersion = $app['releases'][0]['version'];
392 392
 				if (version_compare($newestVersion, $currentVersion, '>')) {
@@ -409,7 +409,7 @@  discard block
 block discarded – undo
409 409
 	 */
410 410
 	private function isInstalledFromGit($appId) {
411 411
 		$app = \OC_App::findAppInDirectories($appId);
412
-		if($app === false) {
412
+		if ($app === false) {
413 413
 			return false;
414 414
 		}
415 415
 		$basedir = $app['path'].'/'.$appId;
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
 	 * The function will check if the app is already downloaded in the apps repository
425 425
 	 */
426 426
 	public function isDownloaded($name) {
427
-		foreach(\OC::$APPSROOTS as $dir) {
427
+		foreach (\OC::$APPSROOTS as $dir) {
428 428
 			$dirToTest  = $dir['path'];
429 429
 			$dirToTest .= '/';
430 430
 			$dirToTest .= $name;
@@ -452,14 +452,14 @@  discard block
 block discarded – undo
452 452
 	 * this has to be done by the function oc_app_uninstall().
453 453
 	 */
454 454
 	public function removeApp($appId) {
455
-		if($this->isDownloaded( $appId )) {
455
+		if ($this->isDownloaded($appId)) {
456 456
 			if (\OC::$server->getAppManager()->isShipped($appId)) {
457 457
 				return false;
458 458
 			}
459
-			$appDir = OC_App::getInstallPath() . '/' . $appId;
459
+			$appDir = OC_App::getInstallPath().'/'.$appId;
460 460
 			OC_Helper::rmdirr($appDir);
461 461
 			return true;
462
-		}else{
462
+		} else {
463 463
 			\OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', ILogger::ERROR);
464 464
 
465 465
 			return false;
@@ -475,8 +475,8 @@  discard block
 block discarded – undo
475 475
 	 */
476 476
 	public function installAppBundle(Bundle $bundle) {
477 477
 		$appIds = $bundle->getAppIdentifiers();
478
-		foreach($appIds as $appId) {
479
-			if(!$this->isDownloaded($appId)) {
478
+		foreach ($appIds as $appId) {
479
+			if (!$this->isDownloaded($appId)) {
480 480
 				$this->downloadApp($appId);
481 481
 			}
482 482
 			$this->installApp($appId);
@@ -500,13 +500,13 @@  discard block
 block discarded – undo
500 500
 		$appManager = \OC::$server->getAppManager();
501 501
 		$config = \OC::$server->getConfig();
502 502
 		$errors = [];
503
-		foreach(\OC::$APPSROOTS as $app_dir) {
504
-			if($dir = opendir( $app_dir['path'] )) {
505
-				while( false !== ( $filename = readdir( $dir ))) {
506
-					if( $filename[0] !== '.' and is_dir($app_dir['path']."/$filename") ) {
507
-						if( file_exists( $app_dir['path']."/$filename/appinfo/info.xml" )) {
508
-							if($config->getAppValue($filename, "installed_version", null) === null) {
509
-								$info=OC_App::getAppInfo($filename);
503
+		foreach (\OC::$APPSROOTS as $app_dir) {
504
+			if ($dir = opendir($app_dir['path'])) {
505
+				while (false !== ($filename = readdir($dir))) {
506
+					if ($filename[0] !== '.' and is_dir($app_dir['path']."/$filename")) {
507
+						if (file_exists($app_dir['path']."/$filename/appinfo/info.xml")) {
508
+							if ($config->getAppValue($filename, "installed_version", null) === null) {
509
+								$info = OC_App::getAppInfo($filename);
510 510
 								$enabled = isset($info['default_enable']);
511 511
 								if (($enabled || in_array($filename, $appManager->getAlwaysEnabledApps()))
512 512
 									  && $config->getAppValue($filename, 'enabled') !== 'no') {
@@ -529,7 +529,7 @@  discard block
 block discarded – undo
529 529
 						}
530 530
 					}
531 531
 				}
532
-				closedir( $dir );
532
+				closedir($dir);
533 533
 			}
534 534
 		}
535 535
 
@@ -546,12 +546,12 @@  discard block
 block discarded – undo
546 546
 		$appPath = OC_App::getAppPath($app);
547 547
 		\OC_App::registerAutoloading($app, $appPath);
548 548
 
549
-		if(is_file("$appPath/appinfo/database.xml")) {
549
+		if (is_file("$appPath/appinfo/database.xml")) {
550 550
 			try {
551 551
 				OC_DB::createDbFromStructure("$appPath/appinfo/database.xml");
552 552
 			} catch (TableExistsException $e) {
553 553
 				throw new HintException(
554
-					'Failed to enable app ' . $app,
554
+					'Failed to enable app '.$app,
555 555
 					'Please ask for help via one of our <a href="https://nextcloud.com/support/" target="_blank" rel="noreferrer noopener">support channels</a>.',
556 556
 					0, $e
557 557
 				);
@@ -580,10 +580,10 @@  discard block
 block discarded – undo
580 580
 		}
581 581
 
582 582
 		//set remote/public handlers
583
-		foreach($info['remote'] as $name=>$path) {
583
+		foreach ($info['remote'] as $name=>$path) {
584 584
 			$config->setAppValue('core', 'remote_'.$name, $app.'/'.$path);
585 585
 		}
586
-		foreach($info['public'] as $name=>$path) {
586
+		foreach ($info['public'] as $name=>$path) {
587 587
 			$config->setAppValue('core', 'public_'.$name, $app.'/'.$path);
588 588
 		}
589 589
 
@@ -596,7 +596,7 @@  discard block
 block discarded – undo
596 596
 	 * @param string $script
597 597
 	 */
598 598
 	private static function includeAppScript($script) {
599
-		if ( file_exists($script) ){
599
+		if (file_exists($script)) {
600 600
 			include $script;
601 601
 		}
602 602
 	}
Please login to merge, or discard this patch.
Braces   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -459,7 +459,7 @@
 block discarded – undo
459 459
 			$appDir = OC_App::getInstallPath() . '/' . $appId;
460 460
 			OC_Helper::rmdirr($appDir);
461 461
 			return true;
462
-		}else{
462
+		} else{
463 463
 			\OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', ILogger::ERROR);
464 464
 
465 465
 			return false;
Please login to merge, or discard this patch.
lib/public/Util.php 2 patches
Indentation   +499 added lines, -499 removed lines patch added patch discarded remove patch
@@ -57,505 +57,505 @@
 block discarded – undo
57 57
  * @since 4.0.0
58 58
  */
59 59
 class Util {
60
-	/**
61
-	 * @deprecated 14.0.0 use \OCP\ILogger::DEBUG
62
-	 */
63
-	const DEBUG=0;
64
-	/**
65
-	 * @deprecated 14.0.0 use \OCP\ILogger::INFO
66
-	 */
67
-	const INFO=1;
68
-	/**
69
-	 * @deprecated 14.0.0 use \OCP\ILogger::WARN
70
-	 */
71
-	const WARN=2;
72
-	/**
73
-	 * @deprecated 14.0.0 use \OCP\ILogger::ERROR
74
-	 */
75
-	const ERROR=3;
76
-	/**
77
-	 * @deprecated 14.0.0 use \OCP\ILogger::FATAL
78
-	 */
79
-	const FATAL=4;
80
-
81
-	/** \OCP\Share\IManager */
82
-	private static $shareManager;
83
-
84
-	/**
85
-	 * get the current installed version of ownCloud
86
-	 * @return array
87
-	 * @since 4.0.0
88
-	 */
89
-	public static function getVersion() {
90
-		return \OC_Util::getVersion();
91
-	}
60
+    /**
61
+     * @deprecated 14.0.0 use \OCP\ILogger::DEBUG
62
+     */
63
+    const DEBUG=0;
64
+    /**
65
+     * @deprecated 14.0.0 use \OCP\ILogger::INFO
66
+     */
67
+    const INFO=1;
68
+    /**
69
+     * @deprecated 14.0.0 use \OCP\ILogger::WARN
70
+     */
71
+    const WARN=2;
72
+    /**
73
+     * @deprecated 14.0.0 use \OCP\ILogger::ERROR
74
+     */
75
+    const ERROR=3;
76
+    /**
77
+     * @deprecated 14.0.0 use \OCP\ILogger::FATAL
78
+     */
79
+    const FATAL=4;
80
+
81
+    /** \OCP\Share\IManager */
82
+    private static $shareManager;
83
+
84
+    /**
85
+     * get the current installed version of ownCloud
86
+     * @return array
87
+     * @since 4.0.0
88
+     */
89
+    public static function getVersion() {
90
+        return \OC_Util::getVersion();
91
+    }
92 92
 	
93
-	/**
94
-	 * Set current update channel
95
-	 * @param string $channel
96
-	 * @since 8.1.0
97
-	 */
98
-	public static function setChannel($channel) {
99
-		\OC::$server->getConfig()->setSystemValue('updater.release.channel', $channel);
100
-	}
93
+    /**
94
+     * Set current update channel
95
+     * @param string $channel
96
+     * @since 8.1.0
97
+     */
98
+    public static function setChannel($channel) {
99
+        \OC::$server->getConfig()->setSystemValue('updater.release.channel', $channel);
100
+    }
101 101
 	
102
-	/**
103
-	 * Get current update channel
104
-	 * @return string
105
-	 * @since 8.1.0
106
-	 */
107
-	public static function getChannel() {
108
-		return \OC_Util::getChannel();
109
-	}
110
-
111
-	/**
112
-	 * write a message in the log
113
-	 * @param string $app
114
-	 * @param string $message
115
-	 * @param int $level
116
-	 * @since 4.0.0
117
-	 * @deprecated 13.0.0 use log of \OCP\ILogger
118
-	 */
119
-	public static function writeLog( $app, $message, $level ) {
120
-		$context = ['app' => $app];
121
-		\OC::$server->getLogger()->log($level, $message, $context);
122
-	}
123
-
124
-	/**
125
-	 * write exception into the log
126
-	 * @param string $app app name
127
-	 * @param \Exception $ex exception to log
128
-	 * @param int $level log level, defaults to \OCP\Util::FATAL
129
-	 * @since ....0.0 - parameter $level was added in 7.0.0
130
-	 * @deprecated 8.2.0 use logException of \OCP\ILogger
131
-	 */
132
-	public static function logException( $app, \Exception $ex, $level = ILogger::FATAL) {
133
-		\OC::$server->getLogger()->logException($ex, ['app' => $app]);
134
-	}
135
-
136
-	/**
137
-	 * check if sharing is disabled for the current user
138
-	 *
139
-	 * @return boolean
140
-	 * @since 7.0.0
141
-	 * @deprecated 9.1.0 Use \OC::$server->getShareManager()->sharingDisabledForUser
142
-	 */
143
-	public static function isSharingDisabledForUser() {
144
-		if (self::$shareManager === null) {
145
-			self::$shareManager = \OC::$server->getShareManager();
146
-		}
147
-
148
-		$user = \OC::$server->getUserSession()->getUser();
149
-		if ($user !== null) {
150
-			$user = $user->getUID();
151
-		}
152
-
153
-		return self::$shareManager->sharingDisabledForUser($user);
154
-	}
155
-
156
-	/**
157
-	 * get l10n object
158
-	 * @param string $application
159
-	 * @param string|null $language
160
-	 * @return \OCP\IL10N
161
-	 * @since 6.0.0 - parameter $language was added in 8.0.0
162
-	 */
163
-	public static function getL10N($application, $language = null) {
164
-		return \OC::$server->getL10N($application, $language);
165
-	}
166
-
167
-	/**
168
-	 * add a css file
169
-	 * @param string $application
170
-	 * @param string $file
171
-	 * @since 4.0.0
172
-	 */
173
-	public static function addStyle( $application, $file = null ) {
174
-		\OC_Util::addStyle( $application, $file );
175
-	}
176
-
177
-	/**
178
-	 * add a javascript file
179
-	 * @param string $application
180
-	 * @param string $file
181
-	 * @since 4.0.0
182
-	 */
183
-	public static function addScript( $application, $file = null ) {
184
-		\OC_Util::addScript( $application, $file );
185
-	}
186
-
187
-	/**
188
-	 * Add a translation JS file
189
-	 * @param string $application application id
190
-	 * @param string $languageCode language code, defaults to the current locale
191
-	 * @since 8.0.0
192
-	 */
193
-	public static function addTranslations($application, $languageCode = null) {
194
-		\OC_Util::addTranslations($application, $languageCode);
195
-	}
196
-
197
-	/**
198
-	 * Add a custom element to the header
199
-	 * If $text is null then the element will be written as empty element.
200
-	 * So use "" to get a closing tag.
201
-	 * @param string $tag tag name of the element
202
-	 * @param array $attributes array of attributes for the element
203
-	 * @param string $text the text content for the element
204
-	 * @since 4.0.0
205
-	 */
206
-	public static function addHeader($tag, $attributes, $text=null) {
207
-		\OC_Util::addHeader($tag, $attributes, $text);
208
-	}
209
-
210
-	/**
211
-	 * Creates an absolute url to the given app and file.
212
-	 * @param string $app app
213
-	 * @param string $file file
214
-	 * @param array $args array with param=>value, will be appended to the returned url
215
-	 * 	The value of $args will be urlencoded
216
-	 * @return string the url
217
-	 * @since 4.0.0 - parameter $args was added in 4.5.0
218
-	 */
219
-	public static function linkToAbsolute( $app, $file, $args = array() ) {
220
-		$urlGenerator = \OC::$server->getURLGenerator();
221
-		return $urlGenerator->getAbsoluteURL(
222
-			$urlGenerator->linkTo($app, $file, $args)
223
-		);
224
-	}
225
-
226
-	/**
227
-	 * Creates an absolute url for remote use.
228
-	 * @param string $service id
229
-	 * @return string the url
230
-	 * @since 4.0.0
231
-	 */
232
-	public static function linkToRemote( $service ) {
233
-		$urlGenerator = \OC::$server->getURLGenerator();
234
-		$remoteBase = $urlGenerator->linkTo('', 'remote.php') . '/' . $service;
235
-		return $urlGenerator->getAbsoluteURL(
236
-			$remoteBase . (($service[strlen($service) - 1] != '/') ? '/' : '')
237
-		);
238
-	}
239
-
240
-	/**
241
-	 * Creates an absolute url for public use
242
-	 * @param string $service id
243
-	 * @return string the url
244
-	 * @since 4.5.0
245
-	 */
246
-	public static function linkToPublic($service) {
247
-		return \OC_Helper::linkToPublic($service);
248
-	}
249
-
250
-	/**
251
-	 * Returns the server host name without an eventual port number
252
-	 * @return string the server hostname
253
-	 * @since 5.0.0
254
-	 */
255
-	public static function getServerHostName() {
256
-		$host_name = \OC::$server->getRequest()->getServerHost();
257
-		// strip away port number (if existing)
258
-		$colon_pos = strpos($host_name, ':');
259
-		if ($colon_pos != FALSE) {
260
-			$host_name = substr($host_name, 0, $colon_pos);
261
-		}
262
-		return $host_name;
263
-	}
264
-
265
-	/**
266
-	 * Returns the default email address
267
-	 * @param string $user_part the user part of the address
268
-	 * @return string the default email address
269
-	 *
270
-	 * Assembles a default email address (using the server hostname
271
-	 * and the given user part, and returns it
272
-	 * Example: when given lostpassword-noreply as $user_part param,
273
-	 *     and is currently accessed via http(s)://example.com/,
274
-	 *     it would return '[email protected]'
275
-	 *
276
-	 * If the configuration value 'mail_from_address' is set in
277
-	 * config.php, this value will override the $user_part that
278
-	 * is passed to this function
279
-	 * @since 5.0.0
280
-	 */
281
-	public static function getDefaultEmailAddress($user_part) {
282
-		$config = \OC::$server->getConfig();
283
-		$user_part = $config->getSystemValue('mail_from_address', $user_part);
284
-		$host_name = self::getServerHostName();
285
-		$host_name = $config->getSystemValue('mail_domain', $host_name);
286
-		$defaultEmailAddress = $user_part.'@'.$host_name;
287
-
288
-		$mailer = \OC::$server->getMailer();
289
-		if ($mailer->validateMailAddress($defaultEmailAddress)) {
290
-			return $defaultEmailAddress;
291
-		}
292
-
293
-		// in case we cannot build a valid email address from the hostname let's fallback to 'localhost.localdomain'
294
-		return $user_part.'@localhost.localdomain';
295
-	}
296
-
297
-	/**
298
-	 * Make a human file size (2048 to 2 kB)
299
-	 * @param int $bytes file size in bytes
300
-	 * @return string a human readable file size
301
-	 * @since 4.0.0
302
-	 */
303
-	public static function humanFileSize($bytes) {
304
-		return \OC_Helper::humanFileSize($bytes);
305
-	}
306
-
307
-	/**
308
-	 * Make a computer file size (2 kB to 2048)
309
-	 * @param string $str file size in a fancy format
310
-	 * @return float a file size in bytes
311
-	 *
312
-	 * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
313
-	 * @since 4.0.0
314
-	 */
315
-	public static function computerFileSize($str) {
316
-		return \OC_Helper::computerFileSize($str);
317
-	}
318
-
319
-	/**
320
-	 * connects a function to a hook
321
-	 *
322
-	 * @param string $signalClass class name of emitter
323
-	 * @param string $signalName name of signal
324
-	 * @param string|object $slotClass class name of slot
325
-	 * @param string $slotName name of slot
326
-	 * @return bool
327
-	 *
328
-	 * This function makes it very easy to connect to use hooks.
329
-	 *
330
-	 * TODO: write example
331
-	 * @since 4.0.0
332
-	 */
333
-	static public function connectHook($signalClass, $signalName, $slotClass, $slotName) {
334
-		return \OC_Hook::connect($signalClass, $signalName, $slotClass, $slotName);
335
-	}
336
-
337
-	/**
338
-	 * Emits a signal. To get data from the slot use references!
339
-	 * @param string $signalclass class name of emitter
340
-	 * @param string $signalname name of signal
341
-	 * @param array $params default: array() array with additional data
342
-	 * @return bool true if slots exists or false if not
343
-	 *
344
-	 * TODO: write example
345
-	 * @since 4.0.0
346
-	 */
347
-	static public function emitHook($signalclass, $signalname, $params = array()) {
348
-		return \OC_Hook::emit($signalclass, $signalname, $params);
349
-	}
350
-
351
-	/**
352
-	 * Cached encrypted CSRF token. Some static unit-tests of ownCloud compare
353
-	 * multiple OC_Template elements which invoke `callRegister`. If the value
354
-	 * would not be cached these unit-tests would fail.
355
-	 * @var string
356
-	 */
357
-	private static $token = '';
358
-
359
-	/**
360
-	 * Register an get/post call. This is important to prevent CSRF attacks
361
-	 * @since 4.5.0
362
-	 */
363
-	public static function callRegister() {
364
-		if(self::$token === '') {
365
-			self::$token = \OC::$server->getCsrfTokenManager()->getToken()->getEncryptedValue();
366
-		}
367
-		return self::$token;
368
-	}
369
-
370
-	/**
371
-	 * Check an ajax get/post call if the request token is valid. exit if not.
372
-	 * @since 4.5.0
373
-	 * @deprecated 9.0.0 Use annotations based on the app framework.
374
-	 */
375
-	public static function callCheck() {
376
-		if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
377
-			header('Location: '.\OC::$WEBROOT);
378
-			exit();
379
-		}
380
-
381
-		if (!\OC::$server->getRequest()->passesCSRFCheck()) {
382
-			exit();
383
-		}
384
-	}
385
-
386
-	/**
387
-	 * Used to sanitize HTML
388
-	 *
389
-	 * This function is used to sanitize HTML and should be applied on any
390
-	 * string or array of strings before displaying it on a web page.
391
-	 *
392
-	 * @param string|array $value
393
-	 * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter.
394
-	 * @since 4.5.0
395
-	 */
396
-	public static function sanitizeHTML($value) {
397
-		return \OC_Util::sanitizeHTML($value);
398
-	}
399
-
400
-	/**
401
-	 * Public function to encode url parameters
402
-	 *
403
-	 * This function is used to encode path to file before output.
404
-	 * Encoding is done according to RFC 3986 with one exception:
405
-	 * Character '/' is preserved as is.
406
-	 *
407
-	 * @param string $component part of URI to encode
408
-	 * @return string
409
-	 * @since 6.0.0
410
-	 */
411
-	public static function encodePath($component) {
412
-		return \OC_Util::encodePath($component);
413
-	}
414
-
415
-	/**
416
-	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
417
-	 *
418
-	 * @param array $input The array to work on
419
-	 * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
420
-	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
421
-	 * @return array
422
-	 * @since 4.5.0
423
-	 */
424
-	public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
425
-		return \OC_Helper::mb_array_change_key_case($input, $case, $encoding);
426
-	}
427
-
428
-	/**
429
-	 * replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement.
430
-	 *
431
-	 * @param string $string The input string. Opposite to the PHP build-in function does not accept an array.
432
-	 * @param string $replacement The replacement string.
433
-	 * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string.
434
-	 * @param int $length Length of the part to be replaced
435
-	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
436
-	 * @return string
437
-	 * @since 4.5.0
438
-	 * @deprecated 8.2.0 Use substr_replace() instead.
439
-	 */
440
-	public static function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = 'UTF-8') {
441
-		return substr_replace($string, $replacement, $start, $length);
442
-	}
443
-
444
-	/**
445
-	 * Replace all occurrences of the search string with the replacement string
446
-	 *
447
-	 * @param string $search The value being searched for, otherwise known as the needle. String.
448
-	 * @param string $replace The replacement string.
449
-	 * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
450
-	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
451
-	 * @param int $count If passed, this will be set to the number of replacements performed.
452
-	 * @return string
453
-	 * @since 4.5.0
454
-	 * @deprecated 8.2.0 Use str_replace() instead.
455
-	 */
456
-	public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
457
-		return str_replace($search, $replace, $subject, $count);
458
-	}
459
-
460
-	/**
461
-	 * performs a search in a nested array
462
-	 *
463
-	 * @param array $haystack the array to be searched
464
-	 * @param string $needle the search string
465
-	 * @param mixed $index optional, only search this key name
466
-	 * @return mixed the key of the matching field, otherwise false
467
-	 * @since 4.5.0
468
-	 */
469
-	public static function recursiveArraySearch($haystack, $needle, $index = null) {
470
-		return \OC_Helper::recursiveArraySearch($haystack, $needle, $index);
471
-	}
472
-
473
-	/**
474
-	 * calculates the maximum upload size respecting system settings, free space and user quota
475
-	 *
476
-	 * @param string $dir the current folder where the user currently operates
477
-	 * @param int $free the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
478
-	 * @return int number of bytes representing
479
-	 * @since 5.0.0
480
-	 */
481
-	public static function maxUploadFilesize($dir, $free = null) {
482
-		return \OC_Helper::maxUploadFilesize($dir, $free);
483
-	}
484
-
485
-	/**
486
-	 * Calculate free space left within user quota
487
-	 * @param string $dir the current folder where the user currently operates
488
-	 * @return int number of bytes representing
489
-	 * @since 7.0.0
490
-	 */
491
-	public static function freeSpace($dir) {
492
-		return \OC_Helper::freeSpace($dir);
493
-	}
494
-
495
-	/**
496
-	 * Calculate PHP upload limit
497
-	 *
498
-	 * @return int number of bytes representing
499
-	 * @since 7.0.0
500
-	 */
501
-	public static function uploadLimit() {
502
-		return \OC_Helper::uploadLimit();
503
-	}
504
-
505
-	/**
506
-	 * Returns whether the given file name is valid
507
-	 * @param string $file file name to check
508
-	 * @return bool true if the file name is valid, false otherwise
509
-	 * @deprecated 8.1.0 use \OC\Files\View::verifyPath()
510
-	 * @since 7.0.0
511
-	 * @suppress PhanDeprecatedFunction
512
-	 */
513
-	public static function isValidFileName($file) {
514
-		return \OC_Util::isValidFileName($file);
515
-	}
516
-
517
-	/**
518
-	 * Compare two strings to provide a natural sort
519
-	 * @param string $a first string to compare
520
-	 * @param string $b second string to compare
521
-	 * @return int -1 if $b comes before $a, 1 if $a comes before $b
522
-	 * or 0 if the strings are identical
523
-	 * @since 7.0.0
524
-	 */
525
-	public static function naturalSortCompare($a, $b) {
526
-		return \OC\NaturalSort::getInstance()->compare($a, $b);
527
-	}
528
-
529
-	/**
530
-	 * check if a password is required for each public link
531
-	 * @return boolean
532
-	 * @since 7.0.0
533
-	 */
534
-	public static function isPublicLinkPasswordRequired() {
535
-		return \OC_Util::isPublicLinkPasswordRequired();
536
-	}
537
-
538
-	/**
539
-	 * check if share API enforces a default expire date
540
-	 * @return boolean
541
-	 * @since 8.0.0
542
-	 */
543
-	public static function isDefaultExpireDateEnforced() {
544
-		return \OC_Util::isDefaultExpireDateEnforced();
545
-	}
546
-
547
-	protected static $needUpgradeCache = null;
548
-
549
-	/**
550
-	 * Checks whether the current version needs upgrade.
551
-	 *
552
-	 * @return bool true if upgrade is needed, false otherwise
553
-	 * @since 7.0.0
554
-	 */
555
-	public static function needUpgrade() {
556
-		if (!isset(self::$needUpgradeCache)) {
557
-			self::$needUpgradeCache=\OC_Util::needUpgrade(\OC::$server->getSystemConfig());
558
-		}		
559
-		return self::$needUpgradeCache;
560
-	}
102
+    /**
103
+     * Get current update channel
104
+     * @return string
105
+     * @since 8.1.0
106
+     */
107
+    public static function getChannel() {
108
+        return \OC_Util::getChannel();
109
+    }
110
+
111
+    /**
112
+     * write a message in the log
113
+     * @param string $app
114
+     * @param string $message
115
+     * @param int $level
116
+     * @since 4.0.0
117
+     * @deprecated 13.0.0 use log of \OCP\ILogger
118
+     */
119
+    public static function writeLog( $app, $message, $level ) {
120
+        $context = ['app' => $app];
121
+        \OC::$server->getLogger()->log($level, $message, $context);
122
+    }
123
+
124
+    /**
125
+     * write exception into the log
126
+     * @param string $app app name
127
+     * @param \Exception $ex exception to log
128
+     * @param int $level log level, defaults to \OCP\Util::FATAL
129
+     * @since ....0.0 - parameter $level was added in 7.0.0
130
+     * @deprecated 8.2.0 use logException of \OCP\ILogger
131
+     */
132
+    public static function logException( $app, \Exception $ex, $level = ILogger::FATAL) {
133
+        \OC::$server->getLogger()->logException($ex, ['app' => $app]);
134
+    }
135
+
136
+    /**
137
+     * check if sharing is disabled for the current user
138
+     *
139
+     * @return boolean
140
+     * @since 7.0.0
141
+     * @deprecated 9.1.0 Use \OC::$server->getShareManager()->sharingDisabledForUser
142
+     */
143
+    public static function isSharingDisabledForUser() {
144
+        if (self::$shareManager === null) {
145
+            self::$shareManager = \OC::$server->getShareManager();
146
+        }
147
+
148
+        $user = \OC::$server->getUserSession()->getUser();
149
+        if ($user !== null) {
150
+            $user = $user->getUID();
151
+        }
152
+
153
+        return self::$shareManager->sharingDisabledForUser($user);
154
+    }
155
+
156
+    /**
157
+     * get l10n object
158
+     * @param string $application
159
+     * @param string|null $language
160
+     * @return \OCP\IL10N
161
+     * @since 6.0.0 - parameter $language was added in 8.0.0
162
+     */
163
+    public static function getL10N($application, $language = null) {
164
+        return \OC::$server->getL10N($application, $language);
165
+    }
166
+
167
+    /**
168
+     * add a css file
169
+     * @param string $application
170
+     * @param string $file
171
+     * @since 4.0.0
172
+     */
173
+    public static function addStyle( $application, $file = null ) {
174
+        \OC_Util::addStyle( $application, $file );
175
+    }
176
+
177
+    /**
178
+     * add a javascript file
179
+     * @param string $application
180
+     * @param string $file
181
+     * @since 4.0.0
182
+     */
183
+    public static function addScript( $application, $file = null ) {
184
+        \OC_Util::addScript( $application, $file );
185
+    }
186
+
187
+    /**
188
+     * Add a translation JS file
189
+     * @param string $application application id
190
+     * @param string $languageCode language code, defaults to the current locale
191
+     * @since 8.0.0
192
+     */
193
+    public static function addTranslations($application, $languageCode = null) {
194
+        \OC_Util::addTranslations($application, $languageCode);
195
+    }
196
+
197
+    /**
198
+     * Add a custom element to the header
199
+     * If $text is null then the element will be written as empty element.
200
+     * So use "" to get a closing tag.
201
+     * @param string $tag tag name of the element
202
+     * @param array $attributes array of attributes for the element
203
+     * @param string $text the text content for the element
204
+     * @since 4.0.0
205
+     */
206
+    public static function addHeader($tag, $attributes, $text=null) {
207
+        \OC_Util::addHeader($tag, $attributes, $text);
208
+    }
209
+
210
+    /**
211
+     * Creates an absolute url to the given app and file.
212
+     * @param string $app app
213
+     * @param string $file file
214
+     * @param array $args array with param=>value, will be appended to the returned url
215
+     * 	The value of $args will be urlencoded
216
+     * @return string the url
217
+     * @since 4.0.0 - parameter $args was added in 4.5.0
218
+     */
219
+    public static function linkToAbsolute( $app, $file, $args = array() ) {
220
+        $urlGenerator = \OC::$server->getURLGenerator();
221
+        return $urlGenerator->getAbsoluteURL(
222
+            $urlGenerator->linkTo($app, $file, $args)
223
+        );
224
+    }
225
+
226
+    /**
227
+     * Creates an absolute url for remote use.
228
+     * @param string $service id
229
+     * @return string the url
230
+     * @since 4.0.0
231
+     */
232
+    public static function linkToRemote( $service ) {
233
+        $urlGenerator = \OC::$server->getURLGenerator();
234
+        $remoteBase = $urlGenerator->linkTo('', 'remote.php') . '/' . $service;
235
+        return $urlGenerator->getAbsoluteURL(
236
+            $remoteBase . (($service[strlen($service) - 1] != '/') ? '/' : '')
237
+        );
238
+    }
239
+
240
+    /**
241
+     * Creates an absolute url for public use
242
+     * @param string $service id
243
+     * @return string the url
244
+     * @since 4.5.0
245
+     */
246
+    public static function linkToPublic($service) {
247
+        return \OC_Helper::linkToPublic($service);
248
+    }
249
+
250
+    /**
251
+     * Returns the server host name without an eventual port number
252
+     * @return string the server hostname
253
+     * @since 5.0.0
254
+     */
255
+    public static function getServerHostName() {
256
+        $host_name = \OC::$server->getRequest()->getServerHost();
257
+        // strip away port number (if existing)
258
+        $colon_pos = strpos($host_name, ':');
259
+        if ($colon_pos != FALSE) {
260
+            $host_name = substr($host_name, 0, $colon_pos);
261
+        }
262
+        return $host_name;
263
+    }
264
+
265
+    /**
266
+     * Returns the default email address
267
+     * @param string $user_part the user part of the address
268
+     * @return string the default email address
269
+     *
270
+     * Assembles a default email address (using the server hostname
271
+     * and the given user part, and returns it
272
+     * Example: when given lostpassword-noreply as $user_part param,
273
+     *     and is currently accessed via http(s)://example.com/,
274
+     *     it would return '[email protected]'
275
+     *
276
+     * If the configuration value 'mail_from_address' is set in
277
+     * config.php, this value will override the $user_part that
278
+     * is passed to this function
279
+     * @since 5.0.0
280
+     */
281
+    public static function getDefaultEmailAddress($user_part) {
282
+        $config = \OC::$server->getConfig();
283
+        $user_part = $config->getSystemValue('mail_from_address', $user_part);
284
+        $host_name = self::getServerHostName();
285
+        $host_name = $config->getSystemValue('mail_domain', $host_name);
286
+        $defaultEmailAddress = $user_part.'@'.$host_name;
287
+
288
+        $mailer = \OC::$server->getMailer();
289
+        if ($mailer->validateMailAddress($defaultEmailAddress)) {
290
+            return $defaultEmailAddress;
291
+        }
292
+
293
+        // in case we cannot build a valid email address from the hostname let's fallback to 'localhost.localdomain'
294
+        return $user_part.'@localhost.localdomain';
295
+    }
296
+
297
+    /**
298
+     * Make a human file size (2048 to 2 kB)
299
+     * @param int $bytes file size in bytes
300
+     * @return string a human readable file size
301
+     * @since 4.0.0
302
+     */
303
+    public static function humanFileSize($bytes) {
304
+        return \OC_Helper::humanFileSize($bytes);
305
+    }
306
+
307
+    /**
308
+     * Make a computer file size (2 kB to 2048)
309
+     * @param string $str file size in a fancy format
310
+     * @return float a file size in bytes
311
+     *
312
+     * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
313
+     * @since 4.0.0
314
+     */
315
+    public static function computerFileSize($str) {
316
+        return \OC_Helper::computerFileSize($str);
317
+    }
318
+
319
+    /**
320
+     * connects a function to a hook
321
+     *
322
+     * @param string $signalClass class name of emitter
323
+     * @param string $signalName name of signal
324
+     * @param string|object $slotClass class name of slot
325
+     * @param string $slotName name of slot
326
+     * @return bool
327
+     *
328
+     * This function makes it very easy to connect to use hooks.
329
+     *
330
+     * TODO: write example
331
+     * @since 4.0.0
332
+     */
333
+    static public function connectHook($signalClass, $signalName, $slotClass, $slotName) {
334
+        return \OC_Hook::connect($signalClass, $signalName, $slotClass, $slotName);
335
+    }
336
+
337
+    /**
338
+     * Emits a signal. To get data from the slot use references!
339
+     * @param string $signalclass class name of emitter
340
+     * @param string $signalname name of signal
341
+     * @param array $params default: array() array with additional data
342
+     * @return bool true if slots exists or false if not
343
+     *
344
+     * TODO: write example
345
+     * @since 4.0.0
346
+     */
347
+    static public function emitHook($signalclass, $signalname, $params = array()) {
348
+        return \OC_Hook::emit($signalclass, $signalname, $params);
349
+    }
350
+
351
+    /**
352
+     * Cached encrypted CSRF token. Some static unit-tests of ownCloud compare
353
+     * multiple OC_Template elements which invoke `callRegister`. If the value
354
+     * would not be cached these unit-tests would fail.
355
+     * @var string
356
+     */
357
+    private static $token = '';
358
+
359
+    /**
360
+     * Register an get/post call. This is important to prevent CSRF attacks
361
+     * @since 4.5.0
362
+     */
363
+    public static function callRegister() {
364
+        if(self::$token === '') {
365
+            self::$token = \OC::$server->getCsrfTokenManager()->getToken()->getEncryptedValue();
366
+        }
367
+        return self::$token;
368
+    }
369
+
370
+    /**
371
+     * Check an ajax get/post call if the request token is valid. exit if not.
372
+     * @since 4.5.0
373
+     * @deprecated 9.0.0 Use annotations based on the app framework.
374
+     */
375
+    public static function callCheck() {
376
+        if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
377
+            header('Location: '.\OC::$WEBROOT);
378
+            exit();
379
+        }
380
+
381
+        if (!\OC::$server->getRequest()->passesCSRFCheck()) {
382
+            exit();
383
+        }
384
+    }
385
+
386
+    /**
387
+     * Used to sanitize HTML
388
+     *
389
+     * This function is used to sanitize HTML and should be applied on any
390
+     * string or array of strings before displaying it on a web page.
391
+     *
392
+     * @param string|array $value
393
+     * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter.
394
+     * @since 4.5.0
395
+     */
396
+    public static function sanitizeHTML($value) {
397
+        return \OC_Util::sanitizeHTML($value);
398
+    }
399
+
400
+    /**
401
+     * Public function to encode url parameters
402
+     *
403
+     * This function is used to encode path to file before output.
404
+     * Encoding is done according to RFC 3986 with one exception:
405
+     * Character '/' is preserved as is.
406
+     *
407
+     * @param string $component part of URI to encode
408
+     * @return string
409
+     * @since 6.0.0
410
+     */
411
+    public static function encodePath($component) {
412
+        return \OC_Util::encodePath($component);
413
+    }
414
+
415
+    /**
416
+     * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
417
+     *
418
+     * @param array $input The array to work on
419
+     * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
420
+     * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
421
+     * @return array
422
+     * @since 4.5.0
423
+     */
424
+    public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
425
+        return \OC_Helper::mb_array_change_key_case($input, $case, $encoding);
426
+    }
427
+
428
+    /**
429
+     * replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement.
430
+     *
431
+     * @param string $string The input string. Opposite to the PHP build-in function does not accept an array.
432
+     * @param string $replacement The replacement string.
433
+     * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string.
434
+     * @param int $length Length of the part to be replaced
435
+     * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
436
+     * @return string
437
+     * @since 4.5.0
438
+     * @deprecated 8.2.0 Use substr_replace() instead.
439
+     */
440
+    public static function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = 'UTF-8') {
441
+        return substr_replace($string, $replacement, $start, $length);
442
+    }
443
+
444
+    /**
445
+     * Replace all occurrences of the search string with the replacement string
446
+     *
447
+     * @param string $search The value being searched for, otherwise known as the needle. String.
448
+     * @param string $replace The replacement string.
449
+     * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
450
+     * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
451
+     * @param int $count If passed, this will be set to the number of replacements performed.
452
+     * @return string
453
+     * @since 4.5.0
454
+     * @deprecated 8.2.0 Use str_replace() instead.
455
+     */
456
+    public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
457
+        return str_replace($search, $replace, $subject, $count);
458
+    }
459
+
460
+    /**
461
+     * performs a search in a nested array
462
+     *
463
+     * @param array $haystack the array to be searched
464
+     * @param string $needle the search string
465
+     * @param mixed $index optional, only search this key name
466
+     * @return mixed the key of the matching field, otherwise false
467
+     * @since 4.5.0
468
+     */
469
+    public static function recursiveArraySearch($haystack, $needle, $index = null) {
470
+        return \OC_Helper::recursiveArraySearch($haystack, $needle, $index);
471
+    }
472
+
473
+    /**
474
+     * calculates the maximum upload size respecting system settings, free space and user quota
475
+     *
476
+     * @param string $dir the current folder where the user currently operates
477
+     * @param int $free the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
478
+     * @return int number of bytes representing
479
+     * @since 5.0.0
480
+     */
481
+    public static function maxUploadFilesize($dir, $free = null) {
482
+        return \OC_Helper::maxUploadFilesize($dir, $free);
483
+    }
484
+
485
+    /**
486
+     * Calculate free space left within user quota
487
+     * @param string $dir the current folder where the user currently operates
488
+     * @return int number of bytes representing
489
+     * @since 7.0.0
490
+     */
491
+    public static function freeSpace($dir) {
492
+        return \OC_Helper::freeSpace($dir);
493
+    }
494
+
495
+    /**
496
+     * Calculate PHP upload limit
497
+     *
498
+     * @return int number of bytes representing
499
+     * @since 7.0.0
500
+     */
501
+    public static function uploadLimit() {
502
+        return \OC_Helper::uploadLimit();
503
+    }
504
+
505
+    /**
506
+     * Returns whether the given file name is valid
507
+     * @param string $file file name to check
508
+     * @return bool true if the file name is valid, false otherwise
509
+     * @deprecated 8.1.0 use \OC\Files\View::verifyPath()
510
+     * @since 7.0.0
511
+     * @suppress PhanDeprecatedFunction
512
+     */
513
+    public static function isValidFileName($file) {
514
+        return \OC_Util::isValidFileName($file);
515
+    }
516
+
517
+    /**
518
+     * Compare two strings to provide a natural sort
519
+     * @param string $a first string to compare
520
+     * @param string $b second string to compare
521
+     * @return int -1 if $b comes before $a, 1 if $a comes before $b
522
+     * or 0 if the strings are identical
523
+     * @since 7.0.0
524
+     */
525
+    public static function naturalSortCompare($a, $b) {
526
+        return \OC\NaturalSort::getInstance()->compare($a, $b);
527
+    }
528
+
529
+    /**
530
+     * check if a password is required for each public link
531
+     * @return boolean
532
+     * @since 7.0.0
533
+     */
534
+    public static function isPublicLinkPasswordRequired() {
535
+        return \OC_Util::isPublicLinkPasswordRequired();
536
+    }
537
+
538
+    /**
539
+     * check if share API enforces a default expire date
540
+     * @return boolean
541
+     * @since 8.0.0
542
+     */
543
+    public static function isDefaultExpireDateEnforced() {
544
+        return \OC_Util::isDefaultExpireDateEnforced();
545
+    }
546
+
547
+    protected static $needUpgradeCache = null;
548
+
549
+    /**
550
+     * Checks whether the current version needs upgrade.
551
+     *
552
+     * @return bool true if upgrade is needed, false otherwise
553
+     * @since 7.0.0
554
+     */
555
+    public static function needUpgrade() {
556
+        if (!isset(self::$needUpgradeCache)) {
557
+            self::$needUpgradeCache=\OC_Util::needUpgrade(\OC::$server->getSystemConfig());
558
+        }		
559
+        return self::$needUpgradeCache;
560
+    }
561 561
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -60,23 +60,23 @@  discard block
 block discarded – undo
60 60
 	/**
61 61
 	 * @deprecated 14.0.0 use \OCP\ILogger::DEBUG
62 62
 	 */
63
-	const DEBUG=0;
63
+	const DEBUG = 0;
64 64
 	/**
65 65
 	 * @deprecated 14.0.0 use \OCP\ILogger::INFO
66 66
 	 */
67
-	const INFO=1;
67
+	const INFO = 1;
68 68
 	/**
69 69
 	 * @deprecated 14.0.0 use \OCP\ILogger::WARN
70 70
 	 */
71
-	const WARN=2;
71
+	const WARN = 2;
72 72
 	/**
73 73
 	 * @deprecated 14.0.0 use \OCP\ILogger::ERROR
74 74
 	 */
75
-	const ERROR=3;
75
+	const ERROR = 3;
76 76
 	/**
77 77
 	 * @deprecated 14.0.0 use \OCP\ILogger::FATAL
78 78
 	 */
79
-	const FATAL=4;
79
+	const FATAL = 4;
80 80
 
81 81
 	/** \OCP\Share\IManager */
82 82
 	private static $shareManager;
@@ -116,7 +116,7 @@  discard block
 block discarded – undo
116 116
 	 * @since 4.0.0
117 117
 	 * @deprecated 13.0.0 use log of \OCP\ILogger
118 118
 	 */
119
-	public static function writeLog( $app, $message, $level ) {
119
+	public static function writeLog($app, $message, $level) {
120 120
 		$context = ['app' => $app];
121 121
 		\OC::$server->getLogger()->log($level, $message, $context);
122 122
 	}
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
 	 * @since ....0.0 - parameter $level was added in 7.0.0
130 130
 	 * @deprecated 8.2.0 use logException of \OCP\ILogger
131 131
 	 */
132
-	public static function logException( $app, \Exception $ex, $level = ILogger::FATAL) {
132
+	public static function logException($app, \Exception $ex, $level = ILogger::FATAL) {
133 133
 		\OC::$server->getLogger()->logException($ex, ['app' => $app]);
134 134
 	}
135 135
 
@@ -170,8 +170,8 @@  discard block
 block discarded – undo
170 170
 	 * @param string $file
171 171
 	 * @since 4.0.0
172 172
 	 */
173
-	public static function addStyle( $application, $file = null ) {
174
-		\OC_Util::addStyle( $application, $file );
173
+	public static function addStyle($application, $file = null) {
174
+		\OC_Util::addStyle($application, $file);
175 175
 	}
176 176
 
177 177
 	/**
@@ -180,8 +180,8 @@  discard block
 block discarded – undo
180 180
 	 * @param string $file
181 181
 	 * @since 4.0.0
182 182
 	 */
183
-	public static function addScript( $application, $file = null ) {
184
-		\OC_Util::addScript( $application, $file );
183
+	public static function addScript($application, $file = null) {
184
+		\OC_Util::addScript($application, $file);
185 185
 	}
186 186
 
187 187
 	/**
@@ -203,7 +203,7 @@  discard block
 block discarded – undo
203 203
 	 * @param string $text the text content for the element
204 204
 	 * @since 4.0.0
205 205
 	 */
206
-	public static function addHeader($tag, $attributes, $text=null) {
206
+	public static function addHeader($tag, $attributes, $text = null) {
207 207
 		\OC_Util::addHeader($tag, $attributes, $text);
208 208
 	}
209 209
 
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
 	 * @return string the url
217 217
 	 * @since 4.0.0 - parameter $args was added in 4.5.0
218 218
 	 */
219
-	public static function linkToAbsolute( $app, $file, $args = array() ) {
219
+	public static function linkToAbsolute($app, $file, $args = array()) {
220 220
 		$urlGenerator = \OC::$server->getURLGenerator();
221 221
 		return $urlGenerator->getAbsoluteURL(
222 222
 			$urlGenerator->linkTo($app, $file, $args)
@@ -229,11 +229,11 @@  discard block
 block discarded – undo
229 229
 	 * @return string the url
230 230
 	 * @since 4.0.0
231 231
 	 */
232
-	public static function linkToRemote( $service ) {
232
+	public static function linkToRemote($service) {
233 233
 		$urlGenerator = \OC::$server->getURLGenerator();
234
-		$remoteBase = $urlGenerator->linkTo('', 'remote.php') . '/' . $service;
234
+		$remoteBase = $urlGenerator->linkTo('', 'remote.php').'/'.$service;
235 235
 		return $urlGenerator->getAbsoluteURL(
236
-			$remoteBase . (($service[strlen($service) - 1] != '/') ? '/' : '')
236
+			$remoteBase.(($service[strlen($service) - 1] != '/') ? '/' : '')
237 237
 		);
238 238
 	}
239 239
 
@@ -361,7 +361,7 @@  discard block
 block discarded – undo
361 361
 	 * @since 4.5.0
362 362
 	 */
363 363
 	public static function callRegister() {
364
-		if(self::$token === '') {
364
+		if (self::$token === '') {
365 365
 			self::$token = \OC::$server->getCsrfTokenManager()->getToken()->getEncryptedValue();
366 366
 		}
367 367
 		return self::$token;
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
 	 * @deprecated 9.0.0 Use annotations based on the app framework.
374 374
 	 */
375 375
 	public static function callCheck() {
376
-		if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
376
+		if (!\OC::$server->getRequest()->passesStrictCookieCheck()) {
377 377
 			header('Location: '.\OC::$WEBROOT);
378 378
 			exit();
379 379
 		}
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
 	 */
555 555
 	public static function needUpgrade() {
556 556
 		if (!isset(self::$needUpgradeCache)) {
557
-			self::$needUpgradeCache=\OC_Util::needUpgrade(\OC::$server->getSystemConfig());
557
+			self::$needUpgradeCache = \OC_Util::needUpgrade(\OC::$server->getSystemConfig());
558 558
 		}		
559 559
 		return self::$needUpgradeCache;
560 560
 	}
Please login to merge, or discard this patch.
lib/public/ILogger.php 2 patches
Indentation   +120 added lines, -120 removed lines patch added patch discarded remove patch
@@ -36,134 +36,134 @@
 block discarded – undo
36 36
  * https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#3-psrlogloggerinterface
37 37
  */
38 38
 interface ILogger {
39
-	/**
40
-	 * @since 14.0.0
41
-	 */
42
-	const DEBUG=0;
43
-	/**
44
-	 * @since 14.0.0
45
-	 */
46
-	const INFO=1;
47
-	/**
48
-	 * @since 14.0.0
49
-	 */
50
-	const WARN=2;
51
-	/**
52
-	 * @since 14.0.0
53
-	 */
54
-	const ERROR=3;
55
-	/**
56
-	 * @since 14.0.0
57
-	 */
58
-	const FATAL=4;
39
+    /**
40
+     * @since 14.0.0
41
+     */
42
+    const DEBUG=0;
43
+    /**
44
+     * @since 14.0.0
45
+     */
46
+    const INFO=1;
47
+    /**
48
+     * @since 14.0.0
49
+     */
50
+    const WARN=2;
51
+    /**
52
+     * @since 14.0.0
53
+     */
54
+    const ERROR=3;
55
+    /**
56
+     * @since 14.0.0
57
+     */
58
+    const FATAL=4;
59 59
 
60
-	/**
61
-	 * System is unusable.
62
-	 *
63
-	 * @param string $message
64
-	 * @param array $context
65
-	 * @return null
66
-	 * @since 7.0.0
67
-	 */
68
-	public function emergency(string $message, array $context = []);
60
+    /**
61
+     * System is unusable.
62
+     *
63
+     * @param string $message
64
+     * @param array $context
65
+     * @return null
66
+     * @since 7.0.0
67
+     */
68
+    public function emergency(string $message, array $context = []);
69 69
 
70
-	/**
71
-	 * Action must be taken immediately.
72
-	 *
73
-	 * @param string $message
74
-	 * @param array $context
75
-	 * @return null
76
-	 * @since 7.0.0
77
-	 */
78
-	public function alert(string $message, array $context = []);
70
+    /**
71
+     * Action must be taken immediately.
72
+     *
73
+     * @param string $message
74
+     * @param array $context
75
+     * @return null
76
+     * @since 7.0.0
77
+     */
78
+    public function alert(string $message, array $context = []);
79 79
 
80
-	/**
81
-	 * Critical conditions.
82
-	 *
83
-	 * @param string $message
84
-	 * @param array $context
85
-	 * @return null
86
-	 * @since 7.0.0
87
-	 */
88
-	public function critical(string $message, array $context = []);
80
+    /**
81
+     * Critical conditions.
82
+     *
83
+     * @param string $message
84
+     * @param array $context
85
+     * @return null
86
+     * @since 7.0.0
87
+     */
88
+    public function critical(string $message, array $context = []);
89 89
 
90
-	/**
91
-	 * Runtime errors that do not require immediate action but should typically
92
-	 * be logged and monitored.
93
-	 *
94
-	 * @param string $message
95
-	 * @param array $context
96
-	 * @return null
97
-	 * @since 7.0.0
98
-	 */
99
-	public function error(string $message, array $context = []);
90
+    /**
91
+     * Runtime errors that do not require immediate action but should typically
92
+     * be logged and monitored.
93
+     *
94
+     * @param string $message
95
+     * @param array $context
96
+     * @return null
97
+     * @since 7.0.0
98
+     */
99
+    public function error(string $message, array $context = []);
100 100
 
101
-	/**
102
-	 * Exceptional occurrences that are not errors.
103
-	 *
104
-	 * @param string $message
105
-	 * @param array $context
106
-	 * @return null
107
-	 * @since 7.0.0
108
-	 */
109
-	public function warning(string $message, array $context = []);
101
+    /**
102
+     * Exceptional occurrences that are not errors.
103
+     *
104
+     * @param string $message
105
+     * @param array $context
106
+     * @return null
107
+     * @since 7.0.0
108
+     */
109
+    public function warning(string $message, array $context = []);
110 110
 
111
-	/**
112
-	 * Normal but significant events.
113
-	 *
114
-	 * @param string $message
115
-	 * @param array $context
116
-	 * @return null
117
-	 * @since 7.0.0
118
-	 */
119
-	public function notice(string $message, array $context = []);
111
+    /**
112
+     * Normal but significant events.
113
+     *
114
+     * @param string $message
115
+     * @param array $context
116
+     * @return null
117
+     * @since 7.0.0
118
+     */
119
+    public function notice(string $message, array $context = []);
120 120
 
121
-	/**
122
-	 * Interesting events.
123
-	 *
124
-	 * @param string $message
125
-	 * @param array $context
126
-	 * @return null
127
-	 * @since 7.0.0
128
-	 */
129
-	public function info(string $message, array $context = []);
121
+    /**
122
+     * Interesting events.
123
+     *
124
+     * @param string $message
125
+     * @param array $context
126
+     * @return null
127
+     * @since 7.0.0
128
+     */
129
+    public function info(string $message, array $context = []);
130 130
 
131
-	/**
132
-	 * Detailed debug information.
133
-	 *
134
-	 * @param string $message
135
-	 * @param array $context
136
-	 * @return null
137
-	 * @since 7.0.0
138
-	 */
139
-	public function debug(string $message, array $context = []);
131
+    /**
132
+     * Detailed debug information.
133
+     *
134
+     * @param string $message
135
+     * @param array $context
136
+     * @return null
137
+     * @since 7.0.0
138
+     */
139
+    public function debug(string $message, array $context = []);
140 140
 
141
-	/**
142
-	 * Logs with an arbitrary level.
143
-	 *
144
-	 * @param int $level
145
-	 * @param string $message
146
-	 * @param array $context
147
-	 * @return mixed
148
-	 * @since 7.0.0
149
-	 */
150
-	public function log(int $level, string $message, array $context = []);
141
+    /**
142
+     * Logs with an arbitrary level.
143
+     *
144
+     * @param int $level
145
+     * @param string $message
146
+     * @param array $context
147
+     * @return mixed
148
+     * @since 7.0.0
149
+     */
150
+    public function log(int $level, string $message, array $context = []);
151 151
 
152
-	/**
153
-	 * Logs an exception very detailed
154
-	 * An additional message can we written to the log by adding it to the
155
-	 * context.
156
-	 *
157
-	 * <code>
158
-	 * $logger->logException($ex, [
159
-	 *     'message' => 'Exception during background job execution'
160
-	 * ]);
161
-	 * </code>
162
-	 *
163
-	 * @param \Exception|\Throwable $exception
164
-	 * @param array $context
165
-	 * @return void
166
-	 * @since 8.2.0
167
-	 */
168
-	public function logException(\Throwable $exception, array $context = []);
152
+    /**
153
+     * Logs an exception very detailed
154
+     * An additional message can we written to the log by adding it to the
155
+     * context.
156
+     *
157
+     * <code>
158
+     * $logger->logException($ex, [
159
+     *     'message' => 'Exception during background job execution'
160
+     * ]);
161
+     * </code>
162
+     *
163
+     * @param \Exception|\Throwable $exception
164
+     * @param array $context
165
+     * @return void
166
+     * @since 8.2.0
167
+     */
168
+    public function logException(\Throwable $exception, array $context = []);
169 169
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -39,23 +39,23 @@
 block discarded – undo
39 39
 	/**
40 40
 	 * @since 14.0.0
41 41
 	 */
42
-	const DEBUG=0;
42
+	const DEBUG = 0;
43 43
 	/**
44 44
 	 * @since 14.0.0
45 45
 	 */
46
-	const INFO=1;
46
+	const INFO = 1;
47 47
 	/**
48 48
 	 * @since 14.0.0
49 49
 	 */
50
-	const WARN=2;
50
+	const WARN = 2;
51 51
 	/**
52 52
 	 * @since 14.0.0
53 53
 	 */
54
-	const ERROR=3;
54
+	const ERROR = 3;
55 55
 	/**
56 56
 	 * @since 14.0.0
57 57
 	 */
58
-	const FATAL=4;
58
+	const FATAL = 4;
59 59
 
60 60
 	/**
61 61
 	 * System is unusable.
Please login to merge, or discard this patch.
settings/ajax/enableapp.php 2 patches
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -32,30 +32,30 @@
 block discarded – undo
32 32
 
33 33
 $lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
34 34
 if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
35
-	$l = \OC::$server->getL10N('core');
36
-	OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
37
-	exit();
35
+    $l = \OC::$server->getL10N('core');
36
+    OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
37
+    exit();
38 38
 }
39 39
 
40 40
 $groups = isset($_POST['groups']) ? (array)$_POST['groups'] : [];
41 41
 $appIds = isset($_POST['appIds']) ? (array)$_POST['appIds'] : [];
42 42
 
43 43
 try {
44
-	$updateRequired = false;
45
-	foreach($appIds as $appId) {
46
-		$app = new OC_App();
47
-		$appId = OC_App::cleanAppId($appId);
48
-		$app->enable($appId, $groups);
49
-		if(\OC_App::shouldUpgrade($appId)) {
50
-			$updateRequired = true;
51
-		}
52
-	}
44
+    $updateRequired = false;
45
+    foreach($appIds as $appId) {
46
+        $app = new OC_App();
47
+        $appId = OC_App::cleanAppId($appId);
48
+        $app->enable($appId, $groups);
49
+        if(\OC_App::shouldUpgrade($appId)) {
50
+            $updateRequired = true;
51
+        }
52
+    }
53 53
 
54
-	OC_JSON::success(['data' => ['update_required' => $updateRequired]]);
54
+    OC_JSON::success(['data' => ['update_required' => $updateRequired]]);
55 55
 } catch (Exception $e) {
56
-	\OC::$server->getLogger()->logException($e, [
57
-		'level' => ILogger::DEBUG,
58
-		'app' => 'core',
59
-	]);
60
-	OC_JSON::error(array("data" => array("message" => $e->getMessage()) ));
56
+    \OC::$server->getLogger()->logException($e, [
57
+        'level' => ILogger::DEBUG,
58
+        'app' => 'core',
59
+    ]);
60
+    OC_JSON::error(array("data" => array("message" => $e->getMessage()) ));
61 61
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -33,20 +33,20 @@  discard block
 block discarded – undo
33 33
 $lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
34 34
 if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
35 35
 	$l = \OC::$server->getL10N('core');
36
-	OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
36
+	OC_JSON::error(array('data' => array('message' => $l->t('Password confirmation is required'))));
37 37
 	exit();
38 38
 }
39 39
 
40
-$groups = isset($_POST['groups']) ? (array)$_POST['groups'] : [];
41
-$appIds = isset($_POST['appIds']) ? (array)$_POST['appIds'] : [];
40
+$groups = isset($_POST['groups']) ? (array) $_POST['groups'] : [];
41
+$appIds = isset($_POST['appIds']) ? (array) $_POST['appIds'] : [];
42 42
 
43 43
 try {
44 44
 	$updateRequired = false;
45
-	foreach($appIds as $appId) {
45
+	foreach ($appIds as $appId) {
46 46
 		$app = new OC_App();
47 47
 		$appId = OC_App::cleanAppId($appId);
48 48
 		$app->enable($appId, $groups);
49
-		if(\OC_App::shouldUpgrade($appId)) {
49
+		if (\OC_App::shouldUpgrade($appId)) {
50 50
 			$updateRequired = true;
51 51
 		}
52 52
 	}
@@ -57,5 +57,5 @@  discard block
 block discarded – undo
57 57
 		'level' => ILogger::DEBUG,
58 58
 		'app' => 'core',
59 59
 	]);
60
-	OC_JSON::error(array("data" => array("message" => $e->getMessage()) ));
60
+	OC_JSON::error(array("data" => array("message" => $e->getMessage())));
61 61
 }
Please login to merge, or discard this patch.
settings/Controller/UsersController.php 1 patch
Indentation   +943 added lines, -943 removed lines patch added patch discarded remove patch
@@ -71,948 +71,948 @@
 block discarded – undo
71 71
  * @package OC\Settings\Controller
72 72
  */
73 73
 class UsersController extends Controller {
74
-	/** @var IL10N */
75
-	private $l10n;
76
-	/** @var IUserSession */
77
-	private $userSession;
78
-	/** @var bool */
79
-	private $isAdmin;
80
-	/** @var IUserManager */
81
-	private $userManager;
82
-	/** @var IGroupManager */
83
-	private $groupManager;
84
-	/** @var IConfig */
85
-	private $config;
86
-	/** @var ILogger */
87
-	private $log;
88
-	/** @var IMailer */
89
-	private $mailer;
90
-	/** @var bool contains the state of the encryption app */
91
-	private $isEncryptionAppEnabled;
92
-	/** @var bool contains the state of the admin recovery setting */
93
-	private $isRestoreEnabled = false;
94
-	/** @var IAppManager */
95
-	private $appManager;
96
-	/** @var IAvatarManager */
97
-	private $avatarManager;
98
-	/** @var AccountManager */
99
-	private $accountManager;
100
-	/** @var ISecureRandom */
101
-	private $secureRandom;
102
-	/** @var NewUserMailHelper */
103
-	private $newUserMailHelper;
104
-	/** @var Manager */
105
-	private $keyManager;
106
-	/** @var IJobList */
107
-	private $jobList;
108
-
109
-	/** @var IUserMountCache */
110
-	private $userMountCache;
111
-
112
-	/** @var IManager */
113
-	private $encryptionManager;
114
-
115
-	public function __construct(string $appName,
116
-								IRequest $request,
117
-								IUserManager $userManager,
118
-								IGroupManager $groupManager,
119
-								IUserSession $userSession,
120
-								IConfig $config,
121
-								bool $isAdmin,
122
-								IL10N $l10n,
123
-								ILogger $log,
124
-								IMailer $mailer,
125
-								IURLGenerator $urlGenerator,
126
-								IAppManager $appManager,
127
-								IAvatarManager $avatarManager,
128
-								AccountManager $accountManager,
129
-								ISecureRandom $secureRandom,
130
-								NewUserMailHelper $newUserMailHelper,
131
-								Manager $keyManager,
132
-								IJobList $jobList,
133
-								IUserMountCache $userMountCache,
134
-								IManager $encryptionManager) {
135
-		parent::__construct($appName, $request);
136
-		$this->userManager = $userManager;
137
-		$this->groupManager = $groupManager;
138
-		$this->userSession = $userSession;
139
-		$this->config = $config;
140
-		$this->isAdmin = $isAdmin;
141
-		$this->l10n = $l10n;
142
-		$this->log = $log;
143
-		$this->mailer = $mailer;
144
-		$this->appManager = $appManager;
145
-		$this->avatarManager = $avatarManager;
146
-		$this->accountManager = $accountManager;
147
-		$this->secureRandom = $secureRandom;
148
-		$this->newUserMailHelper = $newUserMailHelper;
149
-		$this->keyManager = $keyManager;
150
-		$this->jobList = $jobList;
151
-		$this->userMountCache = $userMountCache;
152
-		$this->encryptionManager = $encryptionManager;
153
-
154
-		// check for encryption state - TODO see formatUserForIndex
155
-		$this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption');
156
-		if ($this->isEncryptionAppEnabled) {
157
-			// putting this directly in empty is possible in PHP 5.5+
158
-			$result = $config->getAppValue('encryption', 'recoveryAdminEnabled', '0');
159
-			$this->isRestoreEnabled = !empty($result);
160
-		}
161
-	}
162
-
163
-	/**
164
-	 * @param IUser $user
165
-	 * @param array|null $userGroups
166
-	 * @return array
167
-	 */
168
-	private function formatUserForIndex(IUser $user, array $userGroups = null): array {
169
-
170
-		// TODO: eliminate this encryption specific code below and somehow
171
-		// hook in additional user info from other apps
172
-
173
-		// recovery isn't possible if admin or user has it disabled and encryption
174
-		// is enabled - so we eliminate the else paths in the conditional tree
175
-		// below
176
-		$restorePossible = false;
177
-
178
-		if ($this->isEncryptionAppEnabled) {
179
-			if ($this->isRestoreEnabled) {
180
-				// check for the users recovery setting
181
-				$recoveryMode = $this->config->getUserValue($user->getUID(), 'encryption', 'recoveryEnabled', '0');
182
-				// method call inside empty is possible with PHP 5.5+
183
-				$recoveryModeEnabled = !empty($recoveryMode);
184
-				if ($recoveryModeEnabled) {
185
-					// user also has recovery mode enabled
186
-					$restorePossible = true;
187
-				}
188
-			} else {
189
-				$modules = $this->encryptionManager->getEncryptionModules();
190
-				$restorePossible = true;
191
-				foreach ($modules as $id => $module) {
192
-					/* @var IEncryptionModule $instance */
193
-					$instance = call_user_func($module['callback']);
194
-					if ($instance->needDetailedAccessList()) {
195
-						$restorePossible = false;
196
-						break;
197
-					}
198
-				}
199
-			}
200
-		} else {
201
-			// recovery is possible if encryption is disabled (plain files are
202
-			// available)
203
-			$restorePossible = true;
204
-		}
205
-
206
-		$subAdminGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroupsName($user);
207
-
208
-		$displayName = $user->getEMailAddress();
209
-		if (is_null($displayName)) {
210
-			$displayName = '';
211
-		}
212
-
213
-		$avatarAvailable = false;
214
-		try {
215
-			$avatarAvailable = $this->avatarManager->getAvatar($user->getUID())->exists();
216
-		} catch (\Exception $e) {
217
-			//No avatar yet
218
-		}
219
-
220
-		return [
221
-			'name' => $user->getUID(),
222
-			'displayname' => $user->getDisplayName(),
223
-			'groups' => empty($userGroups) ? $this->groupManager->getUserGroupNames($user) : $userGroups,
224
-			'subadmin' => $subAdminGroups,
225
-			'quota' => $user->getQuota(),
226
-			'quota_bytes' => Util::computerFileSize($user->getQuota()),
227
-			'storageLocation' => $user->getHome(),
228
-			'lastLogin' => $user->getLastLogin() * 1000,
229
-			'backend' => $user->getBackendClassName(),
230
-			'email' => $displayName,
231
-			'isRestoreDisabled' => !$restorePossible,
232
-			'isAvatarAvailable' => $avatarAvailable,
233
-			'isEnabled' => $user->isEnabled(),
234
-		];
235
-	}
236
-
237
-	/**
238
-	 * @param array $userIDs Array with schema [$uid => $displayName]
239
-	 * @return IUser[]
240
-	 */
241
-	private function getUsersForUID(array $userIDs): array {
242
-		$users = [];
243
-		foreach ($userIDs as $uid => $displayName) {
244
-			$users[$uid] = $this->userManager->get($uid);
245
-		}
246
-		return $users;
247
-	}
248
-
249
-	/**
250
-	 * @NoAdminRequired
251
-	 *
252
-	 * @param int $offset
253
-	 * @param int $limit
254
-	 * @param string $gid GID to filter for
255
-	 * @param string $pattern Pattern to search for in the username
256
-	 * @param string $backend Backend to filter for (class-name)
257
-	 * @return DataResponse
258
-	 *
259
-	 * TODO: Tidy up and write unit tests - code is mainly static method calls
260
-	 */
261
-	public function index(int $offset = 0, int $limit = 10, string $gid = '', string $pattern = '', string $backend = ''): DataResponse {
262
-		// Remove backends
263
-		if (!empty($backend)) {
264
-			$activeBackends = $this->userManager->getBackends();
265
-			$this->userManager->clearBackends();
266
-			foreach ($activeBackends as $singleActiveBackend) {
267
-				if ($backend === get_class($singleActiveBackend)) {
268
-					$this->userManager->registerBackend($singleActiveBackend);
269
-					break;
270
-				}
271
-			}
272
-		}
273
-
274
-		$userObjects = [];
275
-		$users = [];
276
-		if ($this->isAdmin) {
277
-			if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
278
-				$batch = $this->getUsersForUID($this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset));
279
-			} else {
280
-				$batch = $this->userManager->search($pattern, $limit, $offset);
281
-			}
282
-
283
-			foreach ($batch as $user) {
284
-				if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
285
-					($gid === '_disabledUsers' && !$user->isEnabled())
286
-				) {
287
-					$userObjects[] = $user;
288
-					$users[] = $this->formatUserForIndex($user);
289
-				}
290
-			}
291
-
292
-		} else {
293
-			$subAdminOfGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
294
-			// New class returns IGroup[] so convert back
295
-			$gids = [];
296
-			foreach ($subAdminOfGroups as $group) {
297
-				$gids[] = $group->getGID();
298
-			}
299
-			$subAdminOfGroups = $gids;
300
-
301
-			// Set the $gid parameter to an empty value if the subadmin has no rights to access a specific group
302
-			if ($gid !== '' && $gid !== '_disabledUsers' && !in_array($gid, $subAdminOfGroups)) {
303
-				$gid = '';
304
-			}
305
-
306
-			// Batch all groups the user is subadmin of when a group is specified
307
-			$batch = [];
308
-			if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
309
-				$batch = $this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset);
310
-			} else {
311
-				foreach ($subAdminOfGroups as $group) {
312
-					$groupUsers = $this->groupManager->displayNamesInGroup($group, $pattern, $limit, $offset);
313
-
314
-					foreach ($groupUsers as $uid => $displayName) {
315
-						$batch[$uid] = $displayName;
316
-					}
317
-				}
318
-			}
319
-			$batch = $this->getUsersForUID($batch);
320
-
321
-			foreach ($batch as $user) {
322
-				// Only add the groups, this user is a subadmin of
323
-				$userGroups = array_values(array_intersect(
324
-					$this->groupManager->getUserGroupIds($user),
325
-					$subAdminOfGroups
326
-				));
327
-				if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
328
-					($gid === '_disabledUsers' && !$user->isEnabled())
329
-				) {
330
-					$userObjects[] = $user;
331
-					$users[] = $this->formatUserForIndex($user, $userGroups);
332
-				}
333
-			}
334
-		}
335
-
336
-		$usedSpace = $this->userMountCache->getUsedSpaceForUsers($userObjects);
337
-
338
-		foreach ($users as &$userData) {
339
-			$userData['size'] = isset($usedSpace[$userData['name']]) ? $usedSpace[$userData['name']] : 0;
340
-		}
341
-
342
-		return new DataResponse($users);
343
-	}
344
-
345
-	/**
346
-	 * @NoAdminRequired
347
-	 * @PasswordConfirmationRequired
348
-	 *
349
-	 * @param string $username
350
-	 * @param string $password
351
-	 * @param array $groups
352
-	 * @param string $email
353
-	 * @return DataResponse
354
-	 */
355
-	public function create(string $username, string $password, array $groups = [], $email = ''): DataResponse {
356
-		if ($email !== '' && !$this->mailer->validateMailAddress($email)) {
357
-			return new DataResponse(
358
-				[
359
-					'message' => $this->l10n->t('Invalid mail address')
360
-				],
361
-				Http::STATUS_UNPROCESSABLE_ENTITY
362
-			);
363
-		}
364
-
365
-		$currentUser = $this->userSession->getUser();
366
-
367
-		if (!$this->isAdmin) {
368
-			if (!empty($groups)) {
369
-				foreach ($groups as $key => $group) {
370
-					$groupObject = $this->groupManager->get($group);
371
-					if ($groupObject === null) {
372
-						unset($groups[$key]);
373
-						continue;
374
-					}
375
-
376
-					if (!$this->groupManager->getSubAdmin()->isSubAdminOfGroup($currentUser, $groupObject)) {
377
-						unset($groups[$key]);
378
-					}
379
-				}
380
-			}
381
-
382
-			if (empty($groups)) {
383
-				return new DataResponse(
384
-					[
385
-						'message' => $this->l10n->t('No valid group selected'),
386
-					],
387
-					Http::STATUS_FORBIDDEN
388
-				);
389
-			}
390
-		}
391
-
392
-		if ($this->userManager->userExists($username)) {
393
-			return new DataResponse(
394
-				[
395
-					'message' => $this->l10n->t('A user with that name already exists.')
396
-				],
397
-				Http::STATUS_CONFLICT
398
-			);
399
-		}
400
-
401
-		$generatePasswordResetToken = false;
402
-		if ($password === '') {
403
-			if ($email === '') {
404
-				return new DataResponse(
405
-					[
406
-						'message' => $this->l10n->t('To send a password link to the user an email address is required.')
407
-					],
408
-					Http::STATUS_UNPROCESSABLE_ENTITY
409
-				);
410
-			}
411
-
412
-			$password = $this->secureRandom->generate(30);
413
-			// Make sure we pass the password_policy
414
-			$password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
415
-			$generatePasswordResetToken = true;
416
-		}
417
-
418
-		try {
419
-			$user = $this->userManager->createUser($username, $password);
420
-		} catch (\Exception $exception) {
421
-			$message = $exception->getMessage();
422
-			if ($exception instanceof HintException && $exception->getHint()) {
423
-				$message = $exception->getHint();
424
-			}
425
-			if (!$message) {
426
-				$message = $this->l10n->t('Unable to create user.');
427
-			}
428
-			return new DataResponse(
429
-				[
430
-					'message' => (string)$message,
431
-				],
432
-				Http::STATUS_FORBIDDEN
433
-			);
434
-		}
435
-
436
-		if ($user instanceof IUser) {
437
-			if ($groups !== null) {
438
-				foreach ($groups as $groupName) {
439
-					$group = $this->groupManager->get($groupName);
440
-
441
-					if (empty($group)) {
442
-						$group = $this->groupManager->createGroup($groupName);
443
-					}
444
-					$group->addUser($user);
445
-				}
446
-			}
447
-			/**
448
-			 * Send new user mail only if a mail is set
449
-			 */
450
-			if ($email !== '') {
451
-				$user->setEMailAddress($email);
452
-				try {
453
-					$emailTemplate = $this->newUserMailHelper->generateTemplate($user, $generatePasswordResetToken);
454
-					$this->newUserMailHelper->sendMail($user, $emailTemplate);
455
-				} catch (\Exception $e) {
456
-					$this->log->logException($e, [
457
-						'message' => "Can't send new user mail to $email",
458
-						'level' => ILogger::ERROR,
459
-						'app' => 'settings',
460
-					]);
461
-				}
462
-			}
463
-			// fetch users groups
464
-			$userGroups = $this->groupManager->getUserGroupNames($user);
465
-
466
-			return new DataResponse(
467
-				$this->formatUserForIndex($user, $userGroups),
468
-				Http::STATUS_CREATED
469
-			);
470
-		}
471
-
472
-		return new DataResponse(
473
-			[
474
-				'message' => $this->l10n->t('Unable to create user.')
475
-			],
476
-			Http::STATUS_FORBIDDEN
477
-		);
478
-
479
-	}
480
-
481
-	/**
482
-	 * @NoAdminRequired
483
-	 * @PasswordConfirmationRequired
484
-	 *
485
-	 * @param string $id
486
-	 * @return DataResponse
487
-	 */
488
-	public function destroy(string $id): DataResponse {
489
-		$userId = $this->userSession->getUser()->getUID();
490
-		$user = $this->userManager->get($id);
491
-
492
-		if ($userId === $id) {
493
-			return new DataResponse(
494
-				[
495
-					'status' => 'error',
496
-					'data' => [
497
-						'message' => $this->l10n->t('Unable to delete user.')
498
-					]
499
-				],
500
-				Http::STATUS_FORBIDDEN
501
-			);
502
-		}
503
-
504
-		if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
505
-			return new DataResponse(
506
-				[
507
-					'status' => 'error',
508
-					'data' => [
509
-						'message' => $this->l10n->t('Authentication error')
510
-					]
511
-				],
512
-				Http::STATUS_FORBIDDEN
513
-			);
514
-		}
515
-
516
-		if ($user && $user->delete()) {
517
-			return new DataResponse(
518
-				[
519
-					'status' => 'success',
520
-					'data' => [
521
-						'username' => $id
522
-					]
523
-				],
524
-				Http::STATUS_NO_CONTENT
525
-			);
526
-		}
527
-
528
-		return new DataResponse(
529
-			[
530
-				'status' => 'error',
531
-				'data' => [
532
-					'message' => $this->l10n->t('Unable to delete user.')
533
-				]
534
-			],
535
-			Http::STATUS_FORBIDDEN
536
-		);
537
-	}
538
-
539
-	/**
540
-	 * @NoAdminRequired
541
-	 *
542
-	 * @param string $id
543
-	 * @param int $enabled
544
-	 * @return DataResponse
545
-	 */
546
-	public function setEnabled(string $id, int $enabled): DataResponse {
547
-		$enabled = (bool)$enabled;
548
-		if ($enabled) {
549
-			$errorMsgGeneral = $this->l10n->t('Error while enabling user.');
550
-		} else {
551
-			$errorMsgGeneral = $this->l10n->t('Error while disabling user.');
552
-		}
553
-
554
-		$userId = $this->userSession->getUser()->getUID();
555
-		$user = $this->userManager->get($id);
556
-
557
-		if ($userId === $id) {
558
-			return new DataResponse(
559
-				[
560
-					'status' => 'error',
561
-					'data' => [
562
-						'message' => $errorMsgGeneral
563
-					]
564
-				], Http::STATUS_FORBIDDEN
565
-			);
566
-		}
567
-
568
-		if ($user) {
569
-			if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
570
-				return new DataResponse(
571
-					[
572
-						'status' => 'error',
573
-						'data' => [
574
-							'message' => $this->l10n->t('Authentication error')
575
-						]
576
-					],
577
-					Http::STATUS_FORBIDDEN
578
-				);
579
-			}
580
-
581
-			$user->setEnabled($enabled);
582
-			return new DataResponse(
583
-				[
584
-					'status' => 'success',
585
-					'data' => [
586
-						'username' => $id,
587
-						'enabled' => $enabled
588
-					]
589
-				]
590
-			);
591
-		} else {
592
-			return new DataResponse(
593
-				[
594
-					'status' => 'error',
595
-					'data' => [
596
-						'message' => $errorMsgGeneral
597
-					]
598
-				],
599
-				Http::STATUS_FORBIDDEN
600
-			);
601
-		}
602
-
603
-	}
604
-
605
-	/**
606
-	 * Set the mail address of a user
607
-	 *
608
-	 * @NoAdminRequired
609
-	 * @NoSubadminRequired
610
-	 * @PasswordConfirmationRequired
611
-	 *
612
-	 * @param string $account
613
-	 * @param bool $onlyVerificationCode only return verification code without updating the data
614
-	 * @return DataResponse
615
-	 */
616
-	public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
617
-
618
-		$user = $this->userSession->getUser();
619
-
620
-		if ($user === null) {
621
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
622
-		}
623
-
624
-		$accountData = $this->accountManager->getUser($user);
625
-		$cloudId = $user->getCloudId();
626
-		$message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
627
-		$signature = $this->signMessage($user, $message);
628
-
629
-		$code = $message . ' ' . $signature;
630
-		$codeMd5 = $message . ' ' . md5($signature);
631
-
632
-		switch ($account) {
633
-			case 'verify-twitter':
634
-				$accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
635
-				$msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
636
-				$code = $codeMd5;
637
-				$type = AccountManager::PROPERTY_TWITTER;
638
-				$data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
639
-				$accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
640
-				break;
641
-			case 'verify-website':
642
-				$accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
643
-				$msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
644
-				$type = AccountManager::PROPERTY_WEBSITE;
645
-				$data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
646
-				$accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
647
-				break;
648
-			default:
649
-				return new DataResponse([], Http::STATUS_BAD_REQUEST);
650
-		}
651
-
652
-		if ($onlyVerificationCode === false) {
653
-			$this->accountManager->updateUser($user, $accountData);
654
-
655
-			$this->jobList->add(VerifyUserData::class,
656
-				[
657
-					'verificationCode' => $code,
658
-					'data' => $data,
659
-					'type' => $type,
660
-					'uid' => $user->getUID(),
661
-					'try' => 0,
662
-					'lastRun' => $this->getCurrentTime()
663
-				]
664
-			);
665
-		}
666
-
667
-		return new DataResponse(['msg' => $msg, 'code' => $code]);
668
-	}
669
-
670
-	/**
671
-	 * get current timestamp
672
-	 *
673
-	 * @return int
674
-	 */
675
-	protected function getCurrentTime(): int {
676
-		return time();
677
-	}
678
-
679
-	/**
680
-	 * sign message with users private key
681
-	 *
682
-	 * @param IUser $user
683
-	 * @param string $message
684
-	 *
685
-	 * @return string base64 encoded signature
686
-	 */
687
-	protected function signMessage(IUser $user, string $message): string {
688
-		$privateKey = $this->keyManager->getKey($user)->getPrivate();
689
-		openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
690
-		return base64_encode($signature);
691
-	}
692
-
693
-	/**
694
-	 * @NoAdminRequired
695
-	 * @NoSubadminRequired
696
-	 * @PasswordConfirmationRequired
697
-	 *
698
-	 * @param string $avatarScope
699
-	 * @param string $displayname
700
-	 * @param string $displaynameScope
701
-	 * @param string $phone
702
-	 * @param string $phoneScope
703
-	 * @param string $email
704
-	 * @param string $emailScope
705
-	 * @param string $website
706
-	 * @param string $websiteScope
707
-	 * @param string $address
708
-	 * @param string $addressScope
709
-	 * @param string $twitter
710
-	 * @param string $twitterScope
711
-	 * @return DataResponse
712
-	 */
713
-	public function setUserSettings($avatarScope,
714
-									$displayname,
715
-									$displaynameScope,
716
-									$phone,
717
-									$phoneScope,
718
-									$email,
719
-									$emailScope,
720
-									$website,
721
-									$websiteScope,
722
-									$address,
723
-									$addressScope,
724
-									$twitter,
725
-									$twitterScope
726
-	) {
727
-
728
-		if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
729
-			return new DataResponse(
730
-				[
731
-					'status' => 'error',
732
-					'data' => [
733
-						'message' => $this->l10n->t('Invalid mail address')
734
-					]
735
-				],
736
-				Http::STATUS_UNPROCESSABLE_ENTITY
737
-			);
738
-		}
739
-
740
-		$user = $this->userSession->getUser();
741
-
742
-		$data = $this->accountManager->getUser($user);
743
-
744
-		$data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
745
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
746
-			$data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
747
-			$data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
748
-		}
749
-
750
-		if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
751
-			$federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
752
-			$shareProvider = $federatedFileSharing->getFederatedShareProvider();
753
-			if ($shareProvider->isLookupServerUploadEnabled()) {
754
-				$data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
755
-				$data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
756
-				$data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
757
-				$data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
758
-			}
759
-		}
760
-
761
-		try {
762
-			$this->saveUserSettings($user, $data);
763
-			return new DataResponse(
764
-				[
765
-					'status' => 'success',
766
-					'data' => [
767
-						'userId' => $user->getUID(),
768
-						'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
769
-						'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
770
-						'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
771
-						'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
772
-						'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
773
-						'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
774
-						'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
775
-						'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
776
-						'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
777
-						'message' => $this->l10n->t('Settings saved')
778
-					]
779
-				],
780
-				Http::STATUS_OK
781
-			);
782
-		} catch (ForbiddenException $e) {
783
-			return new DataResponse([
784
-				'status' => 'error',
785
-				'data' => [
786
-					'message' => $e->getMessage()
787
-				],
788
-			]);
789
-		}
790
-
791
-	}
792
-
793
-
794
-	/**
795
-	 * update account manager with new user data
796
-	 *
797
-	 * @param IUser $user
798
-	 * @param array $data
799
-	 * @throws ForbiddenException
800
-	 */
801
-	protected function saveUserSettings(IUser $user, array $data) {
802
-
803
-		// keep the user back-end up-to-date with the latest display name and email
804
-		// address
805
-		$oldDisplayName = $user->getDisplayName();
806
-		$oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
807
-		if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
808
-			&& $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
809
-		) {
810
-			$result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
811
-			if ($result === false) {
812
-				throw new ForbiddenException($this->l10n->t('Unable to change full name'));
813
-			}
814
-		}
815
-
816
-		$oldEmailAddress = $user->getEMailAddress();
817
-		$oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
818
-		if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
819
-			&& $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
820
-		) {
821
-			// this is the only permission a backend provides and is also used
822
-			// for the permission of setting a email address
823
-			if (!$user->canChangeDisplayName()) {
824
-				throw new ForbiddenException($this->l10n->t('Unable to change email address'));
825
-			}
826
-			$user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
827
-		}
828
-
829
-		$this->accountManager->updateUser($user, $data);
830
-	}
831
-
832
-	/**
833
-	 * Count all unique users visible for the current admin/subadmin.
834
-	 *
835
-	 * @NoAdminRequired
836
-	 *
837
-	 * @return DataResponse
838
-	 */
839
-	public function stats(): DataResponse {
840
-		$userCount = 0;
841
-		if ($this->isAdmin) {
842
-			$countByBackend = $this->userManager->countUsers();
843
-
844
-			if (!empty($countByBackend)) {
845
-				foreach ($countByBackend as $count) {
846
-					$userCount += $count;
847
-				}
848
-			}
849
-		} else {
850
-			$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
851
-
852
-			$uniqueUsers = [];
853
-			foreach ($groups as $group) {
854
-				foreach ($group->getUsers() as $uid => $displayName) {
855
-					$uniqueUsers[$uid] = true;
856
-				}
857
-			}
858
-
859
-			$userCount = count($uniqueUsers);
860
-		}
861
-
862
-		return new DataResponse(
863
-			[
864
-				'totalUsers' => $userCount
865
-			]
866
-		);
867
-	}
868
-
869
-
870
-	/**
871
-	 * Set the displayName of a user
872
-	 *
873
-	 * @NoAdminRequired
874
-	 * @NoSubadminRequired
875
-	 * @PasswordConfirmationRequired
876
-	 * @todo merge into saveUserSettings
877
-	 *
878
-	 * @param string $username
879
-	 * @param string $displayName
880
-	 * @return DataResponse
881
-	 */
882
-	public function setDisplayName(string $username, string $displayName) {
883
-		$currentUser = $this->userSession->getUser();
884
-		$user = $this->userManager->get($username);
885
-
886
-		if ($user === null ||
887
-			!$user->canChangeDisplayName() ||
888
-			(
889
-				!$this->groupManager->isAdmin($currentUser->getUID()) &&
890
-				!$this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $user) &&
891
-				$currentUser->getUID() !== $username
892
-
893
-			)
894
-		) {
895
-			return new DataResponse([
896
-				'status' => 'error',
897
-				'data' => [
898
-					'message' => $this->l10n->t('Authentication error'),
899
-				],
900
-			]);
901
-		}
902
-
903
-		$userData = $this->accountManager->getUser($user);
904
-		$userData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $displayName;
905
-
906
-
907
-		try {
908
-			$this->saveUserSettings($user, $userData);
909
-			return new DataResponse([
910
-				'status' => 'success',
911
-				'data' => [
912
-					'message' => $this->l10n->t('Your full name has been changed.'),
913
-					'username' => $username,
914
-					'displayName' => $displayName,
915
-				],
916
-			]);
917
-		} catch (ForbiddenException $e) {
918
-			return new DataResponse([
919
-				'status' => 'error',
920
-				'data' => [
921
-					'message' => $e->getMessage(),
922
-					'displayName' => $user->getDisplayName(),
923
-				],
924
-			]);
925
-		}
926
-	}
927
-
928
-	/**
929
-	 * Set the mail address of a user
930
-	 *
931
-	 * @NoAdminRequired
932
-	 * @NoSubadminRequired
933
-	 * @PasswordConfirmationRequired
934
-	 *
935
-	 * @param string $id
936
-	 * @param string $mailAddress
937
-	 * @return DataResponse
938
-	 */
939
-	public function setEMailAddress(string $id, string $mailAddress) {
940
-		$user = $this->userManager->get($id);
941
-		if (!$this->isAdmin
942
-			&& !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)
943
-		) {
944
-			return new DataResponse(
945
-				[
946
-					'status' => 'error',
947
-					'data' => [
948
-						'message' => $this->l10n->t('Forbidden')
949
-					]
950
-				],
951
-				Http::STATUS_FORBIDDEN
952
-			);
953
-		}
954
-
955
-		if ($mailAddress !== '' && !$this->mailer->validateMailAddress($mailAddress)) {
956
-			return new DataResponse(
957
-				[
958
-					'status' => 'error',
959
-					'data' => [
960
-						'message' => $this->l10n->t('Invalid mail address')
961
-					]
962
-				],
963
-				Http::STATUS_UNPROCESSABLE_ENTITY
964
-			);
965
-		}
966
-
967
-		if (!$user) {
968
-			return new DataResponse(
969
-				[
970
-					'status' => 'error',
971
-					'data' => [
972
-						'message' => $this->l10n->t('Invalid user')
973
-					]
974
-				],
975
-				Http::STATUS_UNPROCESSABLE_ENTITY
976
-			);
977
-		}
978
-		// this is the only permission a backend provides and is also used
979
-		// for the permission of setting a email address
980
-		if (!$user->canChangeDisplayName()) {
981
-			return new DataResponse(
982
-				[
983
-					'status' => 'error',
984
-					'data' => [
985
-						'message' => $this->l10n->t('Unable to change mail address')
986
-					]
987
-				],
988
-				Http::STATUS_FORBIDDEN
989
-			);
990
-		}
991
-
992
-		$userData = $this->accountManager->getUser($user);
993
-		$userData[AccountManager::PROPERTY_EMAIL]['value'] = $mailAddress;
994
-
995
-		try {
996
-			$this->saveUserSettings($user, $userData);
997
-			return new DataResponse(
998
-				[
999
-					'status' => 'success',
1000
-					'data' => [
1001
-						'username' => $id,
1002
-						'mailAddress' => $mailAddress,
1003
-						'message' => $this->l10n->t('Email saved')
1004
-					]
1005
-				],
1006
-				Http::STATUS_OK
1007
-			);
1008
-		} catch (ForbiddenException $e) {
1009
-			return new DataResponse([
1010
-				'status' => 'error',
1011
-				'data' => [
1012
-					'message' => $e->getMessage()
1013
-				],
1014
-			]);
1015
-		}
1016
-	}
74
+    /** @var IL10N */
75
+    private $l10n;
76
+    /** @var IUserSession */
77
+    private $userSession;
78
+    /** @var bool */
79
+    private $isAdmin;
80
+    /** @var IUserManager */
81
+    private $userManager;
82
+    /** @var IGroupManager */
83
+    private $groupManager;
84
+    /** @var IConfig */
85
+    private $config;
86
+    /** @var ILogger */
87
+    private $log;
88
+    /** @var IMailer */
89
+    private $mailer;
90
+    /** @var bool contains the state of the encryption app */
91
+    private $isEncryptionAppEnabled;
92
+    /** @var bool contains the state of the admin recovery setting */
93
+    private $isRestoreEnabled = false;
94
+    /** @var IAppManager */
95
+    private $appManager;
96
+    /** @var IAvatarManager */
97
+    private $avatarManager;
98
+    /** @var AccountManager */
99
+    private $accountManager;
100
+    /** @var ISecureRandom */
101
+    private $secureRandom;
102
+    /** @var NewUserMailHelper */
103
+    private $newUserMailHelper;
104
+    /** @var Manager */
105
+    private $keyManager;
106
+    /** @var IJobList */
107
+    private $jobList;
108
+
109
+    /** @var IUserMountCache */
110
+    private $userMountCache;
111
+
112
+    /** @var IManager */
113
+    private $encryptionManager;
114
+
115
+    public function __construct(string $appName,
116
+                                IRequest $request,
117
+                                IUserManager $userManager,
118
+                                IGroupManager $groupManager,
119
+                                IUserSession $userSession,
120
+                                IConfig $config,
121
+                                bool $isAdmin,
122
+                                IL10N $l10n,
123
+                                ILogger $log,
124
+                                IMailer $mailer,
125
+                                IURLGenerator $urlGenerator,
126
+                                IAppManager $appManager,
127
+                                IAvatarManager $avatarManager,
128
+                                AccountManager $accountManager,
129
+                                ISecureRandom $secureRandom,
130
+                                NewUserMailHelper $newUserMailHelper,
131
+                                Manager $keyManager,
132
+                                IJobList $jobList,
133
+                                IUserMountCache $userMountCache,
134
+                                IManager $encryptionManager) {
135
+        parent::__construct($appName, $request);
136
+        $this->userManager = $userManager;
137
+        $this->groupManager = $groupManager;
138
+        $this->userSession = $userSession;
139
+        $this->config = $config;
140
+        $this->isAdmin = $isAdmin;
141
+        $this->l10n = $l10n;
142
+        $this->log = $log;
143
+        $this->mailer = $mailer;
144
+        $this->appManager = $appManager;
145
+        $this->avatarManager = $avatarManager;
146
+        $this->accountManager = $accountManager;
147
+        $this->secureRandom = $secureRandom;
148
+        $this->newUserMailHelper = $newUserMailHelper;
149
+        $this->keyManager = $keyManager;
150
+        $this->jobList = $jobList;
151
+        $this->userMountCache = $userMountCache;
152
+        $this->encryptionManager = $encryptionManager;
153
+
154
+        // check for encryption state - TODO see formatUserForIndex
155
+        $this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption');
156
+        if ($this->isEncryptionAppEnabled) {
157
+            // putting this directly in empty is possible in PHP 5.5+
158
+            $result = $config->getAppValue('encryption', 'recoveryAdminEnabled', '0');
159
+            $this->isRestoreEnabled = !empty($result);
160
+        }
161
+    }
162
+
163
+    /**
164
+     * @param IUser $user
165
+     * @param array|null $userGroups
166
+     * @return array
167
+     */
168
+    private function formatUserForIndex(IUser $user, array $userGroups = null): array {
169
+
170
+        // TODO: eliminate this encryption specific code below and somehow
171
+        // hook in additional user info from other apps
172
+
173
+        // recovery isn't possible if admin or user has it disabled and encryption
174
+        // is enabled - so we eliminate the else paths in the conditional tree
175
+        // below
176
+        $restorePossible = false;
177
+
178
+        if ($this->isEncryptionAppEnabled) {
179
+            if ($this->isRestoreEnabled) {
180
+                // check for the users recovery setting
181
+                $recoveryMode = $this->config->getUserValue($user->getUID(), 'encryption', 'recoveryEnabled', '0');
182
+                // method call inside empty is possible with PHP 5.5+
183
+                $recoveryModeEnabled = !empty($recoveryMode);
184
+                if ($recoveryModeEnabled) {
185
+                    // user also has recovery mode enabled
186
+                    $restorePossible = true;
187
+                }
188
+            } else {
189
+                $modules = $this->encryptionManager->getEncryptionModules();
190
+                $restorePossible = true;
191
+                foreach ($modules as $id => $module) {
192
+                    /* @var IEncryptionModule $instance */
193
+                    $instance = call_user_func($module['callback']);
194
+                    if ($instance->needDetailedAccessList()) {
195
+                        $restorePossible = false;
196
+                        break;
197
+                    }
198
+                }
199
+            }
200
+        } else {
201
+            // recovery is possible if encryption is disabled (plain files are
202
+            // available)
203
+            $restorePossible = true;
204
+        }
205
+
206
+        $subAdminGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroupsName($user);
207
+
208
+        $displayName = $user->getEMailAddress();
209
+        if (is_null($displayName)) {
210
+            $displayName = '';
211
+        }
212
+
213
+        $avatarAvailable = false;
214
+        try {
215
+            $avatarAvailable = $this->avatarManager->getAvatar($user->getUID())->exists();
216
+        } catch (\Exception $e) {
217
+            //No avatar yet
218
+        }
219
+
220
+        return [
221
+            'name' => $user->getUID(),
222
+            'displayname' => $user->getDisplayName(),
223
+            'groups' => empty($userGroups) ? $this->groupManager->getUserGroupNames($user) : $userGroups,
224
+            'subadmin' => $subAdminGroups,
225
+            'quota' => $user->getQuota(),
226
+            'quota_bytes' => Util::computerFileSize($user->getQuota()),
227
+            'storageLocation' => $user->getHome(),
228
+            'lastLogin' => $user->getLastLogin() * 1000,
229
+            'backend' => $user->getBackendClassName(),
230
+            'email' => $displayName,
231
+            'isRestoreDisabled' => !$restorePossible,
232
+            'isAvatarAvailable' => $avatarAvailable,
233
+            'isEnabled' => $user->isEnabled(),
234
+        ];
235
+    }
236
+
237
+    /**
238
+     * @param array $userIDs Array with schema [$uid => $displayName]
239
+     * @return IUser[]
240
+     */
241
+    private function getUsersForUID(array $userIDs): array {
242
+        $users = [];
243
+        foreach ($userIDs as $uid => $displayName) {
244
+            $users[$uid] = $this->userManager->get($uid);
245
+        }
246
+        return $users;
247
+    }
248
+
249
+    /**
250
+     * @NoAdminRequired
251
+     *
252
+     * @param int $offset
253
+     * @param int $limit
254
+     * @param string $gid GID to filter for
255
+     * @param string $pattern Pattern to search for in the username
256
+     * @param string $backend Backend to filter for (class-name)
257
+     * @return DataResponse
258
+     *
259
+     * TODO: Tidy up and write unit tests - code is mainly static method calls
260
+     */
261
+    public function index(int $offset = 0, int $limit = 10, string $gid = '', string $pattern = '', string $backend = ''): DataResponse {
262
+        // Remove backends
263
+        if (!empty($backend)) {
264
+            $activeBackends = $this->userManager->getBackends();
265
+            $this->userManager->clearBackends();
266
+            foreach ($activeBackends as $singleActiveBackend) {
267
+                if ($backend === get_class($singleActiveBackend)) {
268
+                    $this->userManager->registerBackend($singleActiveBackend);
269
+                    break;
270
+                }
271
+            }
272
+        }
273
+
274
+        $userObjects = [];
275
+        $users = [];
276
+        if ($this->isAdmin) {
277
+            if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
278
+                $batch = $this->getUsersForUID($this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset));
279
+            } else {
280
+                $batch = $this->userManager->search($pattern, $limit, $offset);
281
+            }
282
+
283
+            foreach ($batch as $user) {
284
+                if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
285
+                    ($gid === '_disabledUsers' && !$user->isEnabled())
286
+                ) {
287
+                    $userObjects[] = $user;
288
+                    $users[] = $this->formatUserForIndex($user);
289
+                }
290
+            }
291
+
292
+        } else {
293
+            $subAdminOfGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
294
+            // New class returns IGroup[] so convert back
295
+            $gids = [];
296
+            foreach ($subAdminOfGroups as $group) {
297
+                $gids[] = $group->getGID();
298
+            }
299
+            $subAdminOfGroups = $gids;
300
+
301
+            // Set the $gid parameter to an empty value if the subadmin has no rights to access a specific group
302
+            if ($gid !== '' && $gid !== '_disabledUsers' && !in_array($gid, $subAdminOfGroups)) {
303
+                $gid = '';
304
+            }
305
+
306
+            // Batch all groups the user is subadmin of when a group is specified
307
+            $batch = [];
308
+            if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
309
+                $batch = $this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset);
310
+            } else {
311
+                foreach ($subAdminOfGroups as $group) {
312
+                    $groupUsers = $this->groupManager->displayNamesInGroup($group, $pattern, $limit, $offset);
313
+
314
+                    foreach ($groupUsers as $uid => $displayName) {
315
+                        $batch[$uid] = $displayName;
316
+                    }
317
+                }
318
+            }
319
+            $batch = $this->getUsersForUID($batch);
320
+
321
+            foreach ($batch as $user) {
322
+                // Only add the groups, this user is a subadmin of
323
+                $userGroups = array_values(array_intersect(
324
+                    $this->groupManager->getUserGroupIds($user),
325
+                    $subAdminOfGroups
326
+                ));
327
+                if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
328
+                    ($gid === '_disabledUsers' && !$user->isEnabled())
329
+                ) {
330
+                    $userObjects[] = $user;
331
+                    $users[] = $this->formatUserForIndex($user, $userGroups);
332
+                }
333
+            }
334
+        }
335
+
336
+        $usedSpace = $this->userMountCache->getUsedSpaceForUsers($userObjects);
337
+
338
+        foreach ($users as &$userData) {
339
+            $userData['size'] = isset($usedSpace[$userData['name']]) ? $usedSpace[$userData['name']] : 0;
340
+        }
341
+
342
+        return new DataResponse($users);
343
+    }
344
+
345
+    /**
346
+     * @NoAdminRequired
347
+     * @PasswordConfirmationRequired
348
+     *
349
+     * @param string $username
350
+     * @param string $password
351
+     * @param array $groups
352
+     * @param string $email
353
+     * @return DataResponse
354
+     */
355
+    public function create(string $username, string $password, array $groups = [], $email = ''): DataResponse {
356
+        if ($email !== '' && !$this->mailer->validateMailAddress($email)) {
357
+            return new DataResponse(
358
+                [
359
+                    'message' => $this->l10n->t('Invalid mail address')
360
+                ],
361
+                Http::STATUS_UNPROCESSABLE_ENTITY
362
+            );
363
+        }
364
+
365
+        $currentUser = $this->userSession->getUser();
366
+
367
+        if (!$this->isAdmin) {
368
+            if (!empty($groups)) {
369
+                foreach ($groups as $key => $group) {
370
+                    $groupObject = $this->groupManager->get($group);
371
+                    if ($groupObject === null) {
372
+                        unset($groups[$key]);
373
+                        continue;
374
+                    }
375
+
376
+                    if (!$this->groupManager->getSubAdmin()->isSubAdminOfGroup($currentUser, $groupObject)) {
377
+                        unset($groups[$key]);
378
+                    }
379
+                }
380
+            }
381
+
382
+            if (empty($groups)) {
383
+                return new DataResponse(
384
+                    [
385
+                        'message' => $this->l10n->t('No valid group selected'),
386
+                    ],
387
+                    Http::STATUS_FORBIDDEN
388
+                );
389
+            }
390
+        }
391
+
392
+        if ($this->userManager->userExists($username)) {
393
+            return new DataResponse(
394
+                [
395
+                    'message' => $this->l10n->t('A user with that name already exists.')
396
+                ],
397
+                Http::STATUS_CONFLICT
398
+            );
399
+        }
400
+
401
+        $generatePasswordResetToken = false;
402
+        if ($password === '') {
403
+            if ($email === '') {
404
+                return new DataResponse(
405
+                    [
406
+                        'message' => $this->l10n->t('To send a password link to the user an email address is required.')
407
+                    ],
408
+                    Http::STATUS_UNPROCESSABLE_ENTITY
409
+                );
410
+            }
411
+
412
+            $password = $this->secureRandom->generate(30);
413
+            // Make sure we pass the password_policy
414
+            $password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
415
+            $generatePasswordResetToken = true;
416
+        }
417
+
418
+        try {
419
+            $user = $this->userManager->createUser($username, $password);
420
+        } catch (\Exception $exception) {
421
+            $message = $exception->getMessage();
422
+            if ($exception instanceof HintException && $exception->getHint()) {
423
+                $message = $exception->getHint();
424
+            }
425
+            if (!$message) {
426
+                $message = $this->l10n->t('Unable to create user.');
427
+            }
428
+            return new DataResponse(
429
+                [
430
+                    'message' => (string)$message,
431
+                ],
432
+                Http::STATUS_FORBIDDEN
433
+            );
434
+        }
435
+
436
+        if ($user instanceof IUser) {
437
+            if ($groups !== null) {
438
+                foreach ($groups as $groupName) {
439
+                    $group = $this->groupManager->get($groupName);
440
+
441
+                    if (empty($group)) {
442
+                        $group = $this->groupManager->createGroup($groupName);
443
+                    }
444
+                    $group->addUser($user);
445
+                }
446
+            }
447
+            /**
448
+             * Send new user mail only if a mail is set
449
+             */
450
+            if ($email !== '') {
451
+                $user->setEMailAddress($email);
452
+                try {
453
+                    $emailTemplate = $this->newUserMailHelper->generateTemplate($user, $generatePasswordResetToken);
454
+                    $this->newUserMailHelper->sendMail($user, $emailTemplate);
455
+                } catch (\Exception $e) {
456
+                    $this->log->logException($e, [
457
+                        'message' => "Can't send new user mail to $email",
458
+                        'level' => ILogger::ERROR,
459
+                        'app' => 'settings',
460
+                    ]);
461
+                }
462
+            }
463
+            // fetch users groups
464
+            $userGroups = $this->groupManager->getUserGroupNames($user);
465
+
466
+            return new DataResponse(
467
+                $this->formatUserForIndex($user, $userGroups),
468
+                Http::STATUS_CREATED
469
+            );
470
+        }
471
+
472
+        return new DataResponse(
473
+            [
474
+                'message' => $this->l10n->t('Unable to create user.')
475
+            ],
476
+            Http::STATUS_FORBIDDEN
477
+        );
478
+
479
+    }
480
+
481
+    /**
482
+     * @NoAdminRequired
483
+     * @PasswordConfirmationRequired
484
+     *
485
+     * @param string $id
486
+     * @return DataResponse
487
+     */
488
+    public function destroy(string $id): DataResponse {
489
+        $userId = $this->userSession->getUser()->getUID();
490
+        $user = $this->userManager->get($id);
491
+
492
+        if ($userId === $id) {
493
+            return new DataResponse(
494
+                [
495
+                    'status' => 'error',
496
+                    'data' => [
497
+                        'message' => $this->l10n->t('Unable to delete user.')
498
+                    ]
499
+                ],
500
+                Http::STATUS_FORBIDDEN
501
+            );
502
+        }
503
+
504
+        if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
505
+            return new DataResponse(
506
+                [
507
+                    'status' => 'error',
508
+                    'data' => [
509
+                        'message' => $this->l10n->t('Authentication error')
510
+                    ]
511
+                ],
512
+                Http::STATUS_FORBIDDEN
513
+            );
514
+        }
515
+
516
+        if ($user && $user->delete()) {
517
+            return new DataResponse(
518
+                [
519
+                    'status' => 'success',
520
+                    'data' => [
521
+                        'username' => $id
522
+                    ]
523
+                ],
524
+                Http::STATUS_NO_CONTENT
525
+            );
526
+        }
527
+
528
+        return new DataResponse(
529
+            [
530
+                'status' => 'error',
531
+                'data' => [
532
+                    'message' => $this->l10n->t('Unable to delete user.')
533
+                ]
534
+            ],
535
+            Http::STATUS_FORBIDDEN
536
+        );
537
+    }
538
+
539
+    /**
540
+     * @NoAdminRequired
541
+     *
542
+     * @param string $id
543
+     * @param int $enabled
544
+     * @return DataResponse
545
+     */
546
+    public function setEnabled(string $id, int $enabled): DataResponse {
547
+        $enabled = (bool)$enabled;
548
+        if ($enabled) {
549
+            $errorMsgGeneral = $this->l10n->t('Error while enabling user.');
550
+        } else {
551
+            $errorMsgGeneral = $this->l10n->t('Error while disabling user.');
552
+        }
553
+
554
+        $userId = $this->userSession->getUser()->getUID();
555
+        $user = $this->userManager->get($id);
556
+
557
+        if ($userId === $id) {
558
+            return new DataResponse(
559
+                [
560
+                    'status' => 'error',
561
+                    'data' => [
562
+                        'message' => $errorMsgGeneral
563
+                    ]
564
+                ], Http::STATUS_FORBIDDEN
565
+            );
566
+        }
567
+
568
+        if ($user) {
569
+            if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
570
+                return new DataResponse(
571
+                    [
572
+                        'status' => 'error',
573
+                        'data' => [
574
+                            'message' => $this->l10n->t('Authentication error')
575
+                        ]
576
+                    ],
577
+                    Http::STATUS_FORBIDDEN
578
+                );
579
+            }
580
+
581
+            $user->setEnabled($enabled);
582
+            return new DataResponse(
583
+                [
584
+                    'status' => 'success',
585
+                    'data' => [
586
+                        'username' => $id,
587
+                        'enabled' => $enabled
588
+                    ]
589
+                ]
590
+            );
591
+        } else {
592
+            return new DataResponse(
593
+                [
594
+                    'status' => 'error',
595
+                    'data' => [
596
+                        'message' => $errorMsgGeneral
597
+                    ]
598
+                ],
599
+                Http::STATUS_FORBIDDEN
600
+            );
601
+        }
602
+
603
+    }
604
+
605
+    /**
606
+     * Set the mail address of a user
607
+     *
608
+     * @NoAdminRequired
609
+     * @NoSubadminRequired
610
+     * @PasswordConfirmationRequired
611
+     *
612
+     * @param string $account
613
+     * @param bool $onlyVerificationCode only return verification code without updating the data
614
+     * @return DataResponse
615
+     */
616
+    public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
617
+
618
+        $user = $this->userSession->getUser();
619
+
620
+        if ($user === null) {
621
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
622
+        }
623
+
624
+        $accountData = $this->accountManager->getUser($user);
625
+        $cloudId = $user->getCloudId();
626
+        $message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
627
+        $signature = $this->signMessage($user, $message);
628
+
629
+        $code = $message . ' ' . $signature;
630
+        $codeMd5 = $message . ' ' . md5($signature);
631
+
632
+        switch ($account) {
633
+            case 'verify-twitter':
634
+                $accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
635
+                $msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
636
+                $code = $codeMd5;
637
+                $type = AccountManager::PROPERTY_TWITTER;
638
+                $data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
639
+                $accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
640
+                break;
641
+            case 'verify-website':
642
+                $accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
643
+                $msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
644
+                $type = AccountManager::PROPERTY_WEBSITE;
645
+                $data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
646
+                $accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
647
+                break;
648
+            default:
649
+                return new DataResponse([], Http::STATUS_BAD_REQUEST);
650
+        }
651
+
652
+        if ($onlyVerificationCode === false) {
653
+            $this->accountManager->updateUser($user, $accountData);
654
+
655
+            $this->jobList->add(VerifyUserData::class,
656
+                [
657
+                    'verificationCode' => $code,
658
+                    'data' => $data,
659
+                    'type' => $type,
660
+                    'uid' => $user->getUID(),
661
+                    'try' => 0,
662
+                    'lastRun' => $this->getCurrentTime()
663
+                ]
664
+            );
665
+        }
666
+
667
+        return new DataResponse(['msg' => $msg, 'code' => $code]);
668
+    }
669
+
670
+    /**
671
+     * get current timestamp
672
+     *
673
+     * @return int
674
+     */
675
+    protected function getCurrentTime(): int {
676
+        return time();
677
+    }
678
+
679
+    /**
680
+     * sign message with users private key
681
+     *
682
+     * @param IUser $user
683
+     * @param string $message
684
+     *
685
+     * @return string base64 encoded signature
686
+     */
687
+    protected function signMessage(IUser $user, string $message): string {
688
+        $privateKey = $this->keyManager->getKey($user)->getPrivate();
689
+        openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
690
+        return base64_encode($signature);
691
+    }
692
+
693
+    /**
694
+     * @NoAdminRequired
695
+     * @NoSubadminRequired
696
+     * @PasswordConfirmationRequired
697
+     *
698
+     * @param string $avatarScope
699
+     * @param string $displayname
700
+     * @param string $displaynameScope
701
+     * @param string $phone
702
+     * @param string $phoneScope
703
+     * @param string $email
704
+     * @param string $emailScope
705
+     * @param string $website
706
+     * @param string $websiteScope
707
+     * @param string $address
708
+     * @param string $addressScope
709
+     * @param string $twitter
710
+     * @param string $twitterScope
711
+     * @return DataResponse
712
+     */
713
+    public function setUserSettings($avatarScope,
714
+                                    $displayname,
715
+                                    $displaynameScope,
716
+                                    $phone,
717
+                                    $phoneScope,
718
+                                    $email,
719
+                                    $emailScope,
720
+                                    $website,
721
+                                    $websiteScope,
722
+                                    $address,
723
+                                    $addressScope,
724
+                                    $twitter,
725
+                                    $twitterScope
726
+    ) {
727
+
728
+        if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
729
+            return new DataResponse(
730
+                [
731
+                    'status' => 'error',
732
+                    'data' => [
733
+                        'message' => $this->l10n->t('Invalid mail address')
734
+                    ]
735
+                ],
736
+                Http::STATUS_UNPROCESSABLE_ENTITY
737
+            );
738
+        }
739
+
740
+        $user = $this->userSession->getUser();
741
+
742
+        $data = $this->accountManager->getUser($user);
743
+
744
+        $data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
745
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
746
+            $data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
747
+            $data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
748
+        }
749
+
750
+        if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
751
+            $federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
752
+            $shareProvider = $federatedFileSharing->getFederatedShareProvider();
753
+            if ($shareProvider->isLookupServerUploadEnabled()) {
754
+                $data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
755
+                $data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
756
+                $data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
757
+                $data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
758
+            }
759
+        }
760
+
761
+        try {
762
+            $this->saveUserSettings($user, $data);
763
+            return new DataResponse(
764
+                [
765
+                    'status' => 'success',
766
+                    'data' => [
767
+                        'userId' => $user->getUID(),
768
+                        'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
769
+                        'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
770
+                        'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
771
+                        'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
772
+                        'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
773
+                        'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
774
+                        'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
775
+                        'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
776
+                        'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
777
+                        'message' => $this->l10n->t('Settings saved')
778
+                    ]
779
+                ],
780
+                Http::STATUS_OK
781
+            );
782
+        } catch (ForbiddenException $e) {
783
+            return new DataResponse([
784
+                'status' => 'error',
785
+                'data' => [
786
+                    'message' => $e->getMessage()
787
+                ],
788
+            ]);
789
+        }
790
+
791
+    }
792
+
793
+
794
+    /**
795
+     * update account manager with new user data
796
+     *
797
+     * @param IUser $user
798
+     * @param array $data
799
+     * @throws ForbiddenException
800
+     */
801
+    protected function saveUserSettings(IUser $user, array $data) {
802
+
803
+        // keep the user back-end up-to-date with the latest display name and email
804
+        // address
805
+        $oldDisplayName = $user->getDisplayName();
806
+        $oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
807
+        if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
808
+            && $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
809
+        ) {
810
+            $result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
811
+            if ($result === false) {
812
+                throw new ForbiddenException($this->l10n->t('Unable to change full name'));
813
+            }
814
+        }
815
+
816
+        $oldEmailAddress = $user->getEMailAddress();
817
+        $oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
818
+        if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
819
+            && $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
820
+        ) {
821
+            // this is the only permission a backend provides and is also used
822
+            // for the permission of setting a email address
823
+            if (!$user->canChangeDisplayName()) {
824
+                throw new ForbiddenException($this->l10n->t('Unable to change email address'));
825
+            }
826
+            $user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
827
+        }
828
+
829
+        $this->accountManager->updateUser($user, $data);
830
+    }
831
+
832
+    /**
833
+     * Count all unique users visible for the current admin/subadmin.
834
+     *
835
+     * @NoAdminRequired
836
+     *
837
+     * @return DataResponse
838
+     */
839
+    public function stats(): DataResponse {
840
+        $userCount = 0;
841
+        if ($this->isAdmin) {
842
+            $countByBackend = $this->userManager->countUsers();
843
+
844
+            if (!empty($countByBackend)) {
845
+                foreach ($countByBackend as $count) {
846
+                    $userCount += $count;
847
+                }
848
+            }
849
+        } else {
850
+            $groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
851
+
852
+            $uniqueUsers = [];
853
+            foreach ($groups as $group) {
854
+                foreach ($group->getUsers() as $uid => $displayName) {
855
+                    $uniqueUsers[$uid] = true;
856
+                }
857
+            }
858
+
859
+            $userCount = count($uniqueUsers);
860
+        }
861
+
862
+        return new DataResponse(
863
+            [
864
+                'totalUsers' => $userCount
865
+            ]
866
+        );
867
+    }
868
+
869
+
870
+    /**
871
+     * Set the displayName of a user
872
+     *
873
+     * @NoAdminRequired
874
+     * @NoSubadminRequired
875
+     * @PasswordConfirmationRequired
876
+     * @todo merge into saveUserSettings
877
+     *
878
+     * @param string $username
879
+     * @param string $displayName
880
+     * @return DataResponse
881
+     */
882
+    public function setDisplayName(string $username, string $displayName) {
883
+        $currentUser = $this->userSession->getUser();
884
+        $user = $this->userManager->get($username);
885
+
886
+        if ($user === null ||
887
+            !$user->canChangeDisplayName() ||
888
+            (
889
+                !$this->groupManager->isAdmin($currentUser->getUID()) &&
890
+                !$this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $user) &&
891
+                $currentUser->getUID() !== $username
892
+
893
+            )
894
+        ) {
895
+            return new DataResponse([
896
+                'status' => 'error',
897
+                'data' => [
898
+                    'message' => $this->l10n->t('Authentication error'),
899
+                ],
900
+            ]);
901
+        }
902
+
903
+        $userData = $this->accountManager->getUser($user);
904
+        $userData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $displayName;
905
+
906
+
907
+        try {
908
+            $this->saveUserSettings($user, $userData);
909
+            return new DataResponse([
910
+                'status' => 'success',
911
+                'data' => [
912
+                    'message' => $this->l10n->t('Your full name has been changed.'),
913
+                    'username' => $username,
914
+                    'displayName' => $displayName,
915
+                ],
916
+            ]);
917
+        } catch (ForbiddenException $e) {
918
+            return new DataResponse([
919
+                'status' => 'error',
920
+                'data' => [
921
+                    'message' => $e->getMessage(),
922
+                    'displayName' => $user->getDisplayName(),
923
+                ],
924
+            ]);
925
+        }
926
+    }
927
+
928
+    /**
929
+     * Set the mail address of a user
930
+     *
931
+     * @NoAdminRequired
932
+     * @NoSubadminRequired
933
+     * @PasswordConfirmationRequired
934
+     *
935
+     * @param string $id
936
+     * @param string $mailAddress
937
+     * @return DataResponse
938
+     */
939
+    public function setEMailAddress(string $id, string $mailAddress) {
940
+        $user = $this->userManager->get($id);
941
+        if (!$this->isAdmin
942
+            && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)
943
+        ) {
944
+            return new DataResponse(
945
+                [
946
+                    'status' => 'error',
947
+                    'data' => [
948
+                        'message' => $this->l10n->t('Forbidden')
949
+                    ]
950
+                ],
951
+                Http::STATUS_FORBIDDEN
952
+            );
953
+        }
954
+
955
+        if ($mailAddress !== '' && !$this->mailer->validateMailAddress($mailAddress)) {
956
+            return new DataResponse(
957
+                [
958
+                    'status' => 'error',
959
+                    'data' => [
960
+                        'message' => $this->l10n->t('Invalid mail address')
961
+                    ]
962
+                ],
963
+                Http::STATUS_UNPROCESSABLE_ENTITY
964
+            );
965
+        }
966
+
967
+        if (!$user) {
968
+            return new DataResponse(
969
+                [
970
+                    'status' => 'error',
971
+                    'data' => [
972
+                        'message' => $this->l10n->t('Invalid user')
973
+                    ]
974
+                ],
975
+                Http::STATUS_UNPROCESSABLE_ENTITY
976
+            );
977
+        }
978
+        // this is the only permission a backend provides and is also used
979
+        // for the permission of setting a email address
980
+        if (!$user->canChangeDisplayName()) {
981
+            return new DataResponse(
982
+                [
983
+                    'status' => 'error',
984
+                    'data' => [
985
+                        'message' => $this->l10n->t('Unable to change mail address')
986
+                    ]
987
+                ],
988
+                Http::STATUS_FORBIDDEN
989
+            );
990
+        }
991
+
992
+        $userData = $this->accountManager->getUser($user);
993
+        $userData[AccountManager::PROPERTY_EMAIL]['value'] = $mailAddress;
994
+
995
+        try {
996
+            $this->saveUserSettings($user, $userData);
997
+            return new DataResponse(
998
+                [
999
+                    'status' => 'success',
1000
+                    'data' => [
1001
+                        'username' => $id,
1002
+                        'mailAddress' => $mailAddress,
1003
+                        'message' => $this->l10n->t('Email saved')
1004
+                    ]
1005
+                ],
1006
+                Http::STATUS_OK
1007
+            );
1008
+        } catch (ForbiddenException $e) {
1009
+            return new DataResponse([
1010
+                'status' => 'error',
1011
+                'data' => [
1012
+                    'message' => $e->getMessage()
1013
+                ],
1014
+            ]);
1015
+        }
1016
+    }
1017 1017
 
1018 1018
 }
Please login to merge, or discard this patch.
lib/private/Log/File.php 2 patches
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -48,159 +48,159 @@
 block discarded – undo
48 48
  */
49 49
 
50 50
 class File implements IWriter, IFileBased {
51
-	/** @var string */
52
-	protected $logFile;
53
-	/** @var IConfig */
54
-	private $config;
51
+    /** @var string */
52
+    protected $logFile;
53
+    /** @var IConfig */
54
+    private $config;
55 55
 
56
-	public function __construct(string $path, string $fallbackPath = '', IConfig $config) {
57
-		$this->logFile = $path;
58
-		if (!file_exists($this->logFile)) {
59
-			if(
60
-				(
61
-					!is_writable(dirname($this->logFile))
62
-					|| !touch($this->logFile)
63
-				)
64
-				&& $fallbackPath !== ''
65
-			) {
66
-				$this->logFile = $fallbackPath;
67
-			}
68
-		}
69
-		$this->config = $config;
70
-	}
56
+    public function __construct(string $path, string $fallbackPath = '', IConfig $config) {
57
+        $this->logFile = $path;
58
+        if (!file_exists($this->logFile)) {
59
+            if(
60
+                (
61
+                    !is_writable(dirname($this->logFile))
62
+                    || !touch($this->logFile)
63
+                )
64
+                && $fallbackPath !== ''
65
+            ) {
66
+                $this->logFile = $fallbackPath;
67
+            }
68
+        }
69
+        $this->config = $config;
70
+    }
71 71
 
72
-	/**
73
-	 * write a message in the log
74
-	 * @param string $app
75
-	 * @param string|array $message
76
-	 * @param int $level
77
-	 */
78
-	public function write(string $app, $message, int $level) {
79
-		// default to ISO8601
80
-		$format = $this->config->getSystemValue('logdateformat', \DateTime::ATOM);
81
-		$logTimeZone = $this->config->getSystemValue('logtimezone', 'UTC');
82
-		try {
83
-			$timezone = new \DateTimeZone($logTimeZone);
84
-		} catch (\Exception $e) {
85
-			$timezone = new \DateTimeZone('UTC');
86
-		}
87
-		$time = \DateTime::createFromFormat("U.u", number_format(microtime(true), 4, ".", ""));
88
-		if ($time === false) {
89
-			$time = new \DateTime(null, $timezone);
90
-		} else {
91
-			// apply timezone if $time is created from UNIX timestamp
92
-			$time->setTimezone($timezone);
93
-		}
94
-		$request = \OC::$server->getRequest();
95
-		$reqId = $request->getId();
96
-		$remoteAddr = $request->getRemoteAddress();
97
-		// remove username/passwords from URLs before writing the to the log file
98
-		$time = $time->format($format);
99
-		$url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
100
-		$method = is_string($request->getMethod()) ? $request->getMethod() : '--';
101
-		if($this->config->getSystemValue('installed', false)) {
102
-			$user = \OC_User::getUser() ? \OC_User::getUser() : '--';
103
-		} else {
104
-			$user = '--';
105
-		}
106
-		$userAgent = $request->getHeader('User-Agent');
107
-		if ($userAgent === '') {
108
-			$userAgent = '--';
109
-		}
110
-		$version = $this->config->getSystemValue('version', '');
111
-		$entry = compact(
112
-			'reqId',
113
-			'level',
114
-			'time',
115
-			'remoteAddr',
116
-			'user',
117
-			'app',
118
-			'method',
119
-			'url',
120
-			'message',
121
-			'userAgent',
122
-			'version'
123
-		);
124
-		// PHP's json_encode only accept proper UTF-8 strings, loop over all
125
-		// elements to ensure that they are properly UTF-8 compliant or convert
126
-		// them manually.
127
-		foreach($entry as $key => $value) {
128
-			if(is_string($value)) {
129
-				$testEncode = json_encode($value);
130
-				if($testEncode === false) {
131
-					$entry[$key] = utf8_encode($value);
132
-				}
133
-			}
134
-		}
135
-		$entry = json_encode($entry, JSON_PARTIAL_OUTPUT_ON_ERROR);
136
-		$handle = @fopen($this->logFile, 'a');
137
-		if ((fileperms($this->logFile) & 0777) != 0640) {
138
-			@chmod($this->logFile, 0640);
139
-		}
140
-		if ($handle) {
141
-			fwrite($handle, $entry."\n");
142
-			fclose($handle);
143
-		} else {
144
-			// Fall back to error_log
145
-			error_log($entry);
146
-		}
147
-		if (php_sapi_name() === 'cli-server') {
148
-			error_log($message, 4);
149
-		}
150
-	}
72
+    /**
73
+     * write a message in the log
74
+     * @param string $app
75
+     * @param string|array $message
76
+     * @param int $level
77
+     */
78
+    public function write(string $app, $message, int $level) {
79
+        // default to ISO8601
80
+        $format = $this->config->getSystemValue('logdateformat', \DateTime::ATOM);
81
+        $logTimeZone = $this->config->getSystemValue('logtimezone', 'UTC');
82
+        try {
83
+            $timezone = new \DateTimeZone($logTimeZone);
84
+        } catch (\Exception $e) {
85
+            $timezone = new \DateTimeZone('UTC');
86
+        }
87
+        $time = \DateTime::createFromFormat("U.u", number_format(microtime(true), 4, ".", ""));
88
+        if ($time === false) {
89
+            $time = new \DateTime(null, $timezone);
90
+        } else {
91
+            // apply timezone if $time is created from UNIX timestamp
92
+            $time->setTimezone($timezone);
93
+        }
94
+        $request = \OC::$server->getRequest();
95
+        $reqId = $request->getId();
96
+        $remoteAddr = $request->getRemoteAddress();
97
+        // remove username/passwords from URLs before writing the to the log file
98
+        $time = $time->format($format);
99
+        $url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
100
+        $method = is_string($request->getMethod()) ? $request->getMethod() : '--';
101
+        if($this->config->getSystemValue('installed', false)) {
102
+            $user = \OC_User::getUser() ? \OC_User::getUser() : '--';
103
+        } else {
104
+            $user = '--';
105
+        }
106
+        $userAgent = $request->getHeader('User-Agent');
107
+        if ($userAgent === '') {
108
+            $userAgent = '--';
109
+        }
110
+        $version = $this->config->getSystemValue('version', '');
111
+        $entry = compact(
112
+            'reqId',
113
+            'level',
114
+            'time',
115
+            'remoteAddr',
116
+            'user',
117
+            'app',
118
+            'method',
119
+            'url',
120
+            'message',
121
+            'userAgent',
122
+            'version'
123
+        );
124
+        // PHP's json_encode only accept proper UTF-8 strings, loop over all
125
+        // elements to ensure that they are properly UTF-8 compliant or convert
126
+        // them manually.
127
+        foreach($entry as $key => $value) {
128
+            if(is_string($value)) {
129
+                $testEncode = json_encode($value);
130
+                if($testEncode === false) {
131
+                    $entry[$key] = utf8_encode($value);
132
+                }
133
+            }
134
+        }
135
+        $entry = json_encode($entry, JSON_PARTIAL_OUTPUT_ON_ERROR);
136
+        $handle = @fopen($this->logFile, 'a');
137
+        if ((fileperms($this->logFile) & 0777) != 0640) {
138
+            @chmod($this->logFile, 0640);
139
+        }
140
+        if ($handle) {
141
+            fwrite($handle, $entry."\n");
142
+            fclose($handle);
143
+        } else {
144
+            // Fall back to error_log
145
+            error_log($entry);
146
+        }
147
+        if (php_sapi_name() === 'cli-server') {
148
+            error_log($message, 4);
149
+        }
150
+    }
151 151
 
152
-	/**
153
-	 * get entries from the log in reverse chronological order
154
-	 * @param int $limit
155
-	 * @param int $offset
156
-	 * @return array
157
-	 */
158
-	public function getEntries(int $limit=50, int $offset=0):array {
159
-		$minLevel = $this->config->getSystemValue("loglevel", ILogger::WARN);
160
-		$entries = array();
161
-		$handle = @fopen($this->logFile, 'rb');
162
-		if ($handle) {
163
-			fseek($handle, 0, SEEK_END);
164
-			$pos = ftell($handle);
165
-			$line = '';
166
-			$entriesCount = 0;
167
-			$lines = 0;
168
-			// Loop through each character of the file looking for new lines
169
-			while ($pos >= 0 && ($limit === null ||$entriesCount < $limit)) {
170
-				fseek($handle, $pos);
171
-				$ch = fgetc($handle);
172
-				if ($ch == "\n" || $pos == 0) {
173
-					if ($line != '') {
174
-						// Add the first character if at the start of the file,
175
-						// because it doesn't hit the else in the loop
176
-						if ($pos == 0) {
177
-							$line = $ch.$line;
178
-						}
179
-						$entry = json_decode($line);
180
-						// Add the line as an entry if it is passed the offset and is equal or above the log level
181
-						if ($entry->level >= $minLevel) {
182
-							$lines++;
183
-							if ($lines > $offset) {
184
-								$entries[] = $entry;
185
-								$entriesCount++;
186
-							}
187
-						}
188
-						$line = '';
189
-					}
190
-				} else {
191
-					$line = $ch.$line;
192
-				}
193
-				$pos--;
194
-			}
195
-			fclose($handle);
196
-		}
197
-		return $entries;
198
-	}
152
+    /**
153
+     * get entries from the log in reverse chronological order
154
+     * @param int $limit
155
+     * @param int $offset
156
+     * @return array
157
+     */
158
+    public function getEntries(int $limit=50, int $offset=0):array {
159
+        $minLevel = $this->config->getSystemValue("loglevel", ILogger::WARN);
160
+        $entries = array();
161
+        $handle = @fopen($this->logFile, 'rb');
162
+        if ($handle) {
163
+            fseek($handle, 0, SEEK_END);
164
+            $pos = ftell($handle);
165
+            $line = '';
166
+            $entriesCount = 0;
167
+            $lines = 0;
168
+            // Loop through each character of the file looking for new lines
169
+            while ($pos >= 0 && ($limit === null ||$entriesCount < $limit)) {
170
+                fseek($handle, $pos);
171
+                $ch = fgetc($handle);
172
+                if ($ch == "\n" || $pos == 0) {
173
+                    if ($line != '') {
174
+                        // Add the first character if at the start of the file,
175
+                        // because it doesn't hit the else in the loop
176
+                        if ($pos == 0) {
177
+                            $line = $ch.$line;
178
+                        }
179
+                        $entry = json_decode($line);
180
+                        // Add the line as an entry if it is passed the offset and is equal or above the log level
181
+                        if ($entry->level >= $minLevel) {
182
+                            $lines++;
183
+                            if ($lines > $offset) {
184
+                                $entries[] = $entry;
185
+                                $entriesCount++;
186
+                            }
187
+                        }
188
+                        $line = '';
189
+                    }
190
+                } else {
191
+                    $line = $ch.$line;
192
+                }
193
+                $pos--;
194
+            }
195
+            fclose($handle);
196
+        }
197
+        return $entries;
198
+    }
199 199
 
200
-	/**
201
-	 * @return string
202
-	 */
203
-	public function getLogFilePath():string {
204
-		return $this->logFile;
205
-	}
200
+    /**
201
+     * @return string
202
+     */
203
+    public function getLogFilePath():string {
204
+        return $this->logFile;
205
+    }
206 206
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -56,7 +56,7 @@  discard block
 block discarded – undo
56 56
 	public function __construct(string $path, string $fallbackPath = '', IConfig $config) {
57 57
 		$this->logFile = $path;
58 58
 		if (!file_exists($this->logFile)) {
59
-			if(
59
+			if (
60 60
 				(
61 61
 					!is_writable(dirname($this->logFile))
62 62
 					|| !touch($this->logFile)
@@ -98,7 +98,7 @@  discard block
 block discarded – undo
98 98
 		$time = $time->format($format);
99 99
 		$url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
100 100
 		$method = is_string($request->getMethod()) ? $request->getMethod() : '--';
101
-		if($this->config->getSystemValue('installed', false)) {
101
+		if ($this->config->getSystemValue('installed', false)) {
102 102
 			$user = \OC_User::getUser() ? \OC_User::getUser() : '--';
103 103
 		} else {
104 104
 			$user = '--';
@@ -124,10 +124,10 @@  discard block
 block discarded – undo
124 124
 		// PHP's json_encode only accept proper UTF-8 strings, loop over all
125 125
 		// elements to ensure that they are properly UTF-8 compliant or convert
126 126
 		// them manually.
127
-		foreach($entry as $key => $value) {
128
-			if(is_string($value)) {
127
+		foreach ($entry as $key => $value) {
128
+			if (is_string($value)) {
129 129
 				$testEncode = json_encode($value);
130
-				if($testEncode === false) {
130
+				if ($testEncode === false) {
131 131
 					$entry[$key] = utf8_encode($value);
132 132
 				}
133 133
 			}
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
 	 * @param int $offset
156 156
 	 * @return array
157 157
 	 */
158
-	public function getEntries(int $limit=50, int $offset=0):array {
158
+	public function getEntries(int $limit = 50, int $offset = 0):array {
159 159
 		$minLevel = $this->config->getSystemValue("loglevel", ILogger::WARN);
160 160
 		$entries = array();
161 161
 		$handle = @fopen($this->logFile, 'rb');
@@ -166,7 +166,7 @@  discard block
 block discarded – undo
166 166
 			$entriesCount = 0;
167 167
 			$lines = 0;
168 168
 			// Loop through each character of the file looking for new lines
169
-			while ($pos >= 0 && ($limit === null ||$entriesCount < $limit)) {
169
+			while ($pos >= 0 && ($limit === null || $entriesCount < $limit)) {
170 170
 				fseek($handle, $pos);
171 171
 				$ch = fgetc($handle);
172 172
 				if ($ch == "\n" || $pos == 0) {
Please login to merge, or discard this patch.
lib/public/Log/IFileBased.php 2 patches
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -31,13 +31,13 @@
 block discarded – undo
31 31
  * @since 14.0.0
32 32
  */
33 33
 interface IFileBased {
34
-	/**
35
-	 * @since 14.0.0
36
-	 */
37
-	public function getLogFilePath():string;
34
+    /**
35
+     * @since 14.0.0
36
+     */
37
+    public function getLogFilePath():string;
38 38
 
39
-	/**
40
-	 * @since 14.0.0
41
-	 */
42
-	public function getEntries(int $limit=50, int $offset=0): array;
39
+    /**
40
+     * @since 14.0.0
41
+     */
42
+    public function getEntries(int $limit=50, int $offset=0): array;
43 43
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -39,5 +39,5 @@
 block discarded – undo
39 39
 	/**
40 40
 	 * @since 14.0.0
41 41
 	 */
42
-	public function getEntries(int $limit=50, int $offset=0): array;
42
+	public function getEntries(int $limit = 50, int $offset = 0): array;
43 43
 }
Please login to merge, or discard this patch.
apps/federation/lib/BackgroundJob/GetSharedSecret.php 2 patches
Indentation   +174 added lines, -174 removed lines patch added patch discarded remove patch
@@ -55,203 +55,203 @@
 block discarded – undo
55 55
  */
56 56
 class GetSharedSecret extends Job {
57 57
 
58
-	/** @var IClient */
59
-	private $httpClient;
58
+    /** @var IClient */
59
+    private $httpClient;
60 60
 
61
-	/** @var IJobList */
62
-	private $jobList;
61
+    /** @var IJobList */
62
+    private $jobList;
63 63
 
64
-	/** @var IURLGenerator */
65
-	private $urlGenerator;
64
+    /** @var IURLGenerator */
65
+    private $urlGenerator;
66 66
 
67
-	/** @var TrustedServers  */
68
-	private $trustedServers;
67
+    /** @var TrustedServers  */
68
+    private $trustedServers;
69 69
 
70
-	/** @var IDiscoveryService  */
71
-	private $ocsDiscoveryService;
70
+    /** @var IDiscoveryService  */
71
+    private $ocsDiscoveryService;
72 72
 
73
-	/** @var ILogger */
74
-	private $logger;
73
+    /** @var ILogger */
74
+    private $logger;
75 75
 
76
-	/** @var ITimeFactory */
77
-	private $timeFactory;
76
+    /** @var ITimeFactory */
77
+    private $timeFactory;
78 78
 
79
-	/** @var bool */
80
-	protected $retainJob = false;
79
+    /** @var bool */
80
+    protected $retainJob = false;
81 81
 
82
-	private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';
82
+    private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';
83 83
 
84
-	/** @var  int  30 day = 2592000sec */
85
-	private $maxLifespan = 2592000;
84
+    /** @var  int  30 day = 2592000sec */
85
+    private $maxLifespan = 2592000;
86 86
 
87
-	/**
88
-	 * RequestSharedSecret constructor.
89
-	 *
90
-	 * @param IClientService $httpClientService
91
-	 * @param IURLGenerator $urlGenerator
92
-	 * @param IJobList $jobList
93
-	 * @param TrustedServers $trustedServers
94
-	 * @param ILogger $logger
95
-	 * @param IDiscoveryService $ocsDiscoveryService
96
-	 * @param ITimeFactory $timeFactory
97
-	 */
98
-	public function __construct(
99
-		IClientService $httpClientService,
100
-		IURLGenerator $urlGenerator,
101
-		IJobList $jobList,
102
-		TrustedServers $trustedServers,
103
-		ILogger $logger,
104
-		IDiscoveryService $ocsDiscoveryService,
105
-		ITimeFactory $timeFactory
106
-	) {
107
-		$this->logger = $logger;
108
-		$this->httpClient = $httpClientService->newClient();
109
-		$this->jobList = $jobList;
110
-		$this->urlGenerator = $urlGenerator;
111
-		$this->ocsDiscoveryService = $ocsDiscoveryService;
112
-		$this->trustedServers = $trustedServers;
113
-		$this->timeFactory = $timeFactory;
114
-	}
87
+    /**
88
+     * RequestSharedSecret constructor.
89
+     *
90
+     * @param IClientService $httpClientService
91
+     * @param IURLGenerator $urlGenerator
92
+     * @param IJobList $jobList
93
+     * @param TrustedServers $trustedServers
94
+     * @param ILogger $logger
95
+     * @param IDiscoveryService $ocsDiscoveryService
96
+     * @param ITimeFactory $timeFactory
97
+     */
98
+    public function __construct(
99
+        IClientService $httpClientService,
100
+        IURLGenerator $urlGenerator,
101
+        IJobList $jobList,
102
+        TrustedServers $trustedServers,
103
+        ILogger $logger,
104
+        IDiscoveryService $ocsDiscoveryService,
105
+        ITimeFactory $timeFactory
106
+    ) {
107
+        $this->logger = $logger;
108
+        $this->httpClient = $httpClientService->newClient();
109
+        $this->jobList = $jobList;
110
+        $this->urlGenerator = $urlGenerator;
111
+        $this->ocsDiscoveryService = $ocsDiscoveryService;
112
+        $this->trustedServers = $trustedServers;
113
+        $this->timeFactory = $timeFactory;
114
+    }
115 115
 
116
-	/**
117
-	 * run the job, then remove it from the joblist
118
-	 *
119
-	 * @param JobList $jobList
120
-	 * @param ILogger|null $logger
121
-	 */
122
-	public function execute($jobList, ILogger $logger = null) {
123
-		$target = $this->argument['url'];
124
-		// only execute if target is still in the list of trusted domains
125
-		if ($this->trustedServers->isTrustedServer($target)) {
126
-			$this->parentExecute($jobList, $logger);
127
-		}
116
+    /**
117
+     * run the job, then remove it from the joblist
118
+     *
119
+     * @param JobList $jobList
120
+     * @param ILogger|null $logger
121
+     */
122
+    public function execute($jobList, ILogger $logger = null) {
123
+        $target = $this->argument['url'];
124
+        // only execute if target is still in the list of trusted domains
125
+        if ($this->trustedServers->isTrustedServer($target)) {
126
+            $this->parentExecute($jobList, $logger);
127
+        }
128 128
 
129
-		$jobList->remove($this, $this->argument);
129
+        $jobList->remove($this, $this->argument);
130 130
 
131
-		if ($this->retainJob) {
132
-			$this->reAddJob($this->argument);
133
-		}
134
-	}
131
+        if ($this->retainJob) {
132
+            $this->reAddJob($this->argument);
133
+        }
134
+    }
135 135
 
136
-	/**
137
-	 * call execute() method of parent
138
-	 *
139
-	 * @param JobList $jobList
140
-	 * @param ILogger $logger
141
-	 */
142
-	protected function parentExecute($jobList, $logger = null) {
143
-		parent::execute($jobList, $logger);
144
-	}
136
+    /**
137
+     * call execute() method of parent
138
+     *
139
+     * @param JobList $jobList
140
+     * @param ILogger $logger
141
+     */
142
+    protected function parentExecute($jobList, $logger = null) {
143
+        parent::execute($jobList, $logger);
144
+    }
145 145
 
146
-	protected function run($argument) {
147
-		$target = $argument['url'];
148
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
149
-		$currentTime = $this->timeFactory->getTime();
150
-		$source = $this->urlGenerator->getAbsoluteURL('/');
151
-		$source = rtrim($source, '/');
152
-		$token = $argument['token'];
146
+    protected function run($argument) {
147
+        $target = $argument['url'];
148
+        $created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
149
+        $currentTime = $this->timeFactory->getTime();
150
+        $source = $this->urlGenerator->getAbsoluteURL('/');
151
+        $source = rtrim($source, '/');
152
+        $token = $argument['token'];
153 153
 
154
-		// kill job after 30 days of trying
155
-		$deadline = $currentTime - $this->maxLifespan;
156
-		if ($created < $deadline) {
157
-			$this->retainJob = false;
158
-			$this->trustedServers->setServerStatus($target,TrustedServers::STATUS_FAILURE);
159
-			return;
160
-		}
154
+        // kill job after 30 days of trying
155
+        $deadline = $currentTime - $this->maxLifespan;
156
+        if ($created < $deadline) {
157
+            $this->retainJob = false;
158
+            $this->trustedServers->setServerStatus($target,TrustedServers::STATUS_FAILURE);
159
+            return;
160
+        }
161 161
 
162
-		$endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
163
-		$endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
162
+        $endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
163
+        $endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
164 164
 
165
-		// make sure that we have a well formatted url
166
-		$url = rtrim($target, '/') . '/' . trim($endPoint, '/');
165
+        // make sure that we have a well formatted url
166
+        $url = rtrim($target, '/') . '/' . trim($endPoint, '/');
167 167
 
168
-		$result = null;
169
-		try {
170
-			$result = $this->httpClient->get(
171
-				$url,
172
-				[
173
-					'query' =>
174
-						[
175
-							'url' => $source,
176
-							'token' => $token,
177
-							'format' => 'json',
178
-						],
179
-					'timeout' => 3,
180
-					'connect_timeout' => 3,
181
-				]
182
-			);
168
+        $result = null;
169
+        try {
170
+            $result = $this->httpClient->get(
171
+                $url,
172
+                [
173
+                    'query' =>
174
+                        [
175
+                            'url' => $source,
176
+                            'token' => $token,
177
+                            'format' => 'json',
178
+                        ],
179
+                    'timeout' => 3,
180
+                    'connect_timeout' => 3,
181
+                ]
182
+            );
183 183
 
184
-			$status = $result->getStatusCode();
184
+            $status = $result->getStatusCode();
185 185
 
186
-		} catch (ClientException $e) {
187
-			$status = $e->getCode();
188
-			if ($status === Http::STATUS_FORBIDDEN) {
189
-				$this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
190
-			} else {
191
-				$this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage(), ['app' => 'federation']);
192
-			}
193
-		} catch (RequestException $e) {
194
-			$status = -1; // There is no status code if we could not connect
195
-			$this->logger->logException($e, [
196
-				'message' => 'Could not connect to ' . $target,
197
-				'level' => ILogger::INFO,
198
-				'app' => 'federation',
199
-			]);
200
-		} catch (RingException $e) {
201
-			$status = -1; // There is no status code if we could not connect
202
-			$this->logger->logException($e, [
203
-				'message' => 'Could not connect to ' . $target,
204
-				'level' => ILogger::INFO,
205
-				'app' => 'federation',
206
-			]);
207
-		} catch (\Exception $e) {
208
-			$status = Http::STATUS_INTERNAL_SERVER_ERROR;
209
-			$this->logger->logException($e, ['app' => 'federation']);
210
-		}
186
+        } catch (ClientException $e) {
187
+            $status = $e->getCode();
188
+            if ($status === Http::STATUS_FORBIDDEN) {
189
+                $this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
190
+            } else {
191
+                $this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage(), ['app' => 'federation']);
192
+            }
193
+        } catch (RequestException $e) {
194
+            $status = -1; // There is no status code if we could not connect
195
+            $this->logger->logException($e, [
196
+                'message' => 'Could not connect to ' . $target,
197
+                'level' => ILogger::INFO,
198
+                'app' => 'federation',
199
+            ]);
200
+        } catch (RingException $e) {
201
+            $status = -1; // There is no status code if we could not connect
202
+            $this->logger->logException($e, [
203
+                'message' => 'Could not connect to ' . $target,
204
+                'level' => ILogger::INFO,
205
+                'app' => 'federation',
206
+            ]);
207
+        } catch (\Exception $e) {
208
+            $status = Http::STATUS_INTERNAL_SERVER_ERROR;
209
+            $this->logger->logException($e, ['app' => 'federation']);
210
+        }
211 211
 
212
-		// if we received a unexpected response we try again later
213
-		if (
214
-			$status !== Http::STATUS_OK
215
-			&& $status !== Http::STATUS_FORBIDDEN
216
-		) {
217
-			$this->retainJob = true;
218
-		}
212
+        // if we received a unexpected response we try again later
213
+        if (
214
+            $status !== Http::STATUS_OK
215
+            && $status !== Http::STATUS_FORBIDDEN
216
+        ) {
217
+            $this->retainJob = true;
218
+        }
219 219
 
220
-		if ($status === Http::STATUS_OK && $result instanceof IResponse) {
221
-			$body = $result->getBody();
222
-			$result = json_decode($body, true);
223
-			if (isset($result['ocs']['data']['sharedSecret'])) {
224
-				$this->trustedServers->addSharedSecret(
225
-						$target,
226
-						$result['ocs']['data']['sharedSecret']
227
-				);
228
-			} else {
229
-				$this->logger->error(
230
-						'remote server "' . $target . '"" does not return a valid shared secret. Received data: ' . $body,
231
-						['app' => 'federation']
232
-				);
233
-				$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
234
-			}
235
-		}
220
+        if ($status === Http::STATUS_OK && $result instanceof IResponse) {
221
+            $body = $result->getBody();
222
+            $result = json_decode($body, true);
223
+            if (isset($result['ocs']['data']['sharedSecret'])) {
224
+                $this->trustedServers->addSharedSecret(
225
+                        $target,
226
+                        $result['ocs']['data']['sharedSecret']
227
+                );
228
+            } else {
229
+                $this->logger->error(
230
+                        'remote server "' . $target . '"" does not return a valid shared secret. Received data: ' . $body,
231
+                        ['app' => 'federation']
232
+                );
233
+                $this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
234
+            }
235
+        }
236 236
 
237
-	}
237
+    }
238 238
 
239
-	/**
240
-	 * re-add background job
241
-	 *
242
-	 * @param array $argument
243
-	 */
244
-	protected function reAddJob(array $argument) {
245
-		$url = $argument['url'];
246
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
247
-		$token = $argument['token'];
248
-		$this->jobList->add(
249
-			GetSharedSecret::class,
250
-			[
251
-				'url' => $url,
252
-				'token' => $token,
253
-				'created' => $created
254
-			]
255
-		);
256
-	}
239
+    /**
240
+     * re-add background job
241
+     *
242
+     * @param array $argument
243
+     */
244
+    protected function reAddJob(array $argument) {
245
+        $url = $argument['url'];
246
+        $created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
247
+        $token = $argument['token'];
248
+        $this->jobList->add(
249
+            GetSharedSecret::class,
250
+            [
251
+                'url' => $url,
252
+                'token' => $token,
253
+                'created' => $created
254
+            ]
255
+        );
256
+    }
257 257
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
 
146 146
 	protected function run($argument) {
147 147
 		$target = $argument['url'];
148
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
148
+		$created = isset($argument['created']) ? (int) $argument['created'] : $this->timeFactory->getTime();
149 149
 		$currentTime = $this->timeFactory->getTime();
150 150
 		$source = $this->urlGenerator->getAbsoluteURL('/');
151 151
 		$source = rtrim($source, '/');
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
 		$deadline = $currentTime - $this->maxLifespan;
156 156
 		if ($created < $deadline) {
157 157
 			$this->retainJob = false;
158
-			$this->trustedServers->setServerStatus($target,TrustedServers::STATUS_FAILURE);
158
+			$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
159 159
 			return;
160 160
 		}
161 161
 
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
 		$endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
164 164
 
165 165
 		// make sure that we have a well formatted url
166
-		$url = rtrim($target, '/') . '/' . trim($endPoint, '/');
166
+		$url = rtrim($target, '/').'/'.trim($endPoint, '/');
167 167
 
168 168
 		$result = null;
169 169
 		try {
@@ -186,21 +186,21 @@  discard block
 block discarded – undo
186 186
 		} catch (ClientException $e) {
187 187
 			$status = $e->getCode();
188 188
 			if ($status === Http::STATUS_FORBIDDEN) {
189
-				$this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
189
+				$this->logger->info($target.' refused to exchange a shared secret with you.', ['app' => 'federation']);
190 190
 			} else {
191
-				$this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage(), ['app' => 'federation']);
191
+				$this->logger->info($target.' responded with a '.$status.' containing: '.$e->getMessage(), ['app' => 'federation']);
192 192
 			}
193 193
 		} catch (RequestException $e) {
194 194
 			$status = -1; // There is no status code if we could not connect
195 195
 			$this->logger->logException($e, [
196
-				'message' => 'Could not connect to ' . $target,
196
+				'message' => 'Could not connect to '.$target,
197 197
 				'level' => ILogger::INFO,
198 198
 				'app' => 'federation',
199 199
 			]);
200 200
 		} catch (RingException $e) {
201 201
 			$status = -1; // There is no status code if we could not connect
202 202
 			$this->logger->logException($e, [
203
-				'message' => 'Could not connect to ' . $target,
203
+				'message' => 'Could not connect to '.$target,
204 204
 				'level' => ILogger::INFO,
205 205
 				'app' => 'federation',
206 206
 			]);
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
 				);
228 228
 			} else {
229 229
 				$this->logger->error(
230
-						'remote server "' . $target . '"" does not return a valid shared secret. Received data: ' . $body,
230
+						'remote server "'.$target.'"" does not return a valid shared secret. Received data: '.$body,
231 231
 						['app' => 'federation']
232 232
 				);
233 233
 				$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
 	 */
244 244
 	protected function reAddJob(array $argument) {
245 245
 		$url = $argument['url'];
246
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
246
+		$created = isset($argument['created']) ? (int) $argument['created'] : $this->timeFactory->getTime();
247 247
 		$token = $argument['token'];
248 248
 		$this->jobList->add(
249 249
 			GetSharedSecret::class,
Please login to merge, or discard this patch.
lib/private/Log/Rotate.php 2 patches
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -33,17 +33,17 @@
 block discarded – undo
33 33
  * location and manage that with your own tools.
34 34
  */
35 35
 class Rotate extends \OC\BackgroundJob\Job {
36
-	use RotationTrait;
36
+    use RotationTrait;
37 37
 
38
-	public function run($dummy) {
39
-		$systemConfig = \OC::$server->getSystemConfig();
40
-		$this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
38
+    public function run($dummy) {
39
+        $systemConfig = \OC::$server->getSystemConfig();
40
+        $this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
41 41
 
42
-		$this->maxSize = \OC::$server->getConfig()->getSystemValue('log_rotate_size', 100 * 1024 * 1024);
43
-		if($this->shouldRotateBySize()) {
44
-			$rotatedFile = $this->rotate();
45
-			$msg = 'Log file "'.$this->filePath.'" was over '.$this->maxSize.' bytes, moved to "'.$rotatedFile.'"';
46
-			\OC::$server->getLogger()->warning($msg, ['app' => Rotate::class]);
47
-		}
48
-	}
42
+        $this->maxSize = \OC::$server->getConfig()->getSystemValue('log_rotate_size', 100 * 1024 * 1024);
43
+        if($this->shouldRotateBySize()) {
44
+            $rotatedFile = $this->rotate();
45
+            $msg = 'Log file "'.$this->filePath.'" was over '.$this->maxSize.' bytes, moved to "'.$rotatedFile.'"';
46
+            \OC::$server->getLogger()->warning($msg, ['app' => Rotate::class]);
47
+        }
48
+    }
49 49
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -37,10 +37,10 @@
 block discarded – undo
37 37
 
38 38
 	public function run($dummy) {
39 39
 		$systemConfig = \OC::$server->getSystemConfig();
40
-		$this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
40
+		$this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT.'/data').'/nextcloud.log');
41 41
 
42 42
 		$this->maxSize = \OC::$server->getConfig()->getSystemValue('log_rotate_size', 100 * 1024 * 1024);
43
-		if($this->shouldRotateBySize()) {
43
+		if ($this->shouldRotateBySize()) {
44 44
 			$rotatedFile = $this->rotate();
45 45
 			$msg = 'Log file "'.$this->filePath.'" was over '.$this->maxSize.' bytes, moved to "'.$rotatedFile.'"';
46 46
 			\OC::$server->getLogger()->warning($msg, ['app' => Rotate::class]);
Please login to merge, or discard this patch.