Completed
Pull Request — master (#4539)
by Morris
12:28
created
lib/private/legacy/user.php 1 patch
Indentation   +561 added lines, -562 removed lines patch added patch discarded remove patch
@@ -57,566 +57,565 @@
 block discarded – undo
57 57
  */
58 58
 class OC_User {
59 59
 
60
-	/**
61
-	 * @return \OC\User\Session
62
-	 */
63
-	public static function getUserSession() {
64
-		return OC::$server->getUserSession();
65
-	}
66
-
67
-	private static $_usedBackends = array();
68
-
69
-	private static $_setupedBackends = array();
70
-
71
-	// bool, stores if a user want to access a resource anonymously, e.g if they open a public link
72
-	private static $incognitoMode = false;
73
-
74
-	/**
75
-	 * Adds the backend to the list of used backends
76
-	 *
77
-	 * @param string|\OCP\UserInterface $backend default: database The backend to use for user management
78
-	 * @return bool
79
-	 *
80
-	 * Set the User Authentication Module
81
-	 */
82
-	public static function useBackend($backend = 'database') {
83
-		if ($backend instanceof \OCP\UserInterface) {
84
-			self::$_usedBackends[get_class($backend)] = $backend;
85
-			\OC::$server->getUserManager()->registerBackend($backend);
86
-		} else {
87
-			// You'll never know what happens
88
-			if (null === $backend OR !is_string($backend)) {
89
-				$backend = 'database';
90
-			}
91
-
92
-			// Load backend
93
-			switch ($backend) {
94
-				case 'database':
95
-				case 'mysql':
96
-				case 'sqlite':
97
-					\OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', \OCP\Util::DEBUG);
98
-					self::$_usedBackends[$backend] = new \OC\User\Database();
99
-					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
100
-					break;
101
-				case 'dummy':
102
-					self::$_usedBackends[$backend] = new \Test\Util\User\Dummy();
103
-					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
104
-					break;
105
-				default:
106
-					\OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', \OCP\Util::DEBUG);
107
-					$className = 'OC_USER_' . strtoupper($backend);
108
-					self::$_usedBackends[$backend] = new $className();
109
-					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
110
-					break;
111
-			}
112
-		}
113
-		return true;
114
-	}
115
-
116
-	/**
117
-	 * remove all used backends
118
-	 */
119
-	public static function clearBackends() {
120
-		self::$_usedBackends = array();
121
-		\OC::$server->getUserManager()->clearBackends();
122
-	}
123
-
124
-	/**
125
-	 * setup the configured backends in config.php
126
-	 */
127
-	public static function setupBackends() {
128
-		OC_App::loadApps(['prelogin']);
129
-		$backends = \OC::$server->getSystemConfig()->getValue('user_backends', []);
130
-		if (isset($backends['default']) && !$backends['default']) {
131
-			// clear default backends
132
-			self::clearBackends();
133
-		}
134
-		foreach ($backends as $i => $config) {
135
-			if (!is_array($config)) {
136
-				continue;
137
-			}
138
-			$class = $config['class'];
139
-			$arguments = $config['arguments'];
140
-			if (class_exists($class)) {
141
-				if (array_search($i, self::$_setupedBackends) === false) {
142
-					// make a reflection object
143
-					$reflectionObj = new ReflectionClass($class);
144
-
145
-					// use Reflection to create a new instance, using the $args
146
-					$backend = $reflectionObj->newInstanceArgs($arguments);
147
-					self::useBackend($backend);
148
-					self::$_setupedBackends[] = $i;
149
-				} else {
150
-					\OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', \OCP\Util::DEBUG);
151
-				}
152
-			} else {
153
-				\OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', \OCP\Util::ERROR);
154
-			}
155
-		}
156
-	}
157
-
158
-	/**
159
-
160
-	 * Try to login a user using the magic cookie (remember login)
161
-	 *
162
-	 * @deprecated use \OCP\IUserSession::loginWithCookie()
163
-	 * @param string $uid The username of the user to log in
164
-	 * @param string $token
165
-	 * @param string $oldSessionId
166
-	 * @return bool
167
-	 */
168
-	public static function loginWithCookie($uid, $token, $oldSessionId) {
169
-		return self::getUserSession()->loginWithCookie($uid, $token, $oldSessionId);
170
-	}
171
-
172
-	/**
173
-	 * Try to login a user, assuming authentication
174
-	 * has already happened (e.g. via Single Sign On).
175
-	 *
176
-	 * Log in a user and regenerate a new session.
177
-	 *
178
-	 * @param \OCP\Authentication\IApacheBackend $backend
179
-	 * @return bool
180
-	 */
181
-	public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
182
-
183
-		$uid = $backend->getCurrentUserId();
184
-		$run = true;
185
-		OC_Hook::emit("OC_User", "pre_login", array("run" => &$run, "uid" => $uid));
186
-
187
-		if ($uid) {
188
-			if (self::getUser() !== $uid) {
189
-				self::setUserId($uid);
190
-				$setUidAsDisplayName = true;
191
-				if($backend instanceof \OCP\UserInterface
192
-					&& $backend->implementsActions(OC_User_Backend::GET_DISPLAYNAME)) {
193
-
194
-					$backendDisplayName = $backend->getDisplayName($uid);
195
-					if(is_string($backendDisplayName) && trim($backendDisplayName) !== '') {
196
-						$setUidAsDisplayName = false;
197
-					}
198
-				}
199
-				if($setUidAsDisplayName) {
200
-					self::setDisplayName($uid);
201
-				}
202
-				$userSession = self::getUserSession();
203
-				$userSession->getSession()->regenerateId();
204
-				$userSession->setLoginName($uid);
205
-				$request = OC::$server->getRequest();
206
-				$userSession->createSessionToken($request, $uid, $uid);
207
-				// setup the filesystem
208
-				OC_Util::setupFS($uid);
209
-				// first call the post_login hooks, the login-process needs to be
210
-				// completed before we can safely create the users folder.
211
-				// For example encryption needs to initialize the users keys first
212
-				// before we can create the user folder with the skeleton files
213
-				OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => ''));
214
-				//trigger creation of user home and /files folder
215
-				\OC::$server->getUserFolder($uid);
216
-			}
217
-			return true;
218
-		}
219
-		return false;
220
-	}
221
-
222
-	/**
223
-	 * Verify with Apache whether user is authenticated.
224
-	 *
225
-	 * @return boolean|null
226
-	 *          true: authenticated
227
-	 *          false: not authenticated
228
-	 *          null: not handled / no backend available
229
-	 */
230
-	public static function handleApacheAuth() {
231
-		$backend = self::findFirstActiveUsedBackend();
232
-		if ($backend) {
233
-			OC_App::loadApps();
234
-
235
-			//setup extra user backends
236
-			self::setupBackends();
237
-			self::unsetMagicInCookie();
238
-
239
-			return self::loginWithApache($backend);
240
-		}
241
-
242
-		return null;
243
-	}
244
-
245
-
246
-	/**
247
-	 * Sets user id for session and triggers emit
248
-	 *
249
-	 * @param string $uid
250
-	 */
251
-	public static function setUserId($uid) {
252
-		$userSession = \OC::$server->getUserSession();
253
-		$userManager = \OC::$server->getUserManager();
254
-		if ($user = $userManager->get($uid)) {
255
-			$userSession->setUser($user);
256
-		} else {
257
-			\OC::$server->getSession()->set('user_id', $uid);
258
-		}
259
-	}
260
-
261
-	/**
262
-	 * Sets user display name for session
263
-	 *
264
-	 * @param string $uid
265
-	 * @param string $displayName
266
-	 * @return bool Whether the display name could get set
267
-	 */
268
-	public static function setDisplayName($uid, $displayName = null) {
269
-		if (is_null($displayName)) {
270
-			$displayName = $uid;
271
-		}
272
-		$user = \OC::$server->getUserManager()->get($uid);
273
-		if ($user) {
274
-			return $user->setDisplayName($displayName);
275
-		} else {
276
-			return false;
277
-		}
278
-	}
279
-
280
-	/**
281
-	 * Check if the user is logged in, considers also the HTTP basic credentials
282
-	 *
283
-	 * @deprecated use \OC::$server->getUserSession()->isLoggedIn()
284
-	 * @return bool
285
-	 */
286
-	public static function isLoggedIn() {
287
-		return \OC::$server->getUserSession()->isLoggedIn();
288
-	}
289
-
290
-	/**
291
-	 * set incognito mode, e.g. if a user wants to open a public link
292
-	 *
293
-	 * @param bool $status
294
-	 */
295
-	public static function setIncognitoMode($status) {
296
-		self::$incognitoMode = $status;
297
-	}
298
-
299
-	/**
300
-	 * get incognito mode status
301
-	 *
302
-	 * @return bool
303
-	 */
304
-	public static function isIncognitoMode() {
305
-		return self::$incognitoMode;
306
-	}
307
-
308
-	/**
309
-	 * Supplies an attribute to the logout hyperlink. The default behaviour
310
-	 * is to return an href with '?logout=true' appended. However, it can
311
-	 * supply any attribute(s) which are valid for <a>.
312
-	 *
313
-	 * @return string with one or more HTML attributes.
314
-	 */
315
-	public static function getLogoutAttribute() {
316
-		$backend = self::findFirstActiveUsedBackend();
317
-		if ($backend) {
318
-			return $backend->getLogoutAttribute();
319
-		}
320
-
321
-		$logoutUrl = \OC::$server->getURLGenerator()->linkToRouteAbsolute(
322
-			'core.login.logout',
323
-			[
324
-				'requesttoken' => \OCP\Util::callRegister(),
325
-			]
326
-		);
327
-
328
-		return 'href="'.$logoutUrl.'"';
329
-	}
330
-
331
-	/**
332
-	 * Check if the user is an admin user
333
-	 *
334
-	 * @param string $uid uid of the admin
335
-	 * @return bool
336
-	 */
337
-	public static function isAdminUser($uid) {
338
-		$group = \OC::$server->getGroupManager()->get('admin');
339
-		$user = \OC::$server->getUserManager()->get($uid);
340
-		if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) {
341
-			return true;
342
-		}
343
-		return false;
344
-	}
345
-
346
-
347
-	/**
348
-	 * get the user id of the user currently logged in.
349
-	 *
350
-	 * @return string|bool uid or false
351
-	 */
352
-	public static function getUser() {
353
-		$uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
354
-		if (!is_null($uid) && self::$incognitoMode === false) {
355
-			return $uid;
356
-		} else {
357
-			return false;
358
-		}
359
-	}
360
-
361
-	/**
362
-	 * get the display name of the user currently logged in.
363
-	 *
364
-	 * @param string $uid
365
-	 * @return string uid or false
366
-	 */
367
-	public static function getDisplayName($uid = null) {
368
-		if ($uid) {
369
-			$user = \OC::$server->getUserManager()->get($uid);
370
-			if ($user) {
371
-				return $user->getDisplayName();
372
-			} else {
373
-				return $uid;
374
-			}
375
-		} else {
376
-			$user = self::getUserSession()->getUser();
377
-			if ($user) {
378
-				return $user->getDisplayName();
379
-			} else {
380
-				return false;
381
-			}
382
-		}
383
-	}
384
-
385
-	/**
386
-	 * Autogenerate a password
387
-	 *
388
-	 * @return string
389
-	 *
390
-	 * generates a password
391
-	 */
392
-	public static function generatePassword() {
393
-		return \OC::$server->getSecureRandom()->generate(30);
394
-	}
395
-
396
-	/**
397
-	 * Set password
398
-	 *
399
-	 * @param string $uid The username
400
-	 * @param string $password The new password
401
-	 * @param string $recoveryPassword for the encryption app to reset encryption keys
402
-	 * @return bool
403
-	 *
404
-	 * Change the password of a user
405
-	 */
406
-	public static function setPassword($uid, $password, $recoveryPassword = null) {
407
-		$user = \OC::$server->getUserManager()->get($uid);
408
-		if ($user) {
409
-			return $user->setPassword($password, $recoveryPassword);
410
-		} else {
411
-			return false;
412
-		}
413
-	}
414
-
415
-	/**
416
-	 * Check whether user can change his avatar
417
-	 *
418
-	 * @param string $uid The username
419
-	 * @return bool
420
-	 *
421
-	 * Check whether a specified user can change his avatar
422
-	 */
423
-	public static function canUserChangeAvatar($uid) {
424
-		$user = \OC::$server->getUserManager()->get($uid);
425
-		if ($user) {
426
-			return $user->canChangeAvatar();
427
-		} else {
428
-			return false;
429
-		}
430
-	}
431
-
432
-	/**
433
-	 * Check whether user can change his password
434
-	 *
435
-	 * @param string $uid The username
436
-	 * @return bool
437
-	 *
438
-	 * Check whether a specified user can change his password
439
-	 */
440
-	public static function canUserChangePassword($uid) {
441
-		$user = \OC::$server->getUserManager()->get($uid);
442
-		if ($user) {
443
-			return $user->canChangePassword();
444
-		} else {
445
-			return false;
446
-		}
447
-	}
448
-
449
-	/**
450
-	 * Check whether user can change his display name
451
-	 *
452
-	 * @param string $uid The username
453
-	 * @return bool
454
-	 *
455
-	 * Check whether a specified user can change his display name
456
-	 */
457
-	public static function canUserChangeDisplayName($uid) {
458
-		$user = \OC::$server->getUserManager()->get($uid);
459
-		if ($user) {
460
-			return $user->canChangeDisplayName();
461
-		} else {
462
-			return false;
463
-		}
464
-	}
465
-
466
-	/**
467
-	 * Check if the password is correct
468
-	 *
469
-	 * @param string $uid The username
470
-	 * @param string $password The password
471
-	 * @return string|false user id a string on success, false otherwise
472
-	 *
473
-	 * Check if the password is correct without logging in the user
474
-	 * returns the user id or false
475
-	 */
476
-	public static function checkPassword($uid, $password) {
477
-		$manager = \OC::$server->getUserManager();
478
-		$username = $manager->checkPassword($uid, $password);
479
-		if ($username !== false) {
480
-			return $username->getUID();
481
-		}
482
-		return false;
483
-	}
484
-
485
-	/**
486
-	 * @param string $uid The username
487
-	 * @return string
488
-	 *
489
-	 * returns the path to the users home directory
490
-	 * @deprecated Use \OC::$server->getUserManager->getHome()
491
-	 */
492
-	public static function getHome($uid) {
493
-		$user = \OC::$server->getUserManager()->get($uid);
494
-		if ($user) {
495
-			return $user->getHome();
496
-		} else {
497
-			return \OC::$server->getSystemConfig()->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
498
-		}
499
-	}
500
-
501
-	/**
502
-	 * Get a list of all users
503
-	 *
504
-	 * @return array an array of all uids
505
-	 *
506
-	 * Get a list of all users.
507
-	 * @param string $search
508
-	 * @param integer $limit
509
-	 * @param integer $offset
510
-	 */
511
-	public static function getUsers($search = '', $limit = null, $offset = null) {
512
-		$users = \OC::$server->getUserManager()->search($search, $limit, $offset);
513
-		$uids = array();
514
-		foreach ($users as $user) {
515
-			$uids[] = $user->getUID();
516
-		}
517
-		return $uids;
518
-	}
519
-
520
-	/**
521
-	 * Get a list of all users display name
522
-	 *
523
-	 * @param string $search
524
-	 * @param int $limit
525
-	 * @param int $offset
526
-	 * @return array associative array with all display names (value) and corresponding uids (key)
527
-	 *
528
-	 * Get a list of all display names and user ids.
529
-	 * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
530
-	 */
531
-	public static function getDisplayNames($search = '', $limit = null, $offset = null) {
532
-		$displayNames = array();
533
-		$users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset);
534
-		foreach ($users as $user) {
535
-			$displayNames[$user->getUID()] = $user->getDisplayName();
536
-		}
537
-		return $displayNames;
538
-	}
539
-
540
-	/**
541
-	 * check if a user exists
542
-	 *
543
-	 * @param string $uid the username
544
-	 * @return boolean
545
-	 */
546
-	public static function userExists($uid) {
547
-		return \OC::$server->getUserManager()->userExists($uid);
548
-	}
549
-
550
-	/**
551
-	 * disables a user
552
-	 *
553
-	 * @param string $uid the user to disable
554
-	 */
555
-	public static function disableUser($uid) {
556
-		$user = \OC::$server->getUserManager()->get($uid);
557
-		if ($user) {
558
-			$user->setEnabled(false);
559
-		}
560
-	}
561
-
562
-	/**
563
-	 * enable a user
564
-	 *
565
-	 * @param string $uid
566
-	 */
567
-	public static function enableUser($uid) {
568
-		$user = \OC::$server->getUserManager()->get($uid);
569
-		if ($user) {
570
-			$user->setEnabled(true);
571
-		}
572
-	}
573
-
574
-	/**
575
-	 * checks if a user is enabled
576
-	 *
577
-	 * @param string $uid
578
-	 * @return bool
579
-	 */
580
-	public static function isEnabled($uid) {
581
-		$user = \OC::$server->getUserManager()->get($uid);
582
-		if ($user) {
583
-			return $user->isEnabled();
584
-		} else {
585
-			return false;
586
-		}
587
-	}
588
-
589
-	/**
590
-	 * Set cookie value to use in next page load
591
-	 *
592
-	 * @param string $username username to be set
593
-	 * @param string $token
594
-	 */
595
-	public static function setMagicInCookie($username, $token) {
596
-		self::getUserSession()->setMagicInCookie($username, $token);
597
-	}
598
-
599
-	/**
600
-	 * Remove cookie for "remember username"
601
-	 */
602
-	public static function unsetMagicInCookie() {
603
-		self::getUserSession()->unsetMagicInCookie();
604
-	}
605
-
606
-	/**
607
-	 * Returns the first active backend from self::$_usedBackends.
608
-	 *
609
-	 * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
610
-	 */
611
-	private static function findFirstActiveUsedBackend() {
612
-		foreach (self::$_usedBackends as $backend) {
613
-			if ($backend instanceof OCP\Authentication\IApacheBackend) {
614
-				if ($backend->isSessionActive()) {
615
-					return $backend;
616
-				}
617
-			}
618
-		}
619
-
620
-		return null;
621
-	}
60
+    /**
61
+     * @return \OC\User\Session
62
+     */
63
+    public static function getUserSession() {
64
+        return OC::$server->getUserSession();
65
+    }
66
+
67
+    private static $_usedBackends = array();
68
+
69
+    private static $_setupedBackends = array();
70
+
71
+    // bool, stores if a user want to access a resource anonymously, e.g if they open a public link
72
+    private static $incognitoMode = false;
73
+
74
+    /**
75
+     * Adds the backend to the list of used backends
76
+     *
77
+     * @param string|\OCP\UserInterface $backend default: database The backend to use for user management
78
+     * @return bool
79
+     *
80
+     * Set the User Authentication Module
81
+     */
82
+    public static function useBackend($backend = 'database') {
83
+        if ($backend instanceof \OCP\UserInterface) {
84
+            self::$_usedBackends[get_class($backend)] = $backend;
85
+            \OC::$server->getUserManager()->registerBackend($backend);
86
+        } else {
87
+            // You'll never know what happens
88
+            if (null === $backend OR !is_string($backend)) {
89
+                $backend = 'database';
90
+            }
91
+
92
+            // Load backend
93
+            switch ($backend) {
94
+                case 'database':
95
+                case 'mysql':
96
+                case 'sqlite':
97
+                    \OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', \OCP\Util::DEBUG);
98
+                    self::$_usedBackends[$backend] = new \OC\User\Database();
99
+                    \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
100
+                    break;
101
+                case 'dummy':
102
+                    self::$_usedBackends[$backend] = new \Test\Util\User\Dummy();
103
+                    \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
104
+                    break;
105
+                default:
106
+                    \OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', \OCP\Util::DEBUG);
107
+                    $className = 'OC_USER_' . strtoupper($backend);
108
+                    self::$_usedBackends[$backend] = new $className();
109
+                    \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
110
+                    break;
111
+            }
112
+        }
113
+        return true;
114
+    }
115
+
116
+    /**
117
+     * remove all used backends
118
+     */
119
+    public static function clearBackends() {
120
+        self::$_usedBackends = array();
121
+        \OC::$server->getUserManager()->clearBackends();
122
+    }
123
+
124
+    /**
125
+     * setup the configured backends in config.php
126
+     */
127
+    public static function setupBackends() {
128
+        OC_App::loadApps(['prelogin']);
129
+        $backends = \OC::$server->getSystemConfig()->getValue('user_backends', []);
130
+        if (isset($backends['default']) && !$backends['default']) {
131
+            // clear default backends
132
+            self::clearBackends();
133
+        }
134
+        foreach ($backends as $i => $config) {
135
+            if (!is_array($config)) {
136
+                continue;
137
+            }
138
+            $class = $config['class'];
139
+            $arguments = $config['arguments'];
140
+            if (class_exists($class)) {
141
+                if (array_search($i, self::$_setupedBackends) === false) {
142
+                    // make a reflection object
143
+                    $reflectionObj = new ReflectionClass($class);
144
+
145
+                    // use Reflection to create a new instance, using the $args
146
+                    $backend = $reflectionObj->newInstanceArgs($arguments);
147
+                    self::useBackend($backend);
148
+                    self::$_setupedBackends[] = $i;
149
+                } else {
150
+                    \OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', \OCP\Util::DEBUG);
151
+                }
152
+            } else {
153
+                \OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', \OCP\Util::ERROR);
154
+            }
155
+        }
156
+    }
157
+
158
+    /**
159
+     * Try to login a user using the magic cookie (remember login)
160
+     *
161
+     * @deprecated use \OCP\IUserSession::loginWithCookie()
162
+     * @param string $uid The username of the user to log in
163
+     * @param string $token
164
+     * @param string $oldSessionId
165
+     * @return bool
166
+     */
167
+    public static function loginWithCookie($uid, $token, $oldSessionId) {
168
+        return self::getUserSession()->loginWithCookie($uid, $token, $oldSessionId);
169
+    }
170
+
171
+    /**
172
+     * Try to login a user, assuming authentication
173
+     * has already happened (e.g. via Single Sign On).
174
+     *
175
+     * Log in a user and regenerate a new session.
176
+     *
177
+     * @param \OCP\Authentication\IApacheBackend $backend
178
+     * @return bool
179
+     */
180
+    public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
181
+
182
+        $uid = $backend->getCurrentUserId();
183
+        $run = true;
184
+        OC_Hook::emit("OC_User", "pre_login", array("run" => &$run, "uid" => $uid));
185
+
186
+        if ($uid) {
187
+            if (self::getUser() !== $uid) {
188
+                self::setUserId($uid);
189
+                $setUidAsDisplayName = true;
190
+                if($backend instanceof \OCP\UserInterface
191
+                    && $backend->implementsActions(OC_User_Backend::GET_DISPLAYNAME)) {
192
+
193
+                    $backendDisplayName = $backend->getDisplayName($uid);
194
+                    if(is_string($backendDisplayName) && trim($backendDisplayName) !== '') {
195
+                        $setUidAsDisplayName = false;
196
+                    }
197
+                }
198
+                if($setUidAsDisplayName) {
199
+                    self::setDisplayName($uid);
200
+                }
201
+                $userSession = self::getUserSession();
202
+                $userSession->getSession()->regenerateId();
203
+                $userSession->setLoginName($uid);
204
+                $request = OC::$server->getRequest();
205
+                $userSession->createSessionToken($request, $uid, $uid);
206
+                // setup the filesystem
207
+                OC_Util::setupFS($uid);
208
+                // first call the post_login hooks, the login-process needs to be
209
+                // completed before we can safely create the users folder.
210
+                // For example encryption needs to initialize the users keys first
211
+                // before we can create the user folder with the skeleton files
212
+                OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => ''));
213
+                //trigger creation of user home and /files folder
214
+                \OC::$server->getUserFolder($uid);
215
+            }
216
+            return true;
217
+        }
218
+        return false;
219
+    }
220
+
221
+    /**
222
+     * Verify with Apache whether user is authenticated.
223
+     *
224
+     * @return boolean|null
225
+     *          true: authenticated
226
+     *          false: not authenticated
227
+     *          null: not handled / no backend available
228
+     */
229
+    public static function handleApacheAuth() {
230
+        $backend = self::findFirstActiveUsedBackend();
231
+        if ($backend) {
232
+            OC_App::loadApps();
233
+
234
+            //setup extra user backends
235
+            self::setupBackends();
236
+            self::unsetMagicInCookie();
237
+
238
+            return self::loginWithApache($backend);
239
+        }
240
+
241
+        return null;
242
+    }
243
+
244
+
245
+    /**
246
+     * Sets user id for session and triggers emit
247
+     *
248
+     * @param string $uid
249
+     */
250
+    public static function setUserId($uid) {
251
+        $userSession = \OC::$server->getUserSession();
252
+        $userManager = \OC::$server->getUserManager();
253
+        if ($user = $userManager->get($uid)) {
254
+            $userSession->setUser($user);
255
+        } else {
256
+            \OC::$server->getSession()->set('user_id', $uid);
257
+        }
258
+    }
259
+
260
+    /**
261
+     * Sets user display name for session
262
+     *
263
+     * @param string $uid
264
+     * @param string $displayName
265
+     * @return bool Whether the display name could get set
266
+     */
267
+    public static function setDisplayName($uid, $displayName = null) {
268
+        if (is_null($displayName)) {
269
+            $displayName = $uid;
270
+        }
271
+        $user = \OC::$server->getUserManager()->get($uid);
272
+        if ($user) {
273
+            return $user->setDisplayName($displayName);
274
+        } else {
275
+            return false;
276
+        }
277
+    }
278
+
279
+    /**
280
+     * Check if the user is logged in, considers also the HTTP basic credentials
281
+     *
282
+     * @deprecated use \OC::$server->getUserSession()->isLoggedIn()
283
+     * @return bool
284
+     */
285
+    public static function isLoggedIn() {
286
+        return \OC::$server->getUserSession()->isLoggedIn();
287
+    }
288
+
289
+    /**
290
+     * set incognito mode, e.g. if a user wants to open a public link
291
+     *
292
+     * @param bool $status
293
+     */
294
+    public static function setIncognitoMode($status) {
295
+        self::$incognitoMode = $status;
296
+    }
297
+
298
+    /**
299
+     * get incognito mode status
300
+     *
301
+     * @return bool
302
+     */
303
+    public static function isIncognitoMode() {
304
+        return self::$incognitoMode;
305
+    }
306
+
307
+    /**
308
+     * Supplies an attribute to the logout hyperlink. The default behaviour
309
+     * is to return an href with '?logout=true' appended. However, it can
310
+     * supply any attribute(s) which are valid for <a>.
311
+     *
312
+     * @return string with one or more HTML attributes.
313
+     */
314
+    public static function getLogoutAttribute() {
315
+        $backend = self::findFirstActiveUsedBackend();
316
+        if ($backend) {
317
+            return $backend->getLogoutAttribute();
318
+        }
319
+
320
+        $logoutUrl = \OC::$server->getURLGenerator()->linkToRouteAbsolute(
321
+            'core.login.logout',
322
+            [
323
+                'requesttoken' => \OCP\Util::callRegister(),
324
+            ]
325
+        );
326
+
327
+        return 'href="'.$logoutUrl.'"';
328
+    }
329
+
330
+    /**
331
+     * Check if the user is an admin user
332
+     *
333
+     * @param string $uid uid of the admin
334
+     * @return bool
335
+     */
336
+    public static function isAdminUser($uid) {
337
+        $group = \OC::$server->getGroupManager()->get('admin');
338
+        $user = \OC::$server->getUserManager()->get($uid);
339
+        if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) {
340
+            return true;
341
+        }
342
+        return false;
343
+    }
344
+
345
+
346
+    /**
347
+     * get the user id of the user currently logged in.
348
+     *
349
+     * @return string|bool uid or false
350
+     */
351
+    public static function getUser() {
352
+        $uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
353
+        if (!is_null($uid) && self::$incognitoMode === false) {
354
+            return $uid;
355
+        } else {
356
+            return false;
357
+        }
358
+    }
359
+
360
+    /**
361
+     * get the display name of the user currently logged in.
362
+     *
363
+     * @param string $uid
364
+     * @return string uid or false
365
+     */
366
+    public static function getDisplayName($uid = null) {
367
+        if ($uid) {
368
+            $user = \OC::$server->getUserManager()->get($uid);
369
+            if ($user) {
370
+                return $user->getDisplayName();
371
+            } else {
372
+                return $uid;
373
+            }
374
+        } else {
375
+            $user = self::getUserSession()->getUser();
376
+            if ($user) {
377
+                return $user->getDisplayName();
378
+            } else {
379
+                return false;
380
+            }
381
+        }
382
+    }
383
+
384
+    /**
385
+     * Autogenerate a password
386
+     *
387
+     * @return string
388
+     *
389
+     * generates a password
390
+     */
391
+    public static function generatePassword() {
392
+        return \OC::$server->getSecureRandom()->generate(30);
393
+    }
394
+
395
+    /**
396
+     * Set password
397
+     *
398
+     * @param string $uid The username
399
+     * @param string $password The new password
400
+     * @param string $recoveryPassword for the encryption app to reset encryption keys
401
+     * @return bool
402
+     *
403
+     * Change the password of a user
404
+     */
405
+    public static function setPassword($uid, $password, $recoveryPassword = null) {
406
+        $user = \OC::$server->getUserManager()->get($uid);
407
+        if ($user) {
408
+            return $user->setPassword($password, $recoveryPassword);
409
+        } else {
410
+            return false;
411
+        }
412
+    }
413
+
414
+    /**
415
+     * Check whether user can change his avatar
416
+     *
417
+     * @param string $uid The username
418
+     * @return bool
419
+     *
420
+     * Check whether a specified user can change his avatar
421
+     */
422
+    public static function canUserChangeAvatar($uid) {
423
+        $user = \OC::$server->getUserManager()->get($uid);
424
+        if ($user) {
425
+            return $user->canChangeAvatar();
426
+        } else {
427
+            return false;
428
+        }
429
+    }
430
+
431
+    /**
432
+     * Check whether user can change his password
433
+     *
434
+     * @param string $uid The username
435
+     * @return bool
436
+     *
437
+     * Check whether a specified user can change his password
438
+     */
439
+    public static function canUserChangePassword($uid) {
440
+        $user = \OC::$server->getUserManager()->get($uid);
441
+        if ($user) {
442
+            return $user->canChangePassword();
443
+        } else {
444
+            return false;
445
+        }
446
+    }
447
+
448
+    /**
449
+     * Check whether user can change his display name
450
+     *
451
+     * @param string $uid The username
452
+     * @return bool
453
+     *
454
+     * Check whether a specified user can change his display name
455
+     */
456
+    public static function canUserChangeDisplayName($uid) {
457
+        $user = \OC::$server->getUserManager()->get($uid);
458
+        if ($user) {
459
+            return $user->canChangeDisplayName();
460
+        } else {
461
+            return false;
462
+        }
463
+    }
464
+
465
+    /**
466
+     * Check if the password is correct
467
+     *
468
+     * @param string $uid The username
469
+     * @param string $password The password
470
+     * @return string|false user id a string on success, false otherwise
471
+     *
472
+     * Check if the password is correct without logging in the user
473
+     * returns the user id or false
474
+     */
475
+    public static function checkPassword($uid, $password) {
476
+        $manager = \OC::$server->getUserManager();
477
+        $username = $manager->checkPassword($uid, $password);
478
+        if ($username !== false) {
479
+            return $username->getUID();
480
+        }
481
+        return false;
482
+    }
483
+
484
+    /**
485
+     * @param string $uid The username
486
+     * @return string
487
+     *
488
+     * returns the path to the users home directory
489
+     * @deprecated Use \OC::$server->getUserManager->getHome()
490
+     */
491
+    public static function getHome($uid) {
492
+        $user = \OC::$server->getUserManager()->get($uid);
493
+        if ($user) {
494
+            return $user->getHome();
495
+        } else {
496
+            return \OC::$server->getSystemConfig()->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
497
+        }
498
+    }
499
+
500
+    /**
501
+     * Get a list of all users
502
+     *
503
+     * @return array an array of all uids
504
+     *
505
+     * Get a list of all users.
506
+     * @param string $search
507
+     * @param integer $limit
508
+     * @param integer $offset
509
+     */
510
+    public static function getUsers($search = '', $limit = null, $offset = null) {
511
+        $users = \OC::$server->getUserManager()->search($search, $limit, $offset);
512
+        $uids = array();
513
+        foreach ($users as $user) {
514
+            $uids[] = $user->getUID();
515
+        }
516
+        return $uids;
517
+    }
518
+
519
+    /**
520
+     * Get a list of all users display name
521
+     *
522
+     * @param string $search
523
+     * @param int $limit
524
+     * @param int $offset
525
+     * @return array associative array with all display names (value) and corresponding uids (key)
526
+     *
527
+     * Get a list of all display names and user ids.
528
+     * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
529
+     */
530
+    public static function getDisplayNames($search = '', $limit = null, $offset = null) {
531
+        $displayNames = array();
532
+        $users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset);
533
+        foreach ($users as $user) {
534
+            $displayNames[$user->getUID()] = $user->getDisplayName();
535
+        }
536
+        return $displayNames;
537
+    }
538
+
539
+    /**
540
+     * check if a user exists
541
+     *
542
+     * @param string $uid the username
543
+     * @return boolean
544
+     */
545
+    public static function userExists($uid) {
546
+        return \OC::$server->getUserManager()->userExists($uid);
547
+    }
548
+
549
+    /**
550
+     * disables a user
551
+     *
552
+     * @param string $uid the user to disable
553
+     */
554
+    public static function disableUser($uid) {
555
+        $user = \OC::$server->getUserManager()->get($uid);
556
+        if ($user) {
557
+            $user->setEnabled(false);
558
+        }
559
+    }
560
+
561
+    /**
562
+     * enable a user
563
+     *
564
+     * @param string $uid
565
+     */
566
+    public static function enableUser($uid) {
567
+        $user = \OC::$server->getUserManager()->get($uid);
568
+        if ($user) {
569
+            $user->setEnabled(true);
570
+        }
571
+    }
572
+
573
+    /**
574
+     * checks if a user is enabled
575
+     *
576
+     * @param string $uid
577
+     * @return bool
578
+     */
579
+    public static function isEnabled($uid) {
580
+        $user = \OC::$server->getUserManager()->get($uid);
581
+        if ($user) {
582
+            return $user->isEnabled();
583
+        } else {
584
+            return false;
585
+        }
586
+    }
587
+
588
+    /**
589
+     * Set cookie value to use in next page load
590
+     *
591
+     * @param string $username username to be set
592
+     * @param string $token
593
+     */
594
+    public static function setMagicInCookie($username, $token) {
595
+        self::getUserSession()->setMagicInCookie($username, $token);
596
+    }
597
+
598
+    /**
599
+     * Remove cookie for "remember username"
600
+     */
601
+    public static function unsetMagicInCookie() {
602
+        self::getUserSession()->unsetMagicInCookie();
603
+    }
604
+
605
+    /**
606
+     * Returns the first active backend from self::$_usedBackends.
607
+     *
608
+     * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
609
+     */
610
+    private static function findFirstActiveUsedBackend() {
611
+        foreach (self::$_usedBackends as $backend) {
612
+            if ($backend instanceof OCP\Authentication\IApacheBackend) {
613
+                if ($backend->isSessionActive()) {
614
+                    return $backend;
615
+                }
616
+            }
617
+        }
618
+
619
+        return null;
620
+    }
622 621
 }
Please login to merge, or discard this patch.
lib/private/legacy/api.php 1 patch
Indentation   +460 added lines, -460 removed lines patch added patch discarded remove patch
@@ -37,464 +37,464 @@
 block discarded – undo
37 37
 
38 38
 class OC_API {
39 39
 
40
-	/**
41
-	 * API authentication levels
42
-	 */
43
-
44
-	/** @deprecated Use \OCP\API::GUEST_AUTH instead */
45
-	const GUEST_AUTH = 0;
46
-
47
-	/** @deprecated Use \OCP\API::USER_AUTH instead */
48
-	const USER_AUTH = 1;
49
-
50
-	/** @deprecated Use \OCP\API::SUBADMIN_AUTH instead */
51
-	const SUBADMIN_AUTH = 2;
52
-
53
-	/** @deprecated Use \OCP\API::ADMIN_AUTH instead */
54
-	const ADMIN_AUTH = 3;
55
-
56
-	/**
57
-	 * API Response Codes
58
-	 */
59
-
60
-	/** @deprecated Use \OCP\API::RESPOND_UNAUTHORISED instead */
61
-	const RESPOND_UNAUTHORISED = 997;
62
-
63
-	/** @deprecated Use \OCP\API::RESPOND_SERVER_ERROR instead */
64
-	const RESPOND_SERVER_ERROR = 996;
65
-
66
-	/** @deprecated Use \OCP\API::RESPOND_NOT_FOUND instead */
67
-	const RESPOND_NOT_FOUND = 998;
68
-
69
-	/** @deprecated Use \OCP\API::RESPOND_UNKNOWN_ERROR instead */
70
-	const RESPOND_UNKNOWN_ERROR = 999;
71
-
72
-	/**
73
-	 * api actions
74
-	 */
75
-	protected static $actions = array();
76
-	private static $logoutRequired = false;
77
-	private static $isLoggedIn = false;
78
-
79
-	/**
80
-	 * registers an api call
81
-	 * @param string $method the http method
82
-	 * @param string $url the url to match
83
-	 * @param callable $action the function to run
84
-	 * @param string $app the id of the app registering the call
85
-	 * @param int $authLevel the level of authentication required for the call
86
-	 * @param array $defaults
87
-	 * @param array $requirements
88
-	 */
89
-	public static function register($method, $url, $action, $app,
90
-				$authLevel = API::USER_AUTH,
91
-				$defaults = array(),
92
-				$requirements = array()) {
93
-		$name = strtolower($method).$url;
94
-		$name = str_replace(array('/', '{', '}'), '_', $name);
95
-		if(!isset(self::$actions[$name])) {
96
-			$oldCollection = OC::$server->getRouter()->getCurrentCollection();
97
-			OC::$server->getRouter()->useCollection('ocs');
98
-			OC::$server->getRouter()->create($name, $url)
99
-				->method($method)
100
-				->defaults($defaults)
101
-				->requirements($requirements)
102
-				->action('OC_API', 'call');
103
-			self::$actions[$name] = array();
104
-			OC::$server->getRouter()->useCollection($oldCollection);
105
-		}
106
-		self::$actions[$name][] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel);
107
-	}
108
-
109
-	/**
110
-	 * handles an api call
111
-	 * @param array $parameters
112
-	 */
113
-	public static function call($parameters) {
114
-		$request = \OC::$server->getRequest();
115
-		$method = $request->getMethod();
116
-
117
-		// Prepare the request variables
118
-		if($method === 'PUT') {
119
-			$parameters['_put'] = $request->getParams();
120
-		} else if($method === 'DELETE') {
121
-			$parameters['_delete'] = $request->getParams();
122
-		}
123
-		$name = $parameters['_route'];
124
-		// Foreach registered action
125
-		$responses = array();
126
-		foreach(self::$actions[$name] as $action) {
127
-			// Check authentication and availability
128
-			if(!self::isAuthorised($action)) {
129
-				$responses[] = array(
130
-					'app' => $action['app'],
131
-					'response' => new OC_OCS_Result(null, API::RESPOND_UNAUTHORISED, 'Unauthorised'),
132
-					'shipped' => OC_App::isShipped($action['app']),
133
-					);
134
-				continue;
135
-			}
136
-			if(!is_callable($action['action'])) {
137
-				$responses[] = array(
138
-					'app' => $action['app'],
139
-					'response' => new OC_OCS_Result(null, API::RESPOND_NOT_FOUND, 'Api method not found'),
140
-					'shipped' => OC_App::isShipped($action['app']),
141
-					);
142
-				continue;
143
-			}
144
-			// Run the action
145
-			$responses[] = array(
146
-				'app' => $action['app'],
147
-				'response' => call_user_func($action['action'], $parameters),
148
-				'shipped' => OC_App::isShipped($action['app']),
149
-				);
150
-		}
151
-		$response = self::mergeResponses($responses);
152
-		$format = self::requestedFormat();
153
-		if (self::$logoutRequired) {
154
-			\OC::$server->getUserSession()->logout();
155
-		}
156
-
157
-		self::respond($response, $format);
158
-	}
159
-
160
-	/**
161
-	 * merge the returned result objects into one response
162
-	 * @param array $responses
163
-	 * @return OC_OCS_Result
164
-	 */
165
-	public static function mergeResponses($responses) {
166
-		// Sort into shipped and third-party
167
-		$shipped = array(
168
-			'succeeded' => array(),
169
-			'failed' => array(),
170
-			);
171
-		$thirdparty = array(
172
-			'succeeded' => array(),
173
-			'failed' => array(),
174
-			);
175
-
176
-		foreach($responses as $response) {
177
-			if($response['shipped'] || ($response['app'] === 'core')) {
178
-				if($response['response']->succeeded()) {
179
-					$shipped['succeeded'][$response['app']] = $response;
180
-				} else {
181
-					$shipped['failed'][$response['app']] = $response;
182
-				}
183
-			} else {
184
-				if($response['response']->succeeded()) {
185
-					$thirdparty['succeeded'][$response['app']] = $response;
186
-				} else {
187
-					$thirdparty['failed'][$response['app']] = $response;
188
-				}
189
-			}
190
-		}
191
-
192
-		// Remove any error responses if there is one shipped response that succeeded
193
-		if(!empty($shipped['failed'])) {
194
-			// Which shipped response do we use if they all failed?
195
-			// They may have failed for different reasons (different status codes)
196
-			// Which response code should we return?
197
-			// Maybe any that are not \OCP\API::RESPOND_SERVER_ERROR
198
-			// Merge failed responses if more than one
199
-			$data = array();
200
-			foreach($shipped['failed'] as $failure) {
201
-				$data = array_merge_recursive($data, $failure['response']->getData());
202
-			}
203
-			$picked = reset($shipped['failed']);
204
-			$code = $picked['response']->getStatusCode();
205
-			$meta = $picked['response']->getMeta();
206
-			$headers = $picked['response']->getHeaders();
207
-			$response = new OC_OCS_Result($data, $code, $meta['message'], $headers);
208
-			return $response;
209
-		} elseif(!empty($shipped['succeeded'])) {
210
-			$responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
211
-		} elseif(!empty($thirdparty['failed'])) {
212
-			// Merge failed responses if more than one
213
-			$data = array();
214
-			foreach($thirdparty['failed'] as $failure) {
215
-				$data = array_merge_recursive($data, $failure['response']->getData());
216
-			}
217
-			$picked = reset($thirdparty['failed']);
218
-			$code = $picked['response']->getStatusCode();
219
-			$meta = $picked['response']->getMeta();
220
-			$headers = $picked['response']->getHeaders();
221
-			$response = new OC_OCS_Result($data, $code, $meta['message'], $headers);
222
-			return $response;
223
-		} else {
224
-			$responses = $thirdparty['succeeded'];
225
-		}
226
-		// Merge the successful responses
227
-		$data = [];
228
-		$codes = [];
229
-		$header = [];
230
-
231
-		foreach($responses as $response) {
232
-			if($response['shipped']) {
233
-				$data = array_merge_recursive($response['response']->getData(), $data);
234
-			} else {
235
-				$data = array_merge_recursive($data, $response['response']->getData());
236
-			}
237
-			$header = array_merge_recursive($header, $response['response']->getHeaders());
238
-			$codes[] = ['code' => $response['response']->getStatusCode(),
239
-				'meta' => $response['response']->getMeta()];
240
-		}
241
-
242
-		// Use any non 100 status codes
243
-		$statusCode = 100;
244
-		$statusMessage = null;
245
-		foreach($codes as $code) {
246
-			if($code['code'] != 100) {
247
-				$statusCode = $code['code'];
248
-				$statusMessage = $code['meta']['message'];
249
-				break;
250
-			}
251
-		}
252
-
253
-		return new OC_OCS_Result($data, $statusCode, $statusMessage, $header);
254
-	}
255
-
256
-	/**
257
-	 * authenticate the api call
258
-	 * @param array $action the action details as supplied to OC_API::register()
259
-	 * @return bool
260
-	 */
261
-	private static function isAuthorised($action) {
262
-		$level = $action['authlevel'];
263
-		switch($level) {
264
-			case API::GUEST_AUTH:
265
-				// Anyone can access
266
-				return true;
267
-			case API::USER_AUTH:
268
-				// User required
269
-				return self::loginUser();
270
-			case API::SUBADMIN_AUTH:
271
-				// Check for subadmin
272
-				$user = self::loginUser();
273
-				if(!$user) {
274
-					return false;
275
-				} else {
276
-					$userObject = \OC::$server->getUserSession()->getUser();
277
-					if($userObject === null) {
278
-						return false;
279
-					}
280
-					$isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
281
-					$admin = OC_User::isAdminUser($user);
282
-					if($isSubAdmin || $admin) {
283
-						return true;
284
-					} else {
285
-						return false;
286
-					}
287
-				}
288
-			case API::ADMIN_AUTH:
289
-				// Check for admin
290
-				$user = self::loginUser();
291
-				if(!$user) {
292
-					return false;
293
-				} else {
294
-					return OC_User::isAdminUser($user);
295
-				}
296
-			default:
297
-				// oops looks like invalid level supplied
298
-				return false;
299
-		}
300
-	}
301
-
302
-	/**
303
-	 * http basic auth
304
-	 * @return string|false (username, or false on failure)
305
-	 */
306
-	private static function loginUser() {
307
-		if(self::$isLoggedIn === true) {
308
-			return \OC_User::getUser();
309
-		}
310
-
311
-		// reuse existing login
312
-		$loggedIn = \OC::$server->getUserSession()->isLoggedIn();
313
-		if ($loggedIn === true) {
314
-			if (\OC::$server->getTwoFactorAuthManager()->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
315
-				// Do not allow access to OCS until the 2FA challenge was solved successfully
316
-				return false;
317
-			}
318
-			$ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false;
319
-			if ($ocsApiRequest) {
320
-
321
-				// initialize the user's filesystem
322
-				\OC_Util::setupFS(\OC_User::getUser());
323
-				self::$isLoggedIn = true;
324
-
325
-				return OC_User::getUser();
326
-			}
327
-			return false;
328
-		}
329
-
330
-		// basic auth - because OC_User::login will create a new session we shall only try to login
331
-		// if user and pass are set
332
-		$userSession = \OC::$server->getUserSession();
333
-		$request = \OC::$server->getRequest();
334
-		try {
335
-			if (OC_User::handleApacheAuth()) {
336
-				self::$logoutRequired = false;
337
-			} else if ($userSession->tryTokenLogin($request)
338
-				|| $userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
339
-				self::$logoutRequired = true;
340
-			} else {
341
-				return false;
342
-			}
343
-			// initialize the user's filesystem
344
-			\OC_Util::setupFS(\OC_User::getUser());
345
-			self::$isLoggedIn = true;
346
-
347
-			return \OC_User::getUser();
348
-		} catch (\OC\User\LoginException $e) {
349
-			return false;
350
-		}
351
-	}
352
-
353
-	/**
354
-	 * respond to a call
355
-	 * @param OC_OCS_Result $result
356
-	 * @param string $format the format xml|json
357
-	 */
358
-	public static function respond($result, $format='xml') {
359
-		$request = \OC::$server->getRequest();
360
-
361
-		// Send 401 headers if unauthorised
362
-		if($result->getStatusCode() === API::RESPOND_UNAUTHORISED) {
363
-			// If request comes from JS return dummy auth request
364
-			if($request->getHeader('X-Requested-With') === 'XMLHttpRequest') {
365
-				header('WWW-Authenticate: DummyBasic realm="Authorisation Required"');
366
-			} else {
367
-				header('WWW-Authenticate: Basic realm="Authorisation Required"');
368
-			}
369
-			header('HTTP/1.0 401 Unauthorized');
370
-		}
371
-
372
-		foreach($result->getHeaders() as $name => $value) {
373
-			header($name . ': ' . $value);
374
-		}
375
-
376
-		$meta = $result->getMeta();
377
-		$data = $result->getData();
378
-		if (self::isV2($request)) {
379
-			$statusCode = self::mapStatusCodes($result->getStatusCode());
380
-			if (!is_null($statusCode)) {
381
-				$meta['statuscode'] = $statusCode;
382
-				OC_Response::setStatus($statusCode);
383
-			}
384
-		}
385
-
386
-		self::setContentType($format);
387
-		$body = self::renderResult($format, $meta, $data);
388
-		echo $body;
389
-	}
390
-
391
-	/**
392
-	 * @param XMLWriter $writer
393
-	 */
394
-	private static function toXML($array, $writer) {
395
-		foreach($array as $k => $v) {
396
-			if ($k[0] === '@') {
397
-				$writer->writeAttribute(substr($k, 1), $v);
398
-				continue;
399
-			} else if (is_numeric($k)) {
400
-				$k = 'element';
401
-			}
402
-			if(is_array($v)) {
403
-				$writer->startElement($k);
404
-				self::toXML($v, $writer);
405
-				$writer->endElement();
406
-			} else {
407
-				$writer->writeElement($k, $v);
408
-			}
409
-		}
410
-	}
411
-
412
-	/**
413
-	 * @return string
414
-	 */
415
-	public static function requestedFormat() {
416
-		$formats = array('json', 'xml');
417
-
418
-		$format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml';
419
-		return $format;
420
-	}
421
-
422
-	/**
423
-	 * Based on the requested format the response content type is set
424
-	 * @param string $format
425
-	 */
426
-	public static function setContentType($format = null) {
427
-		$format = is_null($format) ? self::requestedFormat() : $format;
428
-		if ($format === 'xml') {
429
-			header('Content-type: text/xml; charset=UTF-8');
430
-			return;
431
-		}
432
-
433
-		if ($format === 'json') {
434
-			header('Content-Type: application/json; charset=utf-8');
435
-			return;
436
-		}
437
-
438
-		header('Content-Type: application/octet-stream; charset=utf-8');
439
-	}
440
-
441
-	/**
442
-	 * @param \OCP\IRequest $request
443
-	 * @return bool
444
-	 */
445
-	protected static function isV2(\OCP\IRequest $request) {
446
-		$script = $request->getScriptName();
447
-
448
-		return substr($script, -11) === '/ocs/v2.php';
449
-	}
450
-
451
-	/**
452
-	 * @param integer $sc
453
-	 * @return int
454
-	 */
455
-	public static function mapStatusCodes($sc) {
456
-		switch ($sc) {
457
-			case API::RESPOND_NOT_FOUND:
458
-				return Http::STATUS_NOT_FOUND;
459
-			case API::RESPOND_SERVER_ERROR:
460
-				return Http::STATUS_INTERNAL_SERVER_ERROR;
461
-			case API::RESPOND_UNKNOWN_ERROR:
462
-				return Http::STATUS_INTERNAL_SERVER_ERROR;
463
-			case API::RESPOND_UNAUTHORISED:
464
-				// already handled for v1
465
-				return null;
466
-			case 100:
467
-				return Http::STATUS_OK;
468
-		}
469
-		// any 2xx, 4xx and 5xx will be used as is
470
-		if ($sc >= 200 && $sc < 600) {
471
-			return $sc;
472
-		}
473
-
474
-		return Http::STATUS_BAD_REQUEST;
475
-	}
476
-
477
-	/**
478
-	 * @param string $format
479
-	 * @return string
480
-	 */
481
-	public static function renderResult($format, $meta, $data) {
482
-		$response = array(
483
-			'ocs' => array(
484
-				'meta' => $meta,
485
-				'data' => $data,
486
-			),
487
-		);
488
-		if ($format == 'json') {
489
-			return OC_JSON::encode($response);
490
-		}
491
-
492
-		$writer = new XMLWriter();
493
-		$writer->openMemory();
494
-		$writer->setIndent(true);
495
-		$writer->startDocument();
496
-		self::toXML($response, $writer);
497
-		$writer->endDocument();
498
-		return $writer->outputMemory(true);
499
-	}
40
+    /**
41
+     * API authentication levels
42
+     */
43
+
44
+    /** @deprecated Use \OCP\API::GUEST_AUTH instead */
45
+    const GUEST_AUTH = 0;
46
+
47
+    /** @deprecated Use \OCP\API::USER_AUTH instead */
48
+    const USER_AUTH = 1;
49
+
50
+    /** @deprecated Use \OCP\API::SUBADMIN_AUTH instead */
51
+    const SUBADMIN_AUTH = 2;
52
+
53
+    /** @deprecated Use \OCP\API::ADMIN_AUTH instead */
54
+    const ADMIN_AUTH = 3;
55
+
56
+    /**
57
+     * API Response Codes
58
+     */
59
+
60
+    /** @deprecated Use \OCP\API::RESPOND_UNAUTHORISED instead */
61
+    const RESPOND_UNAUTHORISED = 997;
62
+
63
+    /** @deprecated Use \OCP\API::RESPOND_SERVER_ERROR instead */
64
+    const RESPOND_SERVER_ERROR = 996;
65
+
66
+    /** @deprecated Use \OCP\API::RESPOND_NOT_FOUND instead */
67
+    const RESPOND_NOT_FOUND = 998;
68
+
69
+    /** @deprecated Use \OCP\API::RESPOND_UNKNOWN_ERROR instead */
70
+    const RESPOND_UNKNOWN_ERROR = 999;
71
+
72
+    /**
73
+     * api actions
74
+     */
75
+    protected static $actions = array();
76
+    private static $logoutRequired = false;
77
+    private static $isLoggedIn = false;
78
+
79
+    /**
80
+     * registers an api call
81
+     * @param string $method the http method
82
+     * @param string $url the url to match
83
+     * @param callable $action the function to run
84
+     * @param string $app the id of the app registering the call
85
+     * @param int $authLevel the level of authentication required for the call
86
+     * @param array $defaults
87
+     * @param array $requirements
88
+     */
89
+    public static function register($method, $url, $action, $app,
90
+                $authLevel = API::USER_AUTH,
91
+                $defaults = array(),
92
+                $requirements = array()) {
93
+        $name = strtolower($method).$url;
94
+        $name = str_replace(array('/', '{', '}'), '_', $name);
95
+        if(!isset(self::$actions[$name])) {
96
+            $oldCollection = OC::$server->getRouter()->getCurrentCollection();
97
+            OC::$server->getRouter()->useCollection('ocs');
98
+            OC::$server->getRouter()->create($name, $url)
99
+                ->method($method)
100
+                ->defaults($defaults)
101
+                ->requirements($requirements)
102
+                ->action('OC_API', 'call');
103
+            self::$actions[$name] = array();
104
+            OC::$server->getRouter()->useCollection($oldCollection);
105
+        }
106
+        self::$actions[$name][] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel);
107
+    }
108
+
109
+    /**
110
+     * handles an api call
111
+     * @param array $parameters
112
+     */
113
+    public static function call($parameters) {
114
+        $request = \OC::$server->getRequest();
115
+        $method = $request->getMethod();
116
+
117
+        // Prepare the request variables
118
+        if($method === 'PUT') {
119
+            $parameters['_put'] = $request->getParams();
120
+        } else if($method === 'DELETE') {
121
+            $parameters['_delete'] = $request->getParams();
122
+        }
123
+        $name = $parameters['_route'];
124
+        // Foreach registered action
125
+        $responses = array();
126
+        foreach(self::$actions[$name] as $action) {
127
+            // Check authentication and availability
128
+            if(!self::isAuthorised($action)) {
129
+                $responses[] = array(
130
+                    'app' => $action['app'],
131
+                    'response' => new OC_OCS_Result(null, API::RESPOND_UNAUTHORISED, 'Unauthorised'),
132
+                    'shipped' => OC_App::isShipped($action['app']),
133
+                    );
134
+                continue;
135
+            }
136
+            if(!is_callable($action['action'])) {
137
+                $responses[] = array(
138
+                    'app' => $action['app'],
139
+                    'response' => new OC_OCS_Result(null, API::RESPOND_NOT_FOUND, 'Api method not found'),
140
+                    'shipped' => OC_App::isShipped($action['app']),
141
+                    );
142
+                continue;
143
+            }
144
+            // Run the action
145
+            $responses[] = array(
146
+                'app' => $action['app'],
147
+                'response' => call_user_func($action['action'], $parameters),
148
+                'shipped' => OC_App::isShipped($action['app']),
149
+                );
150
+        }
151
+        $response = self::mergeResponses($responses);
152
+        $format = self::requestedFormat();
153
+        if (self::$logoutRequired) {
154
+            \OC::$server->getUserSession()->logout();
155
+        }
156
+
157
+        self::respond($response, $format);
158
+    }
159
+
160
+    /**
161
+     * merge the returned result objects into one response
162
+     * @param array $responses
163
+     * @return OC_OCS_Result
164
+     */
165
+    public static function mergeResponses($responses) {
166
+        // Sort into shipped and third-party
167
+        $shipped = array(
168
+            'succeeded' => array(),
169
+            'failed' => array(),
170
+            );
171
+        $thirdparty = array(
172
+            'succeeded' => array(),
173
+            'failed' => array(),
174
+            );
175
+
176
+        foreach($responses as $response) {
177
+            if($response['shipped'] || ($response['app'] === 'core')) {
178
+                if($response['response']->succeeded()) {
179
+                    $shipped['succeeded'][$response['app']] = $response;
180
+                } else {
181
+                    $shipped['failed'][$response['app']] = $response;
182
+                }
183
+            } else {
184
+                if($response['response']->succeeded()) {
185
+                    $thirdparty['succeeded'][$response['app']] = $response;
186
+                } else {
187
+                    $thirdparty['failed'][$response['app']] = $response;
188
+                }
189
+            }
190
+        }
191
+
192
+        // Remove any error responses if there is one shipped response that succeeded
193
+        if(!empty($shipped['failed'])) {
194
+            // Which shipped response do we use if they all failed?
195
+            // They may have failed for different reasons (different status codes)
196
+            // Which response code should we return?
197
+            // Maybe any that are not \OCP\API::RESPOND_SERVER_ERROR
198
+            // Merge failed responses if more than one
199
+            $data = array();
200
+            foreach($shipped['failed'] as $failure) {
201
+                $data = array_merge_recursive($data, $failure['response']->getData());
202
+            }
203
+            $picked = reset($shipped['failed']);
204
+            $code = $picked['response']->getStatusCode();
205
+            $meta = $picked['response']->getMeta();
206
+            $headers = $picked['response']->getHeaders();
207
+            $response = new OC_OCS_Result($data, $code, $meta['message'], $headers);
208
+            return $response;
209
+        } elseif(!empty($shipped['succeeded'])) {
210
+            $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
211
+        } elseif(!empty($thirdparty['failed'])) {
212
+            // Merge failed responses if more than one
213
+            $data = array();
214
+            foreach($thirdparty['failed'] as $failure) {
215
+                $data = array_merge_recursive($data, $failure['response']->getData());
216
+            }
217
+            $picked = reset($thirdparty['failed']);
218
+            $code = $picked['response']->getStatusCode();
219
+            $meta = $picked['response']->getMeta();
220
+            $headers = $picked['response']->getHeaders();
221
+            $response = new OC_OCS_Result($data, $code, $meta['message'], $headers);
222
+            return $response;
223
+        } else {
224
+            $responses = $thirdparty['succeeded'];
225
+        }
226
+        // Merge the successful responses
227
+        $data = [];
228
+        $codes = [];
229
+        $header = [];
230
+
231
+        foreach($responses as $response) {
232
+            if($response['shipped']) {
233
+                $data = array_merge_recursive($response['response']->getData(), $data);
234
+            } else {
235
+                $data = array_merge_recursive($data, $response['response']->getData());
236
+            }
237
+            $header = array_merge_recursive($header, $response['response']->getHeaders());
238
+            $codes[] = ['code' => $response['response']->getStatusCode(),
239
+                'meta' => $response['response']->getMeta()];
240
+        }
241
+
242
+        // Use any non 100 status codes
243
+        $statusCode = 100;
244
+        $statusMessage = null;
245
+        foreach($codes as $code) {
246
+            if($code['code'] != 100) {
247
+                $statusCode = $code['code'];
248
+                $statusMessage = $code['meta']['message'];
249
+                break;
250
+            }
251
+        }
252
+
253
+        return new OC_OCS_Result($data, $statusCode, $statusMessage, $header);
254
+    }
255
+
256
+    /**
257
+     * authenticate the api call
258
+     * @param array $action the action details as supplied to OC_API::register()
259
+     * @return bool
260
+     */
261
+    private static function isAuthorised($action) {
262
+        $level = $action['authlevel'];
263
+        switch($level) {
264
+            case API::GUEST_AUTH:
265
+                // Anyone can access
266
+                return true;
267
+            case API::USER_AUTH:
268
+                // User required
269
+                return self::loginUser();
270
+            case API::SUBADMIN_AUTH:
271
+                // Check for subadmin
272
+                $user = self::loginUser();
273
+                if(!$user) {
274
+                    return false;
275
+                } else {
276
+                    $userObject = \OC::$server->getUserSession()->getUser();
277
+                    if($userObject === null) {
278
+                        return false;
279
+                    }
280
+                    $isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
281
+                    $admin = OC_User::isAdminUser($user);
282
+                    if($isSubAdmin || $admin) {
283
+                        return true;
284
+                    } else {
285
+                        return false;
286
+                    }
287
+                }
288
+            case API::ADMIN_AUTH:
289
+                // Check for admin
290
+                $user = self::loginUser();
291
+                if(!$user) {
292
+                    return false;
293
+                } else {
294
+                    return OC_User::isAdminUser($user);
295
+                }
296
+            default:
297
+                // oops looks like invalid level supplied
298
+                return false;
299
+        }
300
+    }
301
+
302
+    /**
303
+     * http basic auth
304
+     * @return string|false (username, or false on failure)
305
+     */
306
+    private static function loginUser() {
307
+        if(self::$isLoggedIn === true) {
308
+            return \OC_User::getUser();
309
+        }
310
+
311
+        // reuse existing login
312
+        $loggedIn = \OC::$server->getUserSession()->isLoggedIn();
313
+        if ($loggedIn === true) {
314
+            if (\OC::$server->getTwoFactorAuthManager()->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
315
+                // Do not allow access to OCS until the 2FA challenge was solved successfully
316
+                return false;
317
+            }
318
+            $ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false;
319
+            if ($ocsApiRequest) {
320
+
321
+                // initialize the user's filesystem
322
+                \OC_Util::setupFS(\OC_User::getUser());
323
+                self::$isLoggedIn = true;
324
+
325
+                return OC_User::getUser();
326
+            }
327
+            return false;
328
+        }
329
+
330
+        // basic auth - because OC_User::login will create a new session we shall only try to login
331
+        // if user and pass are set
332
+        $userSession = \OC::$server->getUserSession();
333
+        $request = \OC::$server->getRequest();
334
+        try {
335
+            if (OC_User::handleApacheAuth()) {
336
+                self::$logoutRequired = false;
337
+            } else if ($userSession->tryTokenLogin($request)
338
+                || $userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
339
+                self::$logoutRequired = true;
340
+            } else {
341
+                return false;
342
+            }
343
+            // initialize the user's filesystem
344
+            \OC_Util::setupFS(\OC_User::getUser());
345
+            self::$isLoggedIn = true;
346
+
347
+            return \OC_User::getUser();
348
+        } catch (\OC\User\LoginException $e) {
349
+            return false;
350
+        }
351
+    }
352
+
353
+    /**
354
+     * respond to a call
355
+     * @param OC_OCS_Result $result
356
+     * @param string $format the format xml|json
357
+     */
358
+    public static function respond($result, $format='xml') {
359
+        $request = \OC::$server->getRequest();
360
+
361
+        // Send 401 headers if unauthorised
362
+        if($result->getStatusCode() === API::RESPOND_UNAUTHORISED) {
363
+            // If request comes from JS return dummy auth request
364
+            if($request->getHeader('X-Requested-With') === 'XMLHttpRequest') {
365
+                header('WWW-Authenticate: DummyBasic realm="Authorisation Required"');
366
+            } else {
367
+                header('WWW-Authenticate: Basic realm="Authorisation Required"');
368
+            }
369
+            header('HTTP/1.0 401 Unauthorized');
370
+        }
371
+
372
+        foreach($result->getHeaders() as $name => $value) {
373
+            header($name . ': ' . $value);
374
+        }
375
+
376
+        $meta = $result->getMeta();
377
+        $data = $result->getData();
378
+        if (self::isV2($request)) {
379
+            $statusCode = self::mapStatusCodes($result->getStatusCode());
380
+            if (!is_null($statusCode)) {
381
+                $meta['statuscode'] = $statusCode;
382
+                OC_Response::setStatus($statusCode);
383
+            }
384
+        }
385
+
386
+        self::setContentType($format);
387
+        $body = self::renderResult($format, $meta, $data);
388
+        echo $body;
389
+    }
390
+
391
+    /**
392
+     * @param XMLWriter $writer
393
+     */
394
+    private static function toXML($array, $writer) {
395
+        foreach($array as $k => $v) {
396
+            if ($k[0] === '@') {
397
+                $writer->writeAttribute(substr($k, 1), $v);
398
+                continue;
399
+            } else if (is_numeric($k)) {
400
+                $k = 'element';
401
+            }
402
+            if(is_array($v)) {
403
+                $writer->startElement($k);
404
+                self::toXML($v, $writer);
405
+                $writer->endElement();
406
+            } else {
407
+                $writer->writeElement($k, $v);
408
+            }
409
+        }
410
+    }
411
+
412
+    /**
413
+     * @return string
414
+     */
415
+    public static function requestedFormat() {
416
+        $formats = array('json', 'xml');
417
+
418
+        $format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml';
419
+        return $format;
420
+    }
421
+
422
+    /**
423
+     * Based on the requested format the response content type is set
424
+     * @param string $format
425
+     */
426
+    public static function setContentType($format = null) {
427
+        $format = is_null($format) ? self::requestedFormat() : $format;
428
+        if ($format === 'xml') {
429
+            header('Content-type: text/xml; charset=UTF-8');
430
+            return;
431
+        }
432
+
433
+        if ($format === 'json') {
434
+            header('Content-Type: application/json; charset=utf-8');
435
+            return;
436
+        }
437
+
438
+        header('Content-Type: application/octet-stream; charset=utf-8');
439
+    }
440
+
441
+    /**
442
+     * @param \OCP\IRequest $request
443
+     * @return bool
444
+     */
445
+    protected static function isV2(\OCP\IRequest $request) {
446
+        $script = $request->getScriptName();
447
+
448
+        return substr($script, -11) === '/ocs/v2.php';
449
+    }
450
+
451
+    /**
452
+     * @param integer $sc
453
+     * @return int
454
+     */
455
+    public static function mapStatusCodes($sc) {
456
+        switch ($sc) {
457
+            case API::RESPOND_NOT_FOUND:
458
+                return Http::STATUS_NOT_FOUND;
459
+            case API::RESPOND_SERVER_ERROR:
460
+                return Http::STATUS_INTERNAL_SERVER_ERROR;
461
+            case API::RESPOND_UNKNOWN_ERROR:
462
+                return Http::STATUS_INTERNAL_SERVER_ERROR;
463
+            case API::RESPOND_UNAUTHORISED:
464
+                // already handled for v1
465
+                return null;
466
+            case 100:
467
+                return Http::STATUS_OK;
468
+        }
469
+        // any 2xx, 4xx and 5xx will be used as is
470
+        if ($sc >= 200 && $sc < 600) {
471
+            return $sc;
472
+        }
473
+
474
+        return Http::STATUS_BAD_REQUEST;
475
+    }
476
+
477
+    /**
478
+     * @param string $format
479
+     * @return string
480
+     */
481
+    public static function renderResult($format, $meta, $data) {
482
+        $response = array(
483
+            'ocs' => array(
484
+                'meta' => $meta,
485
+                'data' => $data,
486
+            ),
487
+        );
488
+        if ($format == 'json') {
489
+            return OC_JSON::encode($response);
490
+        }
491
+
492
+        $writer = new XMLWriter();
493
+        $writer->openMemory();
494
+        $writer->setIndent(true);
495
+        $writer->startDocument();
496
+        self::toXML($response, $writer);
497
+        $writer->endDocument();
498
+        return $writer->outputMemory(true);
499
+    }
500 500
 }
Please login to merge, or discard this patch.